From 21ee78323d7a1b863f4a27256c0707122edbfbcf Mon Sep 17 00:00:00 2001 From: Namjae Jeon Date: Mon, 10 Feb 2025 09:49:27 +0900 Subject: [PATCH] ksmbd: test2 Signed-off-by: Namjae Jeon --- smbacl.c | 80 +++++++++++++++++++++++++++++++++----------------------- smbacl.h | 5 ++-- 2 files changed, 51 insertions(+), 34 deletions(-) diff --git a/smbacl.c b/smbacl.c index 579e57ede..127471a97 100644 --- a/smbacl.c +++ b/smbacl.c @@ -387,7 +387,7 @@ void posix_state_to_acl(struct posix_acl_state *state, pace->e_perm = state->other.allow; } -int init_acl_state(struct posix_acl_state *state, int cnt) +int init_acl_state(struct posix_acl_state *state, u16 cnt) { int alloc; @@ -416,6 +416,37 @@ void free_acl_state(struct posix_acl_state *state) kfree(state->groups); } +static u16 dacl_validate_num_aces(u16 num_aces, char *acl_base, char *end_of_acl) +{ + struct smb_ace *ace; + unsigned int acl_size = sizeof(struct smb_acl); + u16 num = 0; + int i; + + for (i = 0; i < num_aces; ++i) { + if (end_of_acl - acl_base < acl_size) + break; + + ace = (struct smb_ace *)(acl_base + acl_size); + acl_base = (char *)ace; + acl_size = offsetof(struct smb_ace, sid) + + offsetof(struct smb_sid, sub_auth); + + if (end_of_acl - acl_base < acl_size || + ace->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || + (end_of_acl - acl_base < + acl_size + sizeof(__le32) * ace->sid.num_subauth) || + (le16_to_cpu(ace->size) < + acl_size + sizeof(__le32) * ace->sid.num_subauth)) + break; + + acl_size = le16_to_cpu(ace->size); + num++; + } + + return num; +} + #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0) static void parse_dacl(struct mnt_idmap *idmap, #else @@ -426,7 +457,7 @@ static void parse_dacl(struct user_namespace *user_ns, struct smb_fattr *fattr) { int i, ret; - int num_aces = 0; + u16 num_aces = 0; unsigned int acl_size; char *acl_base; struct smb_ace **ppace; @@ -450,16 +481,14 @@ static void parse_dacl(struct user_namespace *user_ns, ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n", le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size), - le32_to_cpu(pdacl->num_aces)); + le16_to_cpu(pdacl->num_aces)); acl_base = (char *)pdacl; acl_size = sizeof(struct smb_acl); - num_aces = le32_to_cpu(pdacl->num_aces); - if (num_aces <= 0) - return; - - if (num_aces > (le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) / sizeof(struct smb_ace *)) + num_aces = dacl_validate_num_aces(le16_to_cpu(pdacl->num_aces), + acl_base, end_of_acl); + if (!num_aces) return; ret = init_acl_state(&acl_state, num_aces); @@ -484,23 +513,10 @@ static void parse_dacl(struct user_namespace *user_ns, * user/group/other have no permissions */ for (i = 0; i < num_aces; ++i) { - if (end_of_acl - acl_base < acl_size) - break; - ppace[i] = (struct smb_ace *)(acl_base + acl_size); acl_base = (char *)ppace[i]; - acl_size = offsetof(struct smb_ace, sid) + - offsetof(struct smb_sid, sub_auth); - - if (end_of_acl - acl_base < acl_size || - ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES || - (end_of_acl - acl_base < - acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) || - (le16_to_cpu(ppace[i]->size) < - acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth)) - break; - acl_size = le16_to_cpu(ppace[i]->size); + ppace[i]->access_req = smb_map_generic_desired_access(ppace[i]->access_req); @@ -649,8 +665,8 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap, static void set_posix_acl_entries_dacl(struct user_namespace *user_ns, #endif struct smb_ace *pndace, - struct smb_fattr *fattr, u32 *num_aces, - u16 *size, u32 nt_aces_num) + struct smb_fattr *fattr, u16 *num_aces, + u16 *size, u16 nt_aces_num) { struct posix_acl_entry *pace; struct smb_sid *sid; @@ -790,7 +806,7 @@ static void set_ntacl_dacl(struct user_namespace *user_ns, struct smb_fattr *fattr) { struct smb_ace *ntace, *pndace; - int nt_num_aces = le32_to_cpu(nt_dacl->num_aces), num_aces = 0; + u16 nt_num_aces = le16_to_cpu(nt_dacl->num_aces), num_aces = 0; unsigned short size = 0; int i; @@ -821,7 +837,7 @@ static void set_ntacl_dacl(struct user_namespace *user_ns, set_posix_acl_entries_dacl(user_ns, pndace, fattr, #endif &num_aces, &size, nt_num_aces); - pndacl->num_aces = cpu_to_le32(num_aces); + pndacl->num_aces = cpu_to_le16(num_aces); pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size); } @@ -833,7 +849,7 @@ static void set_mode_dacl(struct user_namespace *user_ns, struct smb_acl *pndacl, struct smb_fattr *fattr) { struct smb_ace *pace, *pndace; - u32 num_aces = 0; + u16 num_aces = 0; u16 size = 0, ace_size = 0; uid_t uid; const struct smb_sid *sid; @@ -893,7 +909,7 @@ static void set_mode_dacl(struct user_namespace *user_ns, fattr->cf_mode, 0007); out: - pndacl->num_aces = cpu_to_le32(num_aces); + pndacl->num_aces = cpu_to_le16(num_aces); pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size); } @@ -1160,7 +1176,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset); acl_len = pntsd_size - dacloffset; - num_aces = le32_to_cpu(parent_pdacl->num_aces); + num_aces = le16_to_cpu(parent_pdacl->num_aces); pntsd_type = le16_to_cpu(parent_pntsd->type); pdacl_size = le16_to_cpu(parent_pdacl->size); @@ -1320,7 +1336,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset)); pdacl->revision = cpu_to_le16(2); pdacl->size = cpu_to_le16(sizeof(struct smb_acl) + nt_size); - pdacl->num_aces = cpu_to_le32(ace_cnt); + pdacl->num_aces = cpu_to_le16(ace_cnt); pace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); memcpy(pace, aces_base, nt_size); pntsd_size += sizeof(struct smb_acl) + nt_size; @@ -1414,7 +1430,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); aces_size = acl_size - sizeof(struct smb_acl); - for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) { + for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { if (offsetof(struct smb_ace, access_req) > aces_size) break; ace_size = le16_to_cpu(ace->size); @@ -1435,7 +1451,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path, ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl)); aces_size = acl_size - sizeof(struct smb_acl); - for (i = 0; i < le32_to_cpu(pdacl->num_aces); i++) { + for (i = 0; i < le16_to_cpu(pdacl->num_aces); i++) { if (offsetof(struct smb_ace, access_req) > aces_size) break; ace_size = le16_to_cpu(ace->size); diff --git a/smbacl.h b/smbacl.h index e486fa3dd..c698ba003 100644 --- a/smbacl.h +++ b/smbacl.h @@ -140,7 +140,8 @@ struct smb_sid { struct smb_acl { __le16 revision; /* revision level */ __le16 size; - __le32 num_aces; + __le16 num_aces; + __le16 reserved; } __packed; struct smb_ace { @@ -206,7 +207,7 @@ int build_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, #endif struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info, __u32 *secdesclen, struct smb_fattr *fattr); -int init_acl_state(struct posix_acl_state *state, int cnt); +int init_acl_state(struct posix_acl_state *state, u16 cnt); void free_acl_state(struct posix_acl_state *state); void posix_state_to_acl(struct posix_acl_state *state, struct posix_acl_entry *pace);