]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
ksmbd: fix translation in acl entries
authorChristian Brauner <christian.brauner@ubuntu.com>
Mon, 23 Aug 2021 15:13:51 +0000 (17:13 +0200)
committerSteve French <stfrench@microsoft.com>
Sat, 4 Sep 2021 04:29:44 +0000 (23:29 -0500)
The ksmbd server performs translation of posix acls to smb acls.
Currently the translation is wrong since the idmapping of the mount is
used to map the ids into raw userspace ids but what is relevant is the
user namespace of ksmbd itself. The user namespace of ksmbd itself which
is the initial user namespace. The operation is similar to asking "What
*ids would a userspace process see given that k*id in the relevant user
namespace?". Before the final translation we need to apply the idmapping
of the mount in case any is used. Add two simple helpers for ksmbd.

Cc: Steve French <stfrench@microsoft.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Namjae Jeon <namjae.jeon@samsung.com>
Cc: Hyunchul Lee <hyc.lee@gmail.com>
Cc: Sergey Senozhatsky <senozhatsky@chromium.org>
Cc: linux-cifs@vger.kernel.org
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/ksmbd/smbacl.c
fs/ksmbd/smbacl.h
fs/ksmbd/vfs.c

index a7025b31d2f2cf1db8f2f9c1e508ed4c828a6543..3307ca776eb19f09a236ee36db180bd4a4468b69 100644 (file)
@@ -587,14 +587,14 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
                        uid_t uid;
                        unsigned int sid_type = SIDOWNER;
 
-                       uid = from_kuid(user_ns, pace->e_uid);
+                       uid = posix_acl_uid_translate(user_ns, pace);
                        if (!uid)
                                sid_type = SIDUNIX_USER;
                        id_to_sid(uid, sid_type, sid);
                } else if (pace->e_tag == ACL_GROUP) {
                        gid_t gid;
 
-                       gid = from_kgid(user_ns, pace->e_gid);
+                       gid = posix_acl_gid_translate(user_ns, pace);
                        id_to_sid(gid, SIDUNIX_GROUP, sid);
                } else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
                        smb_copy_sid(sid, &sid_everyone);
@@ -653,12 +653,12 @@ posix_default_acl:
                if (pace->e_tag == ACL_USER) {
                        uid_t uid;
 
-                       uid = from_kuid(user_ns, pace->e_uid);
+                       uid = posix_acl_uid_translate(user_ns, pace);
                        id_to_sid(uid, SIDCREATOR_OWNER, sid);
                } else if (pace->e_tag == ACL_GROUP) {
                        gid_t gid;
 
-                       gid = from_kgid(user_ns, pace->e_gid);
+                       gid = posix_acl_gid_translate(user_ns, pace);
                        id_to_sid(gid, SIDCREATOR_GROUP, sid);
                } else {
                        kfree(sid);
@@ -1234,11 +1234,9 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
                        pa_entry = posix_acls->a_entries;
                        for (i = 0; i < posix_acls->a_count; i++, pa_entry++) {
                                if (pa_entry->e_tag == ACL_USER)
-                                       id = from_kuid(user_ns,
-                                                      pa_entry->e_uid);
+                                       id = posix_acl_uid_translate(user_ns, pa_entry);
                                else if (pa_entry->e_tag == ACL_GROUP)
-                                       id = from_kgid(user_ns,
-                                                      pa_entry->e_gid);
+                                       id = posix_acl_gid_translate(user_ns, pa_entry);
                                else
                                        continue;
 
index 940f686a1d95cebc6695f323a4c9870c55acea61..73e08cad412bd7026a7077b5c4f75cb4971b8606 100644 (file)
@@ -209,4 +209,29 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
                 bool type_check);
 void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
 void ksmbd_init_domain(u32 *sub_auth);
+
+static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,
+                                           struct posix_acl_entry *pace)
+{
+       kuid_t kuid;
+
+       /* If this is an idmapped mount, apply the idmapping. */
+       kuid = kuid_into_mnt(mnt_userns, pace->e_uid);
+
+       /* Translate the kuid into a userspace id ksmbd would see. */
+       return from_kuid(&init_user_ns, kuid);
+}
+
+static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,
+                                           struct posix_acl_entry *pace)
+{
+       kgid_t kgid;
+
+       /* If this is an idmapped mount, apply the idmapping. */
+       kgid = kgid_into_mnt(mnt_userns, pace->e_gid);
+
+       /* Translate the kgid into a userspace id ksmbd would see. */
+       return from_kgid(&init_user_ns, kgid);
+}
+
 #endif /* _SMBACL_H */
index 2bb506d1fb321adc9ba5f0b40fab2dfe93f5980f..b047f2980d96c6a32190c8822760b8e1d01fa907 100644 (file)
@@ -1390,14 +1390,14 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac
                switch (pa_entry->e_tag) {
                case ACL_USER:
                        xa_entry->type = SMB_ACL_USER;
-                       xa_entry->uid = from_kuid(user_ns, pa_entry->e_uid);
+                       xa_entry->uid = posix_acl_uid_translate(user_ns, pa_entry);
                        break;
                case ACL_USER_OBJ:
                        xa_entry->type = SMB_ACL_USER_OBJ;
                        break;
                case ACL_GROUP:
                        xa_entry->type = SMB_ACL_GROUP;
-                       xa_entry->gid = from_kgid(user_ns, pa_entry->e_gid);
+                       xa_entry->gid = posix_acl_gid_translate(user_ns, pa_entry);
                        break;
                case ACL_GROUP_OBJ:
                        xa_entry->type = SMB_ACL_GROUP_OBJ;