19 ksmbd fixes, including various fixes pointed out by coverity, id mapping fixes, and some SMB direct fixes
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmE5OpsACgkQiiy9cAdy T1EZtAv/f64lME2MjUUjrRzh+vXCX+//T8rrTUuk3Xi5+giqITldwLCPSHP27M+h JiX9zKAs9rH/0xcKo4MpZITScqc9u8nKX8EmUcpFXw1d8vng3J1uznZD9j5RJVK6 +XdLzpC1RPQylJj8KNz8Wh5qtSvk/IauvdW8vM//PMNwWIplflT0j3Hwi78SeQg5 O16Py97ky0Ze2yX9kdsGC8xyNqpbIGVATvE2z3yP3huNj71oxE7swbpbG0f5n/F3 mE9ki9Blv+ukCOwNsmk3M3vu9HkKw2+mSY3nx8Fct9HJPCHkIMdSkN9Noy/XTpym JU7NpToKDY9sto9hyzdLZQSKTP5RocIeutnYhkpB2ZrYOwASickJGcwwsYuVy1TW bS0hgdN8IgxVBJvykReYJfHyFeJaaIw/gSagCB1ho8BOG+ZXXetJeBTa53pncN96 RkwFaeK5zmB3z4zXCCvvQb50Xe7wzUYw5WWTlIq+HLnDEsGvc3uFMxg05L8xAdL8 2MwtfSTJ =wY/6 -----END PGP SIGNATURE----- Merge tag '5.15-rc-ksmbd-part2' of git://git.samba.org/ksmbd Pull ksmbd fixes from Steve French: - various fixes pointed out by coverity, and a minor cleanup patch - id mapping and ownership fixes - an smbdirect fix * tag '5.15-rc-ksmbd-part2' of git://git.samba.org/ksmbd: ksmbd: fix control flow issues in sid_to_id() ksmbd: fix read of uninitialized variable ret in set_file_basic_info ksmbd: add missing assignments to ret on ndr_read_int64 read calls ksmbd: add validation for ndr read/write functions ksmbd: remove unused ksmbd_file_table_flush function ksmbd: smbd: fix dma mapping error in smb_direct_post_send_data ksmbd: Reduce error log 'speed is unknown' to debug ksmbd: defer notify_change() call ksmbd: remove setattr preparations in set_file_basic_info() ksmbd: ensure error is surfaced in set_file_basic_info() ndr: fix translation in ndr_encode_posix_acl() ksmbd: fix translation in sid_to_id() ksmbd: fix subauth 0 handling in sid_to_id() ksmbd: fix translation in acl entries ksmbd: fix translation in ksmbd_acls_fattr() ksmbd: fix translation in create_posix_rsp_buf() ksmbd: fix translation in smb2_populate_readdir_entry() ksmbd: fix lookup on idmapped mounts
This commit is contained in:
Коммит
bf9f243f23
381
fs/ksmbd/ndr.c
381
fs/ksmbd/ndr.c
|
@ -28,37 +28,60 @@ static int try_to_realloc_ndr_blob(struct ndr *n, size_t sz)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ndr_write_int16(struct ndr *n, __u16 value)
|
||||
static int ndr_write_int16(struct ndr *n, __u16 value)
|
||||
{
|
||||
if (n->length <= n->offset + sizeof(value))
|
||||
try_to_realloc_ndr_blob(n, sizeof(value));
|
||||
if (n->length <= n->offset + sizeof(value)) {
|
||||
int ret;
|
||||
|
||||
ret = try_to_realloc_ndr_blob(n, sizeof(value));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*(__le16 *)ndr_get_field(n) = cpu_to_le16(value);
|
||||
n->offset += sizeof(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ndr_write_int32(struct ndr *n, __u32 value)
|
||||
static int ndr_write_int32(struct ndr *n, __u32 value)
|
||||
{
|
||||
if (n->length <= n->offset + sizeof(value))
|
||||
try_to_realloc_ndr_blob(n, sizeof(value));
|
||||
if (n->length <= n->offset + sizeof(value)) {
|
||||
int ret;
|
||||
|
||||
ret = try_to_realloc_ndr_blob(n, sizeof(value));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*(__le32 *)ndr_get_field(n) = cpu_to_le32(value);
|
||||
n->offset += sizeof(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ndr_write_int64(struct ndr *n, __u64 value)
|
||||
static int ndr_write_int64(struct ndr *n, __u64 value)
|
||||
{
|
||||
if (n->length <= n->offset + sizeof(value))
|
||||
try_to_realloc_ndr_blob(n, sizeof(value));
|
||||
if (n->length <= n->offset + sizeof(value)) {
|
||||
int ret;
|
||||
|
||||
ret = try_to_realloc_ndr_blob(n, sizeof(value));
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
*(__le64 *)ndr_get_field(n) = cpu_to_le64(value);
|
||||
n->offset += sizeof(value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ndr_write_bytes(struct ndr *n, void *value, size_t sz)
|
||||
{
|
||||
if (n->length <= n->offset + sz)
|
||||
try_to_realloc_ndr_blob(n, sz);
|
||||
if (n->length <= n->offset + sz) {
|
||||
int ret;
|
||||
|
||||
ret = try_to_realloc_ndr_blob(n, sz);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(ndr_get_field(n), value, sz);
|
||||
n->offset += sz;
|
||||
|
@ -70,8 +93,13 @@ static int ndr_write_string(struct ndr *n, char *value)
|
|||
size_t sz;
|
||||
|
||||
sz = strlen(value) + 1;
|
||||
if (n->length <= n->offset + sz)
|
||||
try_to_realloc_ndr_blob(n, sz);
|
||||
if (n->length <= n->offset + sz) {
|
||||
int ret;
|
||||
|
||||
ret = try_to_realloc_ndr_blob(n, sz);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(ndr_get_field(n), value, sz);
|
||||
n->offset += sz;
|
||||
|
@ -81,9 +109,14 @@ static int ndr_write_string(struct ndr *n, char *value)
|
|||
|
||||
static int ndr_read_string(struct ndr *n, void *value, size_t sz)
|
||||
{
|
||||
int len = strnlen(ndr_get_field(n), sz);
|
||||
int len;
|
||||
|
||||
memcpy(value, ndr_get_field(n), len);
|
||||
if (n->offset + sz > n->length)
|
||||
return -EINVAL;
|
||||
|
||||
len = strnlen(ndr_get_field(n), sz);
|
||||
if (value)
|
||||
memcpy(value, ndr_get_field(n), len);
|
||||
len++;
|
||||
n->offset += len;
|
||||
n->offset = ALIGN(n->offset, 2);
|
||||
|
@ -92,41 +125,52 @@ static int ndr_read_string(struct ndr *n, void *value, size_t sz)
|
|||
|
||||
static int ndr_read_bytes(struct ndr *n, void *value, size_t sz)
|
||||
{
|
||||
memcpy(value, ndr_get_field(n), sz);
|
||||
if (n->offset + sz > n->length)
|
||||
return -EINVAL;
|
||||
|
||||
if (value)
|
||||
memcpy(value, ndr_get_field(n), sz);
|
||||
n->offset += sz;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __u16 ndr_read_int16(struct ndr *n)
|
||||
static int ndr_read_int16(struct ndr *n, __u16 *value)
|
||||
{
|
||||
__u16 ret;
|
||||
if (n->offset + sizeof(__u16) > n->length)
|
||||
return -EINVAL;
|
||||
|
||||
ret = le16_to_cpu(*(__le16 *)ndr_get_field(n));
|
||||
if (value)
|
||||
*value = le16_to_cpu(*(__le16 *)ndr_get_field(n));
|
||||
n->offset += sizeof(__u16);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __u32 ndr_read_int32(struct ndr *n)
|
||||
static int ndr_read_int32(struct ndr *n, __u32 *value)
|
||||
{
|
||||
__u32 ret;
|
||||
if (n->offset + sizeof(__u32) > n->length)
|
||||
return 0;
|
||||
|
||||
ret = le32_to_cpu(*(__le32 *)ndr_get_field(n));
|
||||
if (value)
|
||||
*value = le32_to_cpu(*(__le32 *)ndr_get_field(n));
|
||||
n->offset += sizeof(__u32);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __u64 ndr_read_int64(struct ndr *n)
|
||||
static int ndr_read_int64(struct ndr *n, __u64 *value)
|
||||
{
|
||||
__u64 ret;
|
||||
if (n->offset + sizeof(__u64) > n->length)
|
||||
return -EINVAL;
|
||||
|
||||
ret = le64_to_cpu(*(__le64 *)ndr_get_field(n));
|
||||
if (value)
|
||||
*value = le64_to_cpu(*(__le64 *)ndr_get_field(n));
|
||||
n->offset += sizeof(__u64);
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
|
||||
{
|
||||
char hex_attr[12] = {0};
|
||||
int ret;
|
||||
|
||||
n->offset = 0;
|
||||
n->length = 1024;
|
||||
|
@ -136,97 +180,161 @@ int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
|
|||
|
||||
if (da->version == 3) {
|
||||
snprintf(hex_attr, 10, "0x%x", da->attr);
|
||||
ndr_write_string(n, hex_attr);
|
||||
ret = ndr_write_string(n, hex_attr);
|
||||
} else {
|
||||
ndr_write_string(n, "");
|
||||
ret = ndr_write_string(n, "");
|
||||
}
|
||||
ndr_write_int16(n, da->version);
|
||||
ndr_write_int32(n, da->version);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int16(n, da->version);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int32(n, da->version);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int32(n, da->flags);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int32(n, da->attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ndr_write_int32(n, da->flags);
|
||||
ndr_write_int32(n, da->attr);
|
||||
if (da->version == 3) {
|
||||
ndr_write_int32(n, da->ea_size);
|
||||
ndr_write_int64(n, da->size);
|
||||
ndr_write_int64(n, da->alloc_size);
|
||||
ret = ndr_write_int32(n, da->ea_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ndr_write_int64(n, da->size);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ndr_write_int64(n, da->alloc_size);
|
||||
} else {
|
||||
ndr_write_int64(n, da->itime);
|
||||
ret = ndr_write_int64(n, da->itime);
|
||||
}
|
||||
ndr_write_int64(n, da->create_time);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int64(n, da->create_time);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (da->version == 3)
|
||||
ndr_write_int64(n, da->change_time);
|
||||
return 0;
|
||||
ret = ndr_write_int64(n, da->change_time);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
|
||||
{
|
||||
char *hex_attr;
|
||||
int version2;
|
||||
|
||||
hex_attr = kzalloc(n->length, GFP_KERNEL);
|
||||
if (!hex_attr)
|
||||
return -ENOMEM;
|
||||
char hex_attr[12];
|
||||
unsigned int version2;
|
||||
int ret;
|
||||
|
||||
n->offset = 0;
|
||||
ndr_read_string(n, hex_attr, n->length);
|
||||
kfree(hex_attr);
|
||||
da->version = ndr_read_int16(n);
|
||||
ret = ndr_read_string(n, hex_attr, sizeof(hex_attr));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int16(n, &da->version);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (da->version != 3 && da->version != 4) {
|
||||
pr_err("v%d version is not supported\n", da->version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
version2 = ndr_read_int32(n);
|
||||
ret = ndr_read_int32(n, &version2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (da->version != version2) {
|
||||
pr_err("ndr version mismatched(version: %d, version2: %d)\n",
|
||||
da->version, version2);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ndr_read_int32(n);
|
||||
da->attr = ndr_read_int32(n);
|
||||
ret = ndr_read_int32(n, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int32(n, &da->attr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (da->version == 4) {
|
||||
da->itime = ndr_read_int64(n);
|
||||
da->create_time = ndr_read_int64(n);
|
||||
ret = ndr_read_int64(n, &da->itime);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int64(n, &da->create_time);
|
||||
} else {
|
||||
ndr_read_int32(n);
|
||||
ndr_read_int64(n);
|
||||
ndr_read_int64(n);
|
||||
da->create_time = ndr_read_int64(n);
|
||||
ndr_read_int64(n);
|
||||
ret = ndr_read_int32(n, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int64(n, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int64(n, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int64(n, &da->create_time);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int64(n, NULL);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
|
||||
{
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
ret = ndr_write_int32(n, acl->count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ndr_write_int32(n, acl->count);
|
||||
n->offset = ALIGN(n->offset, 8);
|
||||
ndr_write_int32(n, acl->count);
|
||||
ndr_write_int32(n, 0);
|
||||
ret = ndr_write_int32(n, acl->count);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int32(n, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < acl->count; i++) {
|
||||
n->offset = ALIGN(n->offset, 8);
|
||||
ndr_write_int16(n, acl->entries[i].type);
|
||||
ndr_write_int16(n, acl->entries[i].type);
|
||||
ret = ndr_write_int16(n, acl->entries[i].type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int16(n, acl->entries[i].type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (acl->entries[i].type == SMB_ACL_USER) {
|
||||
n->offset = ALIGN(n->offset, 8);
|
||||
ndr_write_int64(n, acl->entries[i].uid);
|
||||
ret = ndr_write_int64(n, acl->entries[i].uid);
|
||||
} else if (acl->entries[i].type == SMB_ACL_GROUP) {
|
||||
n->offset = ALIGN(n->offset, 8);
|
||||
ndr_write_int64(n, acl->entries[i].gid);
|
||||
ret = ndr_write_int64(n, acl->entries[i].gid);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* push permission */
|
||||
ndr_write_int32(n, acl->entries[i].perm);
|
||||
ret = ndr_write_int32(n, acl->entries[i].perm);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ndr_encode_posix_acl(struct ndr *n,
|
||||
|
@ -235,7 +343,8 @@ int ndr_encode_posix_acl(struct ndr *n,
|
|||
struct xattr_smb_acl *acl,
|
||||
struct xattr_smb_acl *def_acl)
|
||||
{
|
||||
int ref_id = 0x00020000;
|
||||
unsigned int ref_id = 0x00020000;
|
||||
int ret;
|
||||
|
||||
n->offset = 0;
|
||||
n->length = 1024;
|
||||
|
@ -245,35 +354,46 @@ int ndr_encode_posix_acl(struct ndr *n,
|
|||
|
||||
if (acl) {
|
||||
/* ACL ACCESS */
|
||||
ndr_write_int32(n, ref_id);
|
||||
ret = ndr_write_int32(n, ref_id);
|
||||
ref_id += 4;
|
||||
} else {
|
||||
ndr_write_int32(n, 0);
|
||||
ret = ndr_write_int32(n, 0);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (def_acl) {
|
||||
/* DEFAULT ACL ACCESS */
|
||||
ndr_write_int32(n, ref_id);
|
||||
ret = ndr_write_int32(n, ref_id);
|
||||
ref_id += 4;
|
||||
} else {
|
||||
ndr_write_int32(n, 0);
|
||||
ret = ndr_write_int32(n, 0);
|
||||
}
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ndr_write_int64(n, from_kuid(user_ns, inode->i_uid));
|
||||
ndr_write_int64(n, from_kgid(user_ns, inode->i_gid));
|
||||
ndr_write_int32(n, inode->i_mode);
|
||||
ret = ndr_write_int64(n, from_kuid(&init_user_ns, i_uid_into_mnt(user_ns, inode)));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ndr_write_int64(n, from_kgid(&init_user_ns, i_gid_into_mnt(user_ns, inode)));
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = ndr_write_int32(n, inode->i_mode);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (acl) {
|
||||
ndr_encode_posix_acl_entry(n, acl);
|
||||
if (def_acl)
|
||||
ndr_encode_posix_acl_entry(n, def_acl);
|
||||
ret = ndr_encode_posix_acl_entry(n, acl);
|
||||
if (def_acl && !ret)
|
||||
ret = ndr_encode_posix_acl_entry(n, def_acl);
|
||||
}
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
|
||||
{
|
||||
int ref_id = 0x00020004;
|
||||
unsigned int ref_id = 0x00020004;
|
||||
int ret;
|
||||
|
||||
n->offset = 0;
|
||||
n->length = 2048;
|
||||
|
@ -281,36 +401,65 @@ int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
|
|||
if (!n->data)
|
||||
return -ENOMEM;
|
||||
|
||||
ndr_write_int16(n, acl->version);
|
||||
ndr_write_int32(n, acl->version);
|
||||
ndr_write_int16(n, 2);
|
||||
ndr_write_int32(n, ref_id);
|
||||
ret = ndr_write_int16(n, acl->version);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int32(n, acl->version);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int16(n, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int32(n, ref_id);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* push hash type and hash 64bytes */
|
||||
ndr_write_int16(n, acl->hash_type);
|
||||
ndr_write_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
|
||||
ndr_write_bytes(n, acl->desc, acl->desc_len);
|
||||
ndr_write_int64(n, acl->current_time);
|
||||
ndr_write_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
|
||||
ret = ndr_write_int16(n, acl->hash_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_bytes(n, acl->desc, acl->desc_len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_int64(n, acl->current_time);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_write_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* push ndr for security descriptor */
|
||||
ndr_write_bytes(n, acl->sd_buf, acl->sd_size);
|
||||
|
||||
return 0;
|
||||
ret = ndr_write_bytes(n, acl->sd_buf, acl->sd_size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
|
||||
{
|
||||
int version2;
|
||||
unsigned int version2;
|
||||
int ret;
|
||||
|
||||
n->offset = 0;
|
||||
acl->version = ndr_read_int16(n);
|
||||
ret = ndr_read_int16(n, &acl->version);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (acl->version != 4) {
|
||||
pr_err("v%d version is not supported\n", acl->version);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
version2 = ndr_read_int32(n);
|
||||
ret = ndr_read_int32(n, &version2);
|
||||
if (ret)
|
||||
return ret;
|
||||
if (acl->version != version2) {
|
||||
pr_err("ndr version mismatched(version: %d, version2: %d)\n",
|
||||
acl->version, version2);
|
||||
|
@ -318,11 +467,22 @@ int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
|
|||
}
|
||||
|
||||
/* Read Level */
|
||||
ndr_read_int16(n);
|
||||
ret = ndr_read_int16(n, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Read Ref Id */
|
||||
ndr_read_int32(n);
|
||||
acl->hash_type = ndr_read_int16(n);
|
||||
ndr_read_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
|
||||
ret = ndr_read_int32(n, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_int16(n, &acl->hash_type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ndr_read_bytes(n, acl->hash, XATTR_SD_HASH_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ndr_read_bytes(n, acl->desc, 10);
|
||||
if (strncmp(acl->desc, "posix_acl", 9)) {
|
||||
|
@ -331,15 +491,20 @@ int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
|
|||
}
|
||||
|
||||
/* Read Time */
|
||||
ndr_read_int64(n);
|
||||
ret = ndr_read_int64(n, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Read Posix ACL hash */
|
||||
ndr_read_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
|
||||
ret = ndr_read_bytes(n, acl->posix_acl_hash, XATTR_SD_HASH_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
acl->sd_size = n->length - n->offset;
|
||||
acl->sd_buf = kzalloc(acl->sd_size, GFP_KERNEL);
|
||||
if (!acl->sd_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
ndr_read_bytes(n, acl->sd_buf, acl->sd_size);
|
||||
|
||||
return 0;
|
||||
ret = ndr_read_bytes(n, acl->sd_buf, acl->sd_size);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1614,9 +1614,11 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
|
|||
buf->nlink = cpu_to_le32(inode->i_nlink);
|
||||
buf->reparse_tag = cpu_to_le32(fp->volatile_id);
|
||||
buf->mode = cpu_to_le32(inode->i_mode);
|
||||
id_to_sid(from_kuid(user_ns, inode->i_uid),
|
||||
id_to_sid(from_kuid_munged(&init_user_ns,
|
||||
i_uid_into_mnt(user_ns, inode)),
|
||||
SIDNFS_USER, (struct smb_sid *)&buf->SidBuffer[0]);
|
||||
id_to_sid(from_kgid(user_ns, inode->i_gid),
|
||||
id_to_sid(from_kgid_munged(&init_user_ns,
|
||||
i_gid_into_mnt(user_ns, inode)),
|
||||
SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]);
|
||||
}
|
||||
|
||||
|
|
|
@ -2381,10 +2381,12 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
|
|||
le32_to_cpu(sd_buf->ccontext.DataLength), true);
|
||||
}
|
||||
|
||||
static void ksmbd_acls_fattr(struct smb_fattr *fattr, struct inode *inode)
|
||||
static void ksmbd_acls_fattr(struct smb_fattr *fattr,
|
||||
struct user_namespace *mnt_userns,
|
||||
struct inode *inode)
|
||||
{
|
||||
fattr->cf_uid = inode->i_uid;
|
||||
fattr->cf_gid = inode->i_gid;
|
||||
fattr->cf_uid = i_uid_into_mnt(mnt_userns, inode);
|
||||
fattr->cf_gid = i_gid_into_mnt(mnt_userns, inode);
|
||||
fattr->cf_mode = inode->i_mode;
|
||||
fattr->cf_acls = NULL;
|
||||
fattr->cf_dacls = NULL;
|
||||
|
@ -2893,7 +2895,7 @@ int smb2_open(struct ksmbd_work *work)
|
|||
struct smb_ntsd *pntsd;
|
||||
int pntsd_size, ace_num = 0;
|
||||
|
||||
ksmbd_acls_fattr(&fattr, inode);
|
||||
ksmbd_acls_fattr(&fattr, user_ns, inode);
|
||||
if (fattr.cf_acls)
|
||||
ace_num = fattr.cf_acls->a_count;
|
||||
if (fattr.cf_dacls)
|
||||
|
@ -3324,7 +3326,6 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
|
|||
*/
|
||||
static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
|
||||
struct ksmbd_dir_info *d_info,
|
||||
struct user_namespace *user_ns,
|
||||
struct ksmbd_kstat *ksmbd_kstat)
|
||||
{
|
||||
int next_entry_offset = 0;
|
||||
|
@ -3478,9 +3479,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
|
|||
S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE;
|
||||
if (d_info->hide_dot_file && d_info->name[0] == '.')
|
||||
posix_info->DosAttributes |= ATTR_HIDDEN_LE;
|
||||
id_to_sid(from_kuid(user_ns, ksmbd_kstat->kstat->uid),
|
||||
id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid),
|
||||
SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
|
||||
id_to_sid(from_kgid(user_ns, ksmbd_kstat->kstat->gid),
|
||||
id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid),
|
||||
SIDNFS_GROUP, (struct smb_sid *)&posix_info->SidBuffer[20]);
|
||||
memcpy(posix_info->name, conv_name, conv_len);
|
||||
posix_info->name_len = cpu_to_le32(conv_len);
|
||||
|
@ -3543,9 +3544,9 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
|
|||
return -EINVAL;
|
||||
|
||||
lock_dir(priv->dir_fp);
|
||||
dent = lookup_one_len(priv->d_info->name,
|
||||
priv->dir_fp->filp->f_path.dentry,
|
||||
priv->d_info->name_len);
|
||||
dent = lookup_one(user_ns, priv->d_info->name,
|
||||
priv->dir_fp->filp->f_path.dentry,
|
||||
priv->d_info->name_len);
|
||||
unlock_dir(priv->dir_fp);
|
||||
|
||||
if (IS_ERR(dent)) {
|
||||
|
@ -3571,7 +3572,6 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
|
|||
rc = smb2_populate_readdir_entry(priv->work->conn,
|
||||
priv->info_level,
|
||||
priv->d_info,
|
||||
user_ns,
|
||||
&ksmbd_kstat);
|
||||
dput(dent);
|
||||
if (rc)
|
||||
|
@ -5008,7 +5008,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
|
|||
|
||||
user_ns = file_mnt_user_ns(fp->filp);
|
||||
inode = file_inode(fp->filp);
|
||||
ksmbd_acls_fattr(&fattr, inode);
|
||||
ksmbd_acls_fattr(&fattr, user_ns, inode);
|
||||
|
||||
if (test_share_config_flag(work->tcon->share_conf,
|
||||
KSMBD_SHARE_FLAG_ACL_XATTR))
|
||||
|
@ -5246,7 +5246,9 @@ int smb2_echo(struct ksmbd_work *work)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
static int smb2_rename(struct ksmbd_work *work,
|
||||
struct ksmbd_file *fp,
|
||||
struct user_namespace *user_ns,
|
||||
struct smb2_file_rename_info *file_info,
|
||||
struct nls_table *local_nls)
|
||||
{
|
||||
|
@ -5310,7 +5312,7 @@ static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||
if (rc)
|
||||
goto out;
|
||||
|
||||
rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp),
|
||||
rc = ksmbd_vfs_setxattr(user_ns,
|
||||
fp->filp->f_path.dentry,
|
||||
xattr_stream_name,
|
||||
NULL, 0, 0);
|
||||
|
@ -5438,11 +5440,11 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
|
|||
{
|
||||
struct smb2_file_all_info *file_info;
|
||||
struct iattr attrs;
|
||||
struct iattr temp_attrs;
|
||||
struct timespec64 ctime;
|
||||
struct file *filp;
|
||||
struct inode *inode;
|
||||
struct user_namespace *user_ns;
|
||||
int rc;
|
||||
int rc = 0;
|
||||
|
||||
if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE))
|
||||
return -EACCES;
|
||||
|
@ -5462,11 +5464,11 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
|
|||
}
|
||||
|
||||
if (file_info->ChangeTime) {
|
||||
temp_attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
|
||||
attrs.ia_ctime = temp_attrs.ia_ctime;
|
||||
attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
|
||||
ctime = attrs.ia_ctime;
|
||||
attrs.ia_valid |= ATTR_CTIME;
|
||||
} else {
|
||||
temp_attrs.ia_ctime = inode->i_ctime;
|
||||
ctime = inode->i_ctime;
|
||||
}
|
||||
|
||||
if (file_info->LastWriteTime) {
|
||||
|
@ -5505,13 +5507,6 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
|
|||
rc = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HACK : set ctime here to avoid ctime changed
|
||||
* when file_info->ChangeTime is zero.
|
||||
*/
|
||||
attrs.ia_ctime = temp_attrs.ia_ctime;
|
||||
attrs.ia_valid |= ATTR_CTIME;
|
||||
|
||||
if (attrs.ia_valid) {
|
||||
struct dentry *dentry = filp->f_path.dentry;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
@ -5519,17 +5514,15 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
|
|||
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||
return -EACCES;
|
||||
|
||||
rc = setattr_prepare(user_ns, dentry, &attrs);
|
||||
if (rc)
|
||||
return -EINVAL;
|
||||
|
||||
inode_lock(inode);
|
||||
setattr_copy(user_ns, inode, &attrs);
|
||||
attrs.ia_valid &= ~ATTR_CTIME;
|
||||
rc = notify_change(user_ns, dentry, &attrs, NULL);
|
||||
if (!rc) {
|
||||
inode->i_ctime = ctime;
|
||||
mark_inode_dirty(inode);
|
||||
}
|
||||
inode_unlock(inode);
|
||||
}
|
||||
return 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int set_file_allocation_info(struct ksmbd_work *work,
|
||||
|
@ -5624,6 +5617,7 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||
static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
char *buf)
|
||||
{
|
||||
struct user_namespace *user_ns;
|
||||
struct ksmbd_file *parent_fp;
|
||||
struct dentry *parent;
|
||||
struct dentry *dentry = fp->filp->f_path.dentry;
|
||||
|
@ -5634,11 +5628,12 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||
return -EACCES;
|
||||
}
|
||||
|
||||
user_ns = file_mnt_user_ns(fp->filp);
|
||||
if (ksmbd_stream_fd(fp))
|
||||
goto next;
|
||||
|
||||
parent = dget_parent(dentry);
|
||||
ret = ksmbd_vfs_lock_parent(parent, dentry);
|
||||
ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
|
||||
if (ret) {
|
||||
dput(parent);
|
||||
return ret;
|
||||
|
@ -5655,7 +5650,7 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||
}
|
||||
}
|
||||
next:
|
||||
return smb2_rename(work, fp,
|
||||
return smb2_rename(work, fp, user_ns,
|
||||
(struct smb2_file_rename_info *)buf,
|
||||
work->sess->conn->local_nls);
|
||||
}
|
||||
|
@ -7116,8 +7111,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
|
|||
netdev->ethtool_ops->get_link_ksettings(netdev, &cmd);
|
||||
speed = cmd.base.speed;
|
||||
} else {
|
||||
pr_err("%s %s\n", netdev->name,
|
||||
"speed is unknown, defaulting to 1Gb/sec");
|
||||
ksmbd_debug(SMB, "%s %s\n", netdev->name,
|
||||
"speed is unknown, defaulting to 1Gb/sec");
|
||||
speed = SPEED_1000;
|
||||
}
|
||||
|
||||
|
|
|
@ -291,7 +291,6 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
|
|||
char *search_pattern,
|
||||
int (*fn)(struct ksmbd_conn *, int,
|
||||
struct ksmbd_dir_info *,
|
||||
struct user_namespace *,
|
||||
struct ksmbd_kstat *))
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
@ -322,8 +321,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
|
|||
user_ns,
|
||||
dir->filp->f_path.dentry->d_parent,
|
||||
&ksmbd_kstat);
|
||||
rc = fn(conn, info_level, d_info,
|
||||
user_ns, &ksmbd_kstat);
|
||||
rc = fn(conn, info_level, d_info, &ksmbd_kstat);
|
||||
if (rc)
|
||||
break;
|
||||
if (d_info->out_buf_len <= 0)
|
||||
|
|
|
@ -511,7 +511,6 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
|
|||
int (*fn)(struct ksmbd_conn *,
|
||||
int,
|
||||
struct ksmbd_dir_info *,
|
||||
struct user_namespace *,
|
||||
struct ksmbd_kstat *));
|
||||
|
||||
int ksmbd_extract_shortname(struct ksmbd_conn *conn,
|
||||
|
|
|
@ -274,24 +274,34 @@ static int sid_to_id(struct user_namespace *user_ns,
|
|||
uid_t id;
|
||||
|
||||
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
|
||||
if (id > 0) {
|
||||
uid = make_kuid(user_ns, id);
|
||||
if (uid_valid(uid) && kuid_has_mapping(user_ns, uid)) {
|
||||
fattr->cf_uid = uid;
|
||||
rc = 0;
|
||||
}
|
||||
/*
|
||||
* Translate raw sid into kuid in the server's user
|
||||
* namespace.
|
||||
*/
|
||||
uid = make_kuid(&init_user_ns, id);
|
||||
|
||||
/* If this is an idmapped mount, apply the idmapping. */
|
||||
uid = kuid_from_mnt(user_ns, uid);
|
||||
if (uid_valid(uid)) {
|
||||
fattr->cf_uid = uid;
|
||||
rc = 0;
|
||||
}
|
||||
} else {
|
||||
kgid_t gid;
|
||||
gid_t id;
|
||||
|
||||
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
|
||||
if (id > 0) {
|
||||
gid = make_kgid(user_ns, id);
|
||||
if (gid_valid(gid) && kgid_has_mapping(user_ns, gid)) {
|
||||
fattr->cf_gid = gid;
|
||||
rc = 0;
|
||||
}
|
||||
/*
|
||||
* Translate raw sid into kgid in the server's user
|
||||
* namespace.
|
||||
*/
|
||||
gid = make_kgid(&init_user_ns, id);
|
||||
|
||||
/* If this is an idmapped mount, apply the idmapping. */
|
||||
gid = kgid_from_mnt(user_ns, gid);
|
||||
if (gid_valid(gid)) {
|
||||
fattr->cf_gid = gid;
|
||||
rc = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -587,14 +597,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 +663,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);
|
||||
|
@ -723,7 +733,7 @@ static void set_mode_dacl(struct user_namespace *user_ns,
|
|||
}
|
||||
|
||||
/* owner RID */
|
||||
uid = from_kuid(user_ns, fattr->cf_uid);
|
||||
uid = from_kuid(&init_user_ns, fattr->cf_uid);
|
||||
if (uid)
|
||||
sid = &server_conf.domain_sid;
|
||||
else
|
||||
|
@ -739,7 +749,7 @@ static void set_mode_dacl(struct user_namespace *user_ns,
|
|||
ace_size = fill_ace_for_sid(pace, &sid_unix_groups,
|
||||
ACCESS_ALLOWED, 0, fattr->cf_mode, 0070);
|
||||
pace->sid.sub_auth[pace->sid.num_subauth++] =
|
||||
cpu_to_le32(from_kgid(user_ns, fattr->cf_gid));
|
||||
cpu_to_le32(from_kgid(&init_user_ns, fattr->cf_gid));
|
||||
pace->size = cpu_to_le16(ace_size + 4);
|
||||
size += le16_to_cpu(pace->size);
|
||||
pace = (struct smb_ace *)((char *)pndace + size);
|
||||
|
@ -880,7 +890,7 @@ int build_sec_desc(struct user_namespace *user_ns,
|
|||
if (!nowner_sid_ptr)
|
||||
return -ENOMEM;
|
||||
|
||||
uid = from_kuid(user_ns, fattr->cf_uid);
|
||||
uid = from_kuid(&init_user_ns, fattr->cf_uid);
|
||||
if (!uid)
|
||||
sid_type = SIDUNIX_USER;
|
||||
id_to_sid(uid, sid_type, nowner_sid_ptr);
|
||||
|
@ -891,7 +901,7 @@ int build_sec_desc(struct user_namespace *user_ns,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
gid = from_kgid(user_ns, fattr->cf_gid);
|
||||
gid = from_kgid(&init_user_ns, fattr->cf_gid);
|
||||
id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr);
|
||||
|
||||
offset = sizeof(struct smb_ntsd);
|
||||
|
@ -1234,11 +1244,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;
|
||||
|
||||
|
@ -1322,22 +1330,31 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
|
|||
newattrs.ia_valid |= ATTR_MODE;
|
||||
newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
|
||||
|
||||
inode_lock(inode);
|
||||
rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
|
||||
inode_unlock(inode);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry);
|
||||
/* Update posix acls */
|
||||
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) {
|
||||
rc = set_posix_acl(user_ns, inode,
|
||||
ACL_TYPE_ACCESS, fattr.cf_acls);
|
||||
if (S_ISDIR(inode->i_mode) && fattr.cf_dacls)
|
||||
if (rc < 0)
|
||||
ksmbd_debug(SMB,
|
||||
"Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
|
||||
rc);
|
||||
if (S_ISDIR(inode->i_mode) && fattr.cf_dacls) {
|
||||
rc = set_posix_acl(user_ns, inode,
|
||||
ACL_TYPE_DEFAULT, fattr.cf_dacls);
|
||||
if (rc)
|
||||
ksmbd_debug(SMB,
|
||||
"Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
|
||||
rc);
|
||||
}
|
||||
}
|
||||
|
||||
inode_lock(inode);
|
||||
rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
|
||||
inode_unlock(inode);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
/* Check it only calling from SD BUFFER context */
|
||||
if (type_check && !(le16_to_cpu(pntsd->type) & DACL_PRESENT))
|
||||
goto out;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -1168,7 +1168,7 @@ static int smb_direct_post_send_data(struct smb_direct_transport *t,
|
|||
pr_err("failed to map buffer\n");
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
} else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES - 1) {
|
||||
} else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES) {
|
||||
pr_err("buffer not fitted into sges\n");
|
||||
ret = -E2BIG;
|
||||
ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt,
|
||||
|
|
|
@ -69,14 +69,15 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
|
|||
*
|
||||
* the reference count of @parent isn't incremented.
|
||||
*/
|
||||
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
|
||||
int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
|
||||
struct dentry *child)
|
||||
{
|
||||
struct dentry *dentry;
|
||||
int ret = 0;
|
||||
|
||||
inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
|
||||
dentry = lookup_one_len(child->d_name.name, parent,
|
||||
child->d_name.len);
|
||||
dentry = lookup_one(user_ns, child->d_name.name, parent,
|
||||
child->d_name.len);
|
||||
if (IS_ERR(dentry)) {
|
||||
ret = PTR_ERR(dentry);
|
||||
goto out_err;
|
||||
|
@ -102,7 +103,7 @@ int ksmbd_vfs_may_delete(struct user_namespace *user_ns,
|
|||
int ret;
|
||||
|
||||
parent = dget_parent(dentry);
|
||||
ret = ksmbd_vfs_lock_parent(parent, dentry);
|
||||
ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
|
||||
if (ret) {
|
||||
dput(parent);
|
||||
return ret;
|
||||
|
@ -137,7 +138,7 @@ int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
|
|||
*daccess |= FILE_EXECUTE_LE;
|
||||
|
||||
parent = dget_parent(dentry);
|
||||
ret = ksmbd_vfs_lock_parent(parent, dentry);
|
||||
ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
|
||||
if (ret) {
|
||||
dput(parent);
|
||||
return ret;
|
||||
|
@ -197,6 +198,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
|
|||
*/
|
||||
int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
|
||||
{
|
||||
struct user_namespace *user_ns;
|
||||
struct path path;
|
||||
struct dentry *dentry;
|
||||
int err;
|
||||
|
@ -210,16 +212,16 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
|
|||
return err;
|
||||
}
|
||||
|
||||
user_ns = mnt_user_ns(path.mnt);
|
||||
mode |= S_IFDIR;
|
||||
err = vfs_mkdir(mnt_user_ns(path.mnt), d_inode(path.dentry),
|
||||
dentry, mode);
|
||||
err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
|
||||
if (err) {
|
||||
goto out;
|
||||
} else if (d_unhashed(dentry)) {
|
||||
struct dentry *d;
|
||||
|
||||
d = lookup_one_len(dentry->d_name.name, dentry->d_parent,
|
||||
dentry->d_name.len);
|
||||
d = lookup_one(user_ns, dentry->d_name.name, dentry->d_parent,
|
||||
dentry->d_name.len);
|
||||
if (IS_ERR(d)) {
|
||||
err = PTR_ERR(d);
|
||||
goto out;
|
||||
|
@ -582,6 +584,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
|
|||
*/
|
||||
int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
|
||||
{
|
||||
struct user_namespace *user_ns;
|
||||
struct path path;
|
||||
struct dentry *parent;
|
||||
int err;
|
||||
|
@ -601,8 +604,9 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
|
|||
return err;
|
||||
}
|
||||
|
||||
user_ns = mnt_user_ns(path.mnt);
|
||||
parent = dget_parent(path.dentry);
|
||||
err = ksmbd_vfs_lock_parent(parent, path.dentry);
|
||||
err = ksmbd_vfs_lock_parent(user_ns, parent, path.dentry);
|
||||
if (err) {
|
||||
dput(parent);
|
||||
path_put(&path);
|
||||
|
@ -616,14 +620,12 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
|
|||
}
|
||||
|
||||
if (S_ISDIR(d_inode(path.dentry)->i_mode)) {
|
||||
err = vfs_rmdir(mnt_user_ns(path.mnt), d_inode(parent),
|
||||
path.dentry);
|
||||
err = vfs_rmdir(user_ns, d_inode(parent), path.dentry);
|
||||
if (err && err != -ENOTEMPTY)
|
||||
ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
|
||||
err);
|
||||
} else {
|
||||
err = vfs_unlink(mnt_user_ns(path.mnt), d_inode(parent),
|
||||
path.dentry, NULL);
|
||||
err = vfs_unlink(user_ns, d_inode(parent), path.dentry, NULL);
|
||||
if (err)
|
||||
ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
|
||||
err);
|
||||
|
@ -748,7 +750,8 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
|
|||
if (ksmbd_override_fsids(work))
|
||||
return -ENOMEM;
|
||||
|
||||
dst_dent = lookup_one_len(dst_name, dst_dent_parent, strlen(dst_name));
|
||||
dst_dent = lookup_one(dst_user_ns, dst_name, dst_dent_parent,
|
||||
strlen(dst_name));
|
||||
err = PTR_ERR(dst_dent);
|
||||
if (IS_ERR(dst_dent)) {
|
||||
pr_err("lookup failed %s [%d]\n", dst_name, err);
|
||||
|
@ -779,6 +782,7 @@ out:
|
|||
int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
|
||||
char *newname)
|
||||
{
|
||||
struct user_namespace *user_ns;
|
||||
struct path dst_path;
|
||||
struct dentry *src_dent_parent, *dst_dent_parent;
|
||||
struct dentry *src_dent, *trap_dent, *src_child;
|
||||
|
@ -808,8 +812,9 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||
trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
|
||||
dget(src_dent);
|
||||
dget(dst_dent_parent);
|
||||
src_child = lookup_one_len(src_dent->d_name.name, src_dent_parent,
|
||||
src_dent->d_name.len);
|
||||
user_ns = file_mnt_user_ns(fp->filp);
|
||||
src_child = lookup_one(user_ns, src_dent->d_name.name, src_dent_parent,
|
||||
src_dent->d_name.len);
|
||||
if (IS_ERR(src_child)) {
|
||||
err = PTR_ERR(src_child);
|
||||
goto out_lock;
|
||||
|
@ -823,7 +828,7 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||
dput(src_child);
|
||||
|
||||
err = __ksmbd_vfs_rename(work,
|
||||
file_mnt_user_ns(fp->filp),
|
||||
user_ns,
|
||||
src_dent_parent,
|
||||
src_dent,
|
||||
mnt_user_ns(dst_path.mnt),
|
||||
|
@ -1109,7 +1114,7 @@ int ksmbd_vfs_unlink(struct user_namespace *user_ns,
|
|||
{
|
||||
int err = 0;
|
||||
|
||||
err = ksmbd_vfs_lock_parent(dir, dentry);
|
||||
err = ksmbd_vfs_lock_parent(user_ns, dir, dentry);
|
||||
if (err)
|
||||
return err;
|
||||
dget(dentry);
|
||||
|
@ -1385,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;
|
||||
|
|
|
@ -107,7 +107,8 @@ struct ksmbd_kstat {
|
|||
__le32 file_attributes;
|
||||
};
|
||||
|
||||
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child);
|
||||
int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
|
||||
struct dentry *child);
|
||||
int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry);
|
||||
int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
|
||||
struct dentry *dentry, __le32 *daccess);
|
||||
|
|
|
@ -666,22 +666,6 @@ void ksmbd_free_global_file_table(void)
|
|||
ksmbd_destroy_file_table(&global_ft);
|
||||
}
|
||||
|
||||
int ksmbd_file_table_flush(struct ksmbd_work *work)
|
||||
{
|
||||
struct ksmbd_file *fp = NULL;
|
||||
unsigned int id;
|
||||
int ret;
|
||||
|
||||
read_lock(&work->sess->file_table.lock);
|
||||
idr_for_each_entry(work->sess->file_table.idr, fp, id) {
|
||||
ret = ksmbd_vfs_fsync(work, fp->volatile_id, KSMBD_NO_FID);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
read_unlock(&work->sess->file_table.lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ksmbd_init_file_table(struct ksmbd_file_table *ft)
|
||||
{
|
||||
ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL);
|
||||
|
|
|
@ -152,7 +152,6 @@ void ksmbd_close_session_fds(struct ksmbd_work *work);
|
|||
int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode);
|
||||
int ksmbd_init_global_file_table(void);
|
||||
void ksmbd_free_global_file_table(void);
|
||||
int ksmbd_file_table_flush(struct ksmbd_work *work);
|
||||
void ksmbd_set_fd_limit(unsigned long limit);
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче