Skip to content

Commit

Permalink
ksmbd: test2
Browse files Browse the repository at this point in the history
Signed-off-by: Namjae Jeon <[email protected]>
  • Loading branch information
namjaejeon committed Feb 10, 2025
1 parent 87afc11 commit 21ee783
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 34 deletions.
80 changes: 48 additions & 32 deletions smbacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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);
}

Expand All @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down
5 changes: 3 additions & 2 deletions smbacl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 21ee783

Please sign in to comment.