Five SMB server fixes, two related client fixes, and minor MAINTAINERS update
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmfJNHEACgkQiiy9cAdy T1EChgv/UKhM3QptW++f0sVL7T7rPPpX0K18B/rrXrdKedP+MBp2BpeF+2Hm/YEQ VJndiltUzmOsXnO5NCqcsczHhYtn9J6oK50kCG7L/lNs1rK7BckXbaUtMyFJ1zbi 2mjCUVJfO9bEDUfIWq27+RSoce8UDiFTqvmjJnqTU9ogL/lmRZq8TNpHdj984mCh XiqbSVWDbYwm7RAJovRp2WY8K2OqZ1FTpNmhjaPHAMWQ3r11Am125MLNackEg7SW 0Zp816G02it7NKD59V860d4BDL1Qi2WBqrH1BdYcX9cfo0vScdPV9BuCGbcfKCZ3 UHH6oJdc/kRZw8zCUHjgLZcvDJmmH5umDStfPAdCQYw9n6MoxP6gi5xldWDb9o5l 0goN3R8afn8V27N+BRKIs+gN8qqat7Pmpl62TMSRQEMCceDc5uH+r5lgFzswwNZL Yc3VJRrEZmBYlHOY3uSwoqwoM0ugB27Wo0JqdH3UKB7nY616CpdJyExaW5XgUqO5 uSekIAx6 =/wl5 -----END PGP SIGNATURE----- Merge tag 'v6.14-rc5-smb3-fixes' of git://git.samba.org/ksmbd Pull smb fixes from Steve French: "Five SMB server fixes, two related client fixes, and minor MAINTAINERS update: - Two SMB3 lock fixes fixes (including use after free and bug on fix) - Fix to race condition that can happen in processing IPC responses - Four ACL related fixes: one related to endianness of num_aces, and two related fixes to the checks for num_aces (for both client and server), and one fixing missing check for num_subauths which can cause memory corruption - And minor update to email addresses in MAINTAINERS file" * tag 'v6.14-rc5-smb3-fixes' of git://git.samba.org/ksmbd: cifs: fix incorrect validation for num_aces field of smb_acl ksmbd: fix incorrect validation for num_aces field of smb_acl smb: common: change the data type of num_aces to le16 ksmbd: fix bug on trap in smb2_lock ksmbd: fix use-after-free in smb2_lock ksmbd: fix type confusion via race condition when using ipc_msg_send_request ksmbd: fix out-of-bounds in parse_sec_desc() MAINTAINERS: update email address in cifs and ksmbd entry
This commit is contained in:
commit
1238f0af13
7 changed files with 66 additions and 37 deletions
|
@ -5775,6 +5775,7 @@ X: drivers/clk/clkdev.c
|
||||||
|
|
||||||
COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
|
COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3)
|
||||||
M: Steve French <sfrench@samba.org>
|
M: Steve French <sfrench@samba.org>
|
||||||
|
M: Steve French <smfrench@gmail.com>
|
||||||
R: Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
|
R: Paulo Alcantara <pc@manguebit.com> (DFS, global name space)
|
||||||
R: Ronnie Sahlberg <ronniesahlberg@gmail.com> (directory leases, sparse files)
|
R: Ronnie Sahlberg <ronniesahlberg@gmail.com> (directory leases, sparse files)
|
||||||
R: Shyam Prasad N <sprasad@microsoft.com> (multichannel)
|
R: Shyam Prasad N <sprasad@microsoft.com> (multichannel)
|
||||||
|
@ -12655,7 +12656,9 @@ F: tools/testing/selftests/
|
||||||
|
|
||||||
KERNEL SMB3 SERVER (KSMBD)
|
KERNEL SMB3 SERVER (KSMBD)
|
||||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||||
|
M: Namjae Jeon <linkinjeon@samba.org>
|
||||||
M: Steve French <sfrench@samba.org>
|
M: Steve French <sfrench@samba.org>
|
||||||
|
M: Steve French <smfrench@gmail.com>
|
||||||
R: Sergey Senozhatsky <senozhatsky@chromium.org>
|
R: Sergey Senozhatsky <senozhatsky@chromium.org>
|
||||||
R: Tom Talpey <tom@talpey.com>
|
R: Tom Talpey <tom@talpey.com>
|
||||||
L: linux-cifs@vger.kernel.org
|
L: linux-cifs@vger.kernel.org
|
||||||
|
|
|
@ -763,7 +763,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
||||||
struct cifs_fattr *fattr, bool mode_from_special_sid)
|
struct cifs_fattr *fattr, bool mode_from_special_sid)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int num_aces = 0;
|
u16 num_aces = 0;
|
||||||
int acl_size;
|
int acl_size;
|
||||||
char *acl_base;
|
char *acl_base;
|
||||||
struct smb_ace **ppace;
|
struct smb_ace **ppace;
|
||||||
|
@ -778,14 +778,15 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validate that we do not go past end of acl */
|
/* validate that we do not go past end of acl */
|
||||||
if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
|
if (end_of_acl < (char *)pdacl + sizeof(struct smb_acl) ||
|
||||||
|
end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
|
||||||
cifs_dbg(VFS, "ACL too small to parse DACL\n");
|
cifs_dbg(VFS, "ACL too small to parse DACL\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
|
cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
|
||||||
le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
|
le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
|
||||||
le32_to_cpu(pdacl->num_aces));
|
le16_to_cpu(pdacl->num_aces));
|
||||||
|
|
||||||
/* reset rwx permissions for user/group/other.
|
/* reset rwx permissions for user/group/other.
|
||||||
Also, if num_aces is 0 i.e. DACL has no ACEs,
|
Also, if num_aces is 0 i.e. DACL has no ACEs,
|
||||||
|
@ -795,12 +796,15 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
||||||
acl_base = (char *)pdacl;
|
acl_base = (char *)pdacl;
|
||||||
acl_size = sizeof(struct smb_acl);
|
acl_size = sizeof(struct smb_acl);
|
||||||
|
|
||||||
num_aces = le32_to_cpu(pdacl->num_aces);
|
num_aces = le16_to_cpu(pdacl->num_aces);
|
||||||
if (num_aces > 0) {
|
if (num_aces > 0) {
|
||||||
umode_t denied_mode = 0;
|
umode_t denied_mode = 0;
|
||||||
|
|
||||||
if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
|
if (num_aces > (le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) /
|
||||||
|
(offsetof(struct smb_ace, sid) +
|
||||||
|
offsetof(struct smb_sid, sub_auth) + sizeof(__le16)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *),
|
ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!ppace)
|
if (!ppace)
|
||||||
|
@ -937,12 +941,12 @@ unsigned int setup_special_user_owner_ACE(struct smb_ace *pntace)
|
||||||
static void populate_new_aces(char *nacl_base,
|
static void populate_new_aces(char *nacl_base,
|
||||||
struct smb_sid *pownersid,
|
struct smb_sid *pownersid,
|
||||||
struct smb_sid *pgrpsid,
|
struct smb_sid *pgrpsid,
|
||||||
__u64 *pnmode, u32 *pnum_aces, u16 *pnsize,
|
__u64 *pnmode, u16 *pnum_aces, u16 *pnsize,
|
||||||
bool modefromsid,
|
bool modefromsid,
|
||||||
bool posix)
|
bool posix)
|
||||||
{
|
{
|
||||||
__u64 nmode;
|
__u64 nmode;
|
||||||
u32 num_aces = 0;
|
u16 num_aces = 0;
|
||||||
u16 nsize = 0;
|
u16 nsize = 0;
|
||||||
__u64 user_mode;
|
__u64 user_mode;
|
||||||
__u64 group_mode;
|
__u64 group_mode;
|
||||||
|
@ -1050,7 +1054,7 @@ static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *p
|
||||||
u16 size = 0;
|
u16 size = 0;
|
||||||
struct smb_ace *pntace = NULL;
|
struct smb_ace *pntace = NULL;
|
||||||
char *acl_base = NULL;
|
char *acl_base = NULL;
|
||||||
u32 src_num_aces = 0;
|
u16 src_num_aces = 0;
|
||||||
u16 nsize = 0;
|
u16 nsize = 0;
|
||||||
struct smb_ace *pnntace = NULL;
|
struct smb_ace *pnntace = NULL;
|
||||||
char *nacl_base = NULL;
|
char *nacl_base = NULL;
|
||||||
|
@ -1058,7 +1062,7 @@ static __u16 replace_sids_and_copy_aces(struct smb_acl *pdacl, struct smb_acl *p
|
||||||
|
|
||||||
acl_base = (char *)pdacl;
|
acl_base = (char *)pdacl;
|
||||||
size = sizeof(struct smb_acl);
|
size = sizeof(struct smb_acl);
|
||||||
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
src_num_aces = le16_to_cpu(pdacl->num_aces);
|
||||||
|
|
||||||
nacl_base = (char *)pndacl;
|
nacl_base = (char *)pndacl;
|
||||||
nsize = sizeof(struct smb_acl);
|
nsize = sizeof(struct smb_acl);
|
||||||
|
@ -1090,11 +1094,11 @@ static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
|
||||||
u16 size = 0;
|
u16 size = 0;
|
||||||
struct smb_ace *pntace = NULL;
|
struct smb_ace *pntace = NULL;
|
||||||
char *acl_base = NULL;
|
char *acl_base = NULL;
|
||||||
u32 src_num_aces = 0;
|
u16 src_num_aces = 0;
|
||||||
u16 nsize = 0;
|
u16 nsize = 0;
|
||||||
struct smb_ace *pnntace = NULL;
|
struct smb_ace *pnntace = NULL;
|
||||||
char *nacl_base = NULL;
|
char *nacl_base = NULL;
|
||||||
u32 num_aces = 0;
|
u16 num_aces = 0;
|
||||||
bool new_aces_set = false;
|
bool new_aces_set = false;
|
||||||
|
|
||||||
/* Assuming that pndacl and pnmode are never NULL */
|
/* Assuming that pndacl and pnmode are never NULL */
|
||||||
|
@ -1112,7 +1116,7 @@ static int set_chmod_dacl(struct smb_acl *pdacl, struct smb_acl *pndacl,
|
||||||
|
|
||||||
acl_base = (char *)pdacl;
|
acl_base = (char *)pdacl;
|
||||||
size = sizeof(struct smb_acl);
|
size = sizeof(struct smb_acl);
|
||||||
src_num_aces = le32_to_cpu(pdacl->num_aces);
|
src_num_aces = le16_to_cpu(pdacl->num_aces);
|
||||||
|
|
||||||
/* Retain old ACEs which we can retain */
|
/* Retain old ACEs which we can retain */
|
||||||
for (i = 0; i < src_num_aces; ++i) {
|
for (i = 0; i < src_num_aces; ++i) {
|
||||||
|
@ -1158,7 +1162,7 @@ next_ace:
|
||||||
}
|
}
|
||||||
|
|
||||||
finalize_dacl:
|
finalize_dacl:
|
||||||
pndacl->num_aces = cpu_to_le32(num_aces);
|
pndacl->num_aces = cpu_to_le16(num_aces);
|
||||||
pndacl->size = cpu_to_le16(nsize);
|
pndacl->size = cpu_to_le16(nsize);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1293,7 +1297,7 @@ static int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *pnntsd,
|
||||||
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
|
dacloffset ? dacl_ptr->revision : cpu_to_le16(ACL_REVISION);
|
||||||
|
|
||||||
ndacl_ptr->size = cpu_to_le16(0);
|
ndacl_ptr->size = cpu_to_le16(0);
|
||||||
ndacl_ptr->num_aces = cpu_to_le32(0);
|
ndacl_ptr->num_aces = cpu_to_le16(0);
|
||||||
|
|
||||||
rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr,
|
rc = set_chmod_dacl(dacl_ptr, ndacl_ptr, owner_sid_ptr, group_sid_ptr,
|
||||||
pnmode, mode_from_sid, posix);
|
pnmode, mode_from_sid, posix);
|
||||||
|
@ -1653,7 +1657,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 *pnmode,
|
||||||
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
|
dacl_ptr = (struct smb_acl *)((char *)pntsd + dacloffset);
|
||||||
if (mode_from_sid)
|
if (mode_from_sid)
|
||||||
nsecdesclen +=
|
nsecdesclen +=
|
||||||
le32_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);
|
le16_to_cpu(dacl_ptr->num_aces) * sizeof(struct smb_ace);
|
||||||
else /* cifsacl */
|
else /* cifsacl */
|
||||||
nsecdesclen += le16_to_cpu(dacl_ptr->size);
|
nsecdesclen += le16_to_cpu(dacl_ptr->size);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,8 @@ struct smb_sid {
|
||||||
struct smb_acl {
|
struct smb_acl {
|
||||||
__le16 revision; /* revision level */
|
__le16 revision; /* revision level */
|
||||||
__le16 size;
|
__le16 size;
|
||||||
__le32 num_aces;
|
__le16 num_aces;
|
||||||
|
__le16 reserved;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct smb_ace {
|
struct smb_ace {
|
||||||
|
|
|
@ -7458,17 +7458,17 @@ out_check_cl:
|
||||||
}
|
}
|
||||||
|
|
||||||
no_check_cl:
|
no_check_cl:
|
||||||
|
flock = smb_lock->fl;
|
||||||
|
list_del(&smb_lock->llist);
|
||||||
|
|
||||||
if (smb_lock->zero_len) {
|
if (smb_lock->zero_len) {
|
||||||
err = 0;
|
err = 0;
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
|
|
||||||
flock = smb_lock->fl;
|
|
||||||
list_del(&smb_lock->llist);
|
|
||||||
retry:
|
retry:
|
||||||
rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
|
rc = vfs_lock_file(filp, smb_lock->cmd, flock, NULL);
|
||||||
skip:
|
skip:
|
||||||
if (flags & SMB2_LOCKFLAG_UNLOCK) {
|
if (smb_lock->flags & SMB2_LOCKFLAG_UNLOCK) {
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
ksmbd_debug(SMB, "File unlocked\n");
|
ksmbd_debug(SMB, "File unlocked\n");
|
||||||
} else if (rc == -ENOENT) {
|
} else if (rc == -ENOENT) {
|
||||||
|
|
|
@ -333,7 +333,7 @@ void posix_state_to_acl(struct posix_acl_state *state,
|
||||||
pace->e_perm = state->other.allow;
|
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;
|
int alloc;
|
||||||
|
|
||||||
|
@ -368,7 +368,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
|
||||||
struct smb_fattr *fattr)
|
struct smb_fattr *fattr)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
int num_aces = 0;
|
u16 num_aces = 0;
|
||||||
unsigned int acl_size;
|
unsigned int acl_size;
|
||||||
char *acl_base;
|
char *acl_base;
|
||||||
struct smb_ace **ppace;
|
struct smb_ace **ppace;
|
||||||
|
@ -389,16 +389,18 @@ static void parse_dacl(struct mnt_idmap *idmap,
|
||||||
|
|
||||||
ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n",
|
ksmbd_debug(SMB, "DACL revision %d size %d num aces %d\n",
|
||||||
le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
|
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_base = (char *)pdacl;
|
||||||
acl_size = sizeof(struct smb_acl);
|
acl_size = sizeof(struct smb_acl);
|
||||||
|
|
||||||
num_aces = le32_to_cpu(pdacl->num_aces);
|
num_aces = le16_to_cpu(pdacl->num_aces);
|
||||||
if (num_aces <= 0)
|
if (num_aces <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (num_aces > ULONG_MAX / sizeof(struct smb_ace *))
|
if (num_aces > (le16_to_cpu(pdacl->size) - sizeof(struct smb_acl)) /
|
||||||
|
(offsetof(struct smb_ace, sid) +
|
||||||
|
offsetof(struct smb_sid, sub_auth) + sizeof(__le16)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ret = init_acl_state(&acl_state, num_aces);
|
ret = init_acl_state(&acl_state, num_aces);
|
||||||
|
@ -432,6 +434,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
|
||||||
offsetof(struct smb_sid, sub_auth);
|
offsetof(struct smb_sid, sub_auth);
|
||||||
|
|
||||||
if (end_of_acl - acl_base < acl_size ||
|
if (end_of_acl - acl_base < acl_size ||
|
||||||
|
ppace[i]->sid.num_subauth == 0 ||
|
||||||
ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
|
ppace[i]->sid.num_subauth > SID_MAX_SUB_AUTHORITIES ||
|
||||||
(end_of_acl - acl_base <
|
(end_of_acl - acl_base <
|
||||||
acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
|
acl_size + sizeof(__le32) * ppace[i]->sid.num_subauth) ||
|
||||||
|
@ -580,7 +583,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
|
||||||
|
|
||||||
static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
|
static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
|
||||||
struct smb_ace *pndace,
|
struct smb_ace *pndace,
|
||||||
struct smb_fattr *fattr, u32 *num_aces,
|
struct smb_fattr *fattr, u16 *num_aces,
|
||||||
u16 *size, u32 nt_aces_num)
|
u16 *size, u32 nt_aces_num)
|
||||||
{
|
{
|
||||||
struct posix_acl_entry *pace;
|
struct posix_acl_entry *pace;
|
||||||
|
@ -701,7 +704,7 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
|
||||||
struct smb_fattr *fattr)
|
struct smb_fattr *fattr)
|
||||||
{
|
{
|
||||||
struct smb_ace *ntace, *pndace;
|
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;
|
unsigned short size = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -728,7 +731,7 @@ static void set_ntacl_dacl(struct mnt_idmap *idmap,
|
||||||
|
|
||||||
set_posix_acl_entries_dacl(idmap, pndace, fattr,
|
set_posix_acl_entries_dacl(idmap, pndace, fattr,
|
||||||
&num_aces, &size, nt_num_aces);
|
&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);
|
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,7 +739,7 @@ static void set_mode_dacl(struct mnt_idmap *idmap,
|
||||||
struct smb_acl *pndacl, struct smb_fattr *fattr)
|
struct smb_acl *pndacl, struct smb_fattr *fattr)
|
||||||
{
|
{
|
||||||
struct smb_ace *pace, *pndace;
|
struct smb_ace *pace, *pndace;
|
||||||
u32 num_aces = 0;
|
u16 num_aces = 0;
|
||||||
u16 size = 0, ace_size = 0;
|
u16 size = 0, ace_size = 0;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
const struct smb_sid *sid;
|
const struct smb_sid *sid;
|
||||||
|
@ -792,7 +795,7 @@ static void set_mode_dacl(struct mnt_idmap *idmap,
|
||||||
fattr->cf_mode, 0007);
|
fattr->cf_mode, 0007);
|
||||||
|
|
||||||
out:
|
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);
|
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,6 +810,13 @@ static int parse_sid(struct smb_sid *psid, char *end_of_acl)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!psid->num_subauth)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (psid->num_subauth > SID_MAX_SUB_AUTHORITIES ||
|
||||||
|
end_of_acl < (char *)psid + 8 + sizeof(__le32) * psid->num_subauth)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,6 +858,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
|
||||||
pntsd->type = cpu_to_le16(DACL_PRESENT);
|
pntsd->type = cpu_to_le16(DACL_PRESENT);
|
||||||
|
|
||||||
if (pntsd->osidoffset) {
|
if (pntsd->osidoffset) {
|
||||||
|
if (le32_to_cpu(pntsd->osidoffset) < sizeof(struct smb_ntsd))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
rc = parse_sid(owner_sid_ptr, end_of_acl);
|
rc = parse_sid(owner_sid_ptr, end_of_acl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
|
pr_err("%s: Error %d parsing Owner SID\n", __func__, rc);
|
||||||
|
@ -863,6 +876,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pntsd->gsidoffset) {
|
if (pntsd->gsidoffset) {
|
||||||
|
if (le32_to_cpu(pntsd->gsidoffset) < sizeof(struct smb_ntsd))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
rc = parse_sid(group_sid_ptr, end_of_acl);
|
rc = parse_sid(group_sid_ptr, end_of_acl);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: Error %d mapping Owner SID to gid\n",
|
pr_err("%s: Error %d mapping Owner SID to gid\n",
|
||||||
|
@ -884,6 +900,9 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
|
||||||
pntsd->type |= cpu_to_le16(DACL_PROTECTED);
|
pntsd->type |= cpu_to_le16(DACL_PROTECTED);
|
||||||
|
|
||||||
if (dacloffset) {
|
if (dacloffset) {
|
||||||
|
if (dacloffset < sizeof(struct smb_ntsd))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
parse_dacl(idmap, dacl_ptr, end_of_acl,
|
parse_dacl(idmap, dacl_ptr, end_of_acl,
|
||||||
owner_sid_ptr, group_sid_ptr, fattr);
|
owner_sid_ptr, group_sid_ptr, fattr);
|
||||||
}
|
}
|
||||||
|
@ -1006,8 +1025,9 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
|
||||||
struct smb_sid owner_sid, group_sid;
|
struct smb_sid owner_sid, group_sid;
|
||||||
struct dentry *parent = path->dentry->d_parent;
|
struct dentry *parent = path->dentry->d_parent;
|
||||||
struct mnt_idmap *idmap = mnt_idmap(path->mnt);
|
struct mnt_idmap *idmap = mnt_idmap(path->mnt);
|
||||||
int inherited_flags = 0, flags = 0, i, ace_cnt = 0, nt_size = 0, pdacl_size;
|
int inherited_flags = 0, flags = 0, i, nt_size = 0, pdacl_size;
|
||||||
int rc = 0, num_aces, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size;
|
int rc = 0, dacloffset, pntsd_type, pntsd_size, acl_len, aces_size;
|
||||||
|
u16 num_aces, ace_cnt = 0;
|
||||||
char *aces_base;
|
char *aces_base;
|
||||||
bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
|
bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
|
||||||
|
|
||||||
|
@ -1023,7 +1043,7 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
|
||||||
|
|
||||||
parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
|
parent_pdacl = (struct smb_acl *)((char *)parent_pntsd + dacloffset);
|
||||||
acl_len = pntsd_size - 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);
|
pntsd_type = le16_to_cpu(parent_pntsd->type);
|
||||||
pdacl_size = le16_to_cpu(parent_pdacl->size);
|
pdacl_size = le16_to_cpu(parent_pdacl->size);
|
||||||
|
|
||||||
|
@ -1183,7 +1203,7 @@ pass:
|
||||||
pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
|
pdacl = (struct smb_acl *)((char *)pntsd + le32_to_cpu(pntsd->dacloffset));
|
||||||
pdacl->revision = cpu_to_le16(2);
|
pdacl->revision = cpu_to_le16(2);
|
||||||
pdacl->size = cpu_to_le16(sizeof(struct smb_acl) + nt_size);
|
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));
|
pace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
|
||||||
memcpy(pace, aces_base, nt_size);
|
memcpy(pace, aces_base, nt_size);
|
||||||
pntsd_size += sizeof(struct smb_acl) + nt_size;
|
pntsd_size += sizeof(struct smb_acl) + nt_size;
|
||||||
|
@ -1264,7 +1284,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
|
||||||
|
|
||||||
ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
|
ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
|
||||||
aces_size = acl_size - 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)
|
if (offsetof(struct smb_ace, access_req) > aces_size)
|
||||||
break;
|
break;
|
||||||
ace_size = le16_to_cpu(ace->size);
|
ace_size = le16_to_cpu(ace->size);
|
||||||
|
@ -1285,7 +1305,7 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, const struct path *path,
|
||||||
|
|
||||||
ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
|
ace = (struct smb_ace *)((char *)pdacl + sizeof(struct smb_acl));
|
||||||
aces_size = acl_size - 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)
|
if (offsetof(struct smb_ace, access_req) > aces_size)
|
||||||
break;
|
break;
|
||||||
ace_size = le16_to_cpu(ace->size);
|
ace_size = le16_to_cpu(ace->size);
|
||||||
|
|
|
@ -86,7 +86,7 @@ int parse_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
|
||||||
int build_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
|
int build_sec_desc(struct mnt_idmap *idmap, struct smb_ntsd *pntsd,
|
||||||
struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info,
|
struct smb_ntsd *ppntsd, int ppntsd_size, int addition_info,
|
||||||
__u32 *secdesclen, struct smb_fattr *fattr);
|
__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 free_acl_state(struct posix_acl_state *state);
|
||||||
void posix_state_to_acl(struct posix_acl_state *state,
|
void posix_state_to_acl(struct posix_acl_state *state,
|
||||||
struct posix_acl_entry *pace);
|
struct posix_acl_entry *pace);
|
||||||
|
|
|
@ -281,6 +281,7 @@ static int handle_response(int type, void *payload, size_t sz)
|
||||||
if (entry->type + 1 != type) {
|
if (entry->type + 1 != type) {
|
||||||
pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
|
pr_err("Waiting for IPC type %d, got %d. Ignore.\n",
|
||||||
entry->type + 1, type);
|
entry->type + 1, type);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->response = kvzalloc(sz, KSMBD_DEFAULT_GFP);
|
entry->response = kvzalloc(sz, KSMBD_DEFAULT_GFP);
|
||||||
|
|
Loading…
Add table
Reference in a new issue