From af34983e831587472333e47c86a350a2360c6093 Mon Sep 17 00:00:00 2001 From: Hyunchul Lee Date: Wed, 30 Jun 2021 18:25:53 +0900 Subject: [PATCH] ksmbd: add user namespace support For user namespace support, call vfs functions with struct user_namespace got from struct path. This patch have been tested mannually as below. Create an id-mapped mount using the mount-idmapped utility (https://github.com/brauner/mount-idmapped). $ mount-idmapped --map-mount b:1003:1002:1 /home/foo /foo (the user, "foo" is 1003, and the user "bar" is 1002). And mount the export directory using cifs with the user, "bar". succeed to create/delete/stat/read/write files and directory in the /foo. But fail with a bind mount for /home/foo. Reviewed-by: Christoph Hellwig Signed-off-by: Hyunchul Lee Signed-off-by: Namjae Jeon Signed-off-by: Steve French --- fs/ksmbd/ndr.c | 8 ++- fs/ksmbd/ndr.h | 4 +- fs/ksmbd/oplock.c | 4 +- fs/ksmbd/smb2pdu.c | 113 +++++++++++++++++++++------------ fs/ksmbd/smb_common.c | 5 +- fs/ksmbd/smb_common.h | 1 + fs/ksmbd/smbacl.c | 99 +++++++++++++++++------------ fs/ksmbd/smbacl.h | 10 +-- fs/ksmbd/vfs.c | 172 +++++++++++++++++++++++++++++++------------------- fs/ksmbd/vfs.h | 51 ++++++++++----- fs/ksmbd/vfs_cache.c | 5 +- 11 files changed, 294 insertions(+), 178 deletions(-) diff --git a/fs/ksmbd/ndr.c b/fs/ksmbd/ndr.c index bcf13a2..cf0df78 100644 --- a/fs/ksmbd/ndr.c +++ b/fs/ksmbd/ndr.c @@ -222,7 +222,9 @@ static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl) return 0; } -int ndr_encode_posix_acl(struct ndr *n, struct inode *inode, +int ndr_encode_posix_acl(struct ndr *n, + struct user_namespace *user_ns, + struct inode *inode, struct xattr_smb_acl *acl, struct xattr_smb_acl *def_acl) { @@ -250,8 +252,8 @@ int ndr_encode_posix_acl(struct ndr *n, struct inode *inode, ndr_write_int32(n, 0); } - ndr_write_int64(n, from_kuid(&init_user_ns, inode->i_uid)); - ndr_write_int64(n, from_kgid(&init_user_ns, inode->i_gid)); + 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); if (acl) { diff --git a/fs/ksmbd/ndr.h b/fs/ksmbd/ndr.h index 77b2d1a..60ca265 100644 --- a/fs/ksmbd/ndr.h +++ b/fs/ksmbd/ndr.h @@ -14,8 +14,8 @@ struct ndr { int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da); int ndr_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da); -int ndr_encode_posix_acl(struct ndr *n, struct inode *inode, - struct xattr_smb_acl *acl, +int ndr_encode_posix_acl(struct ndr *n, struct user_namespace *user_ns, + struct inode *inode, struct xattr_smb_acl *acl, struct xattr_smb_acl *def_acl); int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl); int ndr_encode_v3_ntacl(struct ndr *n, struct xattr_ntacl *acl); diff --git a/fs/ksmbd/oplock.c b/fs/ksmbd/oplock.c index a9f171cc..5484b5b 100644 --- a/fs/ksmbd/oplock.c +++ b/fs/ksmbd/oplock.c @@ -1612,9 +1612,9 @@ 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(&init_user_ns, inode->i_uid), + id_to_sid(from_kuid(file_mnt_user_ns(fp->filp), inode->i_uid), SIDNFS_USER, (struct smb_sid *)&buf->SidBuffer[0]); - id_to_sid(from_kgid(&init_user_ns, inode->i_gid), + id_to_sid(from_kgid(file_mnt_user_ns(fp->filp), inode->i_gid), SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]); } diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c index d79ea3e..dda9081 100644 --- a/fs/ksmbd/smb2pdu.c +++ b/fs/ksmbd/smb2pdu.c @@ -2081,14 +2081,16 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path) value = (char *)&eabuf->name + eabuf->EaNameLength + 1; if (!eabuf->EaValueLength) { - rc = ksmbd_vfs_casexattr_len(path->dentry, + rc = ksmbd_vfs_casexattr_len(mnt_user_ns(path->mnt), + path->dentry, attr_name, XATTR_USER_PREFIX_LEN + eabuf->EaNameLength); /* delete the EA only when it exits */ if (rc > 0) { - rc = ksmbd_vfs_remove_xattr(path->dentry, + rc = ksmbd_vfs_remove_xattr(mnt_user_ns(path->mnt), + path->dentry, attr_name); if (rc < 0) { @@ -2102,7 +2104,8 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path) /* if the EA doesn't exist, just do nothing. */ rc = 0; } else { - rc = ksmbd_vfs_setxattr(path->dentry, attr_name, value, + rc = ksmbd_vfs_setxattr(mnt_user_ns(path->mnt), + path->dentry, attr_name, value, le16_to_cpu(eabuf->EaValueLength), 0); if (rc < 0) { ksmbd_debug(SMB, @@ -2155,7 +2158,8 @@ static noinline int smb2_set_stream_name_xattr(struct path *path, fp->stream.size = xattr_stream_size; /* Check if there is stream prefix in xattr space */ - rc = ksmbd_vfs_casexattr_len(path->dentry, + rc = ksmbd_vfs_casexattr_len(mnt_user_ns(path->mnt), + path->dentry, xattr_stream_name, xattr_stream_size); if (rc >= 0) @@ -2166,7 +2170,8 @@ static noinline int smb2_set_stream_name_xattr(struct path *path, return -EBADF; } - rc = ksmbd_vfs_setxattr(path->dentry, xattr_stream_name, NULL, 0, 0); + rc = ksmbd_vfs_setxattr(mnt_user_ns(path->mnt), + path->dentry, xattr_stream_name, NULL, 0, 0); if (rc < 0) pr_err("Failed to store XATTR stream name :%d\n", rc); return 0; @@ -2196,7 +2201,8 @@ static int smb2_remove_smb_xattrs(struct path *path) strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN)) continue; - err = ksmbd_vfs_remove_xattr(path->dentry, name); + err = ksmbd_vfs_remove_xattr(mnt_user_ns(path->mnt), + path->dentry, name); if (err) ksmbd_debug(SMB, "remove xattr failed : %s\n", name); } @@ -2240,7 +2246,8 @@ static void smb2_new_xattrs(struct ksmbd_tree_connect *tcon, struct path *path, da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | XATTR_DOSINFO_ITIME; - rc = ksmbd_vfs_set_dos_attrib_xattr(path->dentry, &da); + rc = ksmbd_vfs_set_dos_attrib_xattr(mnt_user_ns(path->mnt), + path->dentry, &da); if (rc) ksmbd_debug(SMB, "failed to store file attribute into xattr\n"); } @@ -2258,7 +2265,8 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) return; - rc = ksmbd_vfs_get_dos_attrib_xattr(path->dentry, &da); + rc = ksmbd_vfs_get_dos_attrib_xattr(mnt_user_ns(path->mnt), + path->dentry, &da); if (rc > 0) { fp->f_ci->m_fattr = cpu_to_le32(da.attr); fp->create_time = da.create_time; @@ -2634,7 +2642,7 @@ int smb2_open(struct ksmbd_work *work) rc = 0; } else { file_present = true; - generic_fillattr(&init_user_ns, d_inode(path.dentry), &stat); + generic_fillattr(mnt_user_ns(path.mnt), d_inode(path.dentry), &stat); } if (stream_name) { if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { @@ -2695,7 +2703,8 @@ int smb2_open(struct ksmbd_work *work) if (!file_present) { daccess = cpu_to_le32(GENERIC_ALL_FLAGS); } else { - rc = ksmbd_vfs_query_maximal_access(path.dentry, + rc = ksmbd_vfs_query_maximal_access(mnt_user_ns(path.mnt), + path.dentry, &daccess); if (rc) goto err_out; @@ -2738,7 +2747,7 @@ int smb2_open(struct ksmbd_work *work) * is already granted. */ if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) { - rc = inode_permission(&init_user_ns, + rc = inode_permission(mnt_user_ns(path.mnt), d_inode(path.dentry), may_flags); if (rc) @@ -2746,7 +2755,8 @@ int smb2_open(struct ksmbd_work *work) if ((daccess & FILE_DELETE_LE) || (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)) { - rc = ksmbd_vfs_may_delete(path.dentry); + rc = ksmbd_vfs_may_delete(mnt_user_ns(path.mnt), + path.dentry); if (rc) goto err_out; } @@ -2809,7 +2819,9 @@ int smb2_open(struct ksmbd_work *work) int posix_acl_rc; struct inode *inode = d_inode(path.dentry); - posix_acl_rc = ksmbd_vfs_inherit_posix_acl(inode, d_inode(path.dentry->d_parent)); + posix_acl_rc = ksmbd_vfs_inherit_posix_acl(mnt_user_ns(path.mnt), + inode, + d_inode(path.dentry->d_parent)); if (posix_acl_rc) ksmbd_debug(SMB, "inherit posix acl failed : %d\n", posix_acl_rc); @@ -2823,7 +2835,8 @@ int smb2_open(struct ksmbd_work *work) rc = smb2_create_sd_buffer(work, req, &path); if (rc) { if (posix_acl_rc) - ksmbd_vfs_set_init_posix_acl(inode); + ksmbd_vfs_set_init_posix_acl(mnt_user_ns(path.mnt), + inode); if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) { @@ -2845,15 +2858,17 @@ int smb2_open(struct ksmbd_work *work) if (!pntsd) goto err_out; - rc = build_sec_desc(pntsd, NULL, + rc = build_sec_desc(mnt_user_ns(path.mnt), + pntsd, NULL, OWNER_SECINFO | - GROUP_SECINFO | - DACL_SECINFO, + GROUP_SECINFO | + DACL_SECINFO, &pntsd_size, &fattr); posix_acl_release(fattr.cf_acls); posix_acl_release(fattr.cf_dacls); rc = ksmbd_vfs_set_sd_xattr(conn, + mnt_user_ns(path.mnt), path.dentry, pntsd, pntsd_size); @@ -2895,7 +2910,7 @@ int smb2_open(struct ksmbd_work *work) rc = ksmbd_vfs_getattr(&path, &stat); if (rc) { - generic_fillattr(&init_user_ns, d_inode(path.dentry), &stat); + generic_fillattr(mnt_user_ns(path.mnt), d_inode(path.dentry), &stat); rc = 0; } @@ -2996,7 +3011,8 @@ int smb2_open(struct ksmbd_work *work) memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); - generic_fillattr(&init_user_ns, file_inode(fp->filp), &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), + &stat); rsp->StructureSize = cpu_to_le16(89); rcu_read_lock(); @@ -3048,7 +3064,8 @@ int smb2_open(struct ksmbd_work *work) struct create_context *mxac_ccontext; if (maximal_access == 0) - ksmbd_vfs_query_maximal_access(path.dentry, + ksmbd_vfs_query_maximal_access(mnt_user_ns(path.mnt), + path.dentry, &maximal_access); mxac_ccontext = (struct create_context *)(rsp->Buffer + le32_to_cpu(rsp->CreateContextsLength)); @@ -3251,6 +3268,7 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level) * @conn: connection instance * @info_level: smb information level * @d_info: structure included variables for query dir + * @user_ns: user namespace * @ksmbd_kstat: ksmbd wrapper of dirent stat information * * if directory has many entries, find first can't read it fully. @@ -3260,6 +3278,7 @@ 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; @@ -3412,9 +3431,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(&init_user_ns, ksmbd_kstat->kstat->uid), + id_to_sid(from_kuid(user_ns, ksmbd_kstat->kstat->uid), SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]); - id_to_sid(from_kgid(&init_user_ns, ksmbd_kstat->kstat->gid), + id_to_sid(from_kgid(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); @@ -3496,12 +3515,14 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv) ksmbd_kstat.kstat = &kstat; if (priv->info_level != FILE_NAMES_INFORMATION) ksmbd_vfs_fill_dentry_attrs(priv->work, + file_mnt_user_ns(priv->dir_fp->filp), dent, &ksmbd_kstat); rc = smb2_populate_readdir_entry(priv->work->conn, priv->info_level, priv->d_info, + file_mnt_user_ns(priv->dir_fp->filp), &ksmbd_kstat); dput(dent); if (rc) @@ -3710,7 +3731,8 @@ int smb2_query_dir(struct ksmbd_work *work) } if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) || - inode_permission(&init_user_ns, file_inode(dir_fp->filp), + inode_permission(file_mnt_user_ns(dir_fp->filp), + file_inode(dir_fp->filp), MAY_READ | MAY_EXEC)) { pr_err("no right to enumerate directory (%pd)\n", dir_fp->filp->f_path.dentry); @@ -4035,7 +4057,8 @@ static int smb2_get_ea(struct ksmbd_work *work, struct ksmbd_file *fp, buf_free_len -= (offsetof(struct smb2_ea_info, name) + name_len + 1); /* bailout if xattr can't fit in buf_free_len */ - value_len = ksmbd_vfs_getxattr(path->dentry, name, &buf); + value_len = ksmbd_vfs_getxattr(mnt_user_ns(path->mnt), + path->dentry, name, &buf); if (value_len <= 0) { rc = -ENOENT; rsp->hdr.Status = STATUS_INVALID_HANDLE; @@ -4124,7 +4147,8 @@ static int get_file_basic_info(struct smb2_query_info_rsp *rsp, } basic_info = (struct smb2_file_all_info *)rsp->Buffer; - generic_fillattr(&init_user_ns, file_inode(fp->filp), &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), + &stat); basic_info->CreationTime = cpu_to_le64(fp->create_time); time = ksmbd_UnixTimeToNT(stat.atime); basic_info->LastAccessTime = cpu_to_le64(time); @@ -4165,7 +4189,7 @@ static void get_file_standard_info(struct smb2_query_info_rsp *rsp, struct kstat stat; inode = file_inode(fp->filp); - generic_fillattr(&init_user_ns, inode, &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat); sinfo = (struct smb2_file_standard_info *)rsp->Buffer; delete_pending = ksmbd_inode_pending_delete(fp); @@ -4220,7 +4244,7 @@ static int get_file_all_info(struct ksmbd_work *work, return -ENOMEM; inode = file_inode(fp->filp); - generic_fillattr(&init_user_ns, inode, &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat); ksmbd_debug(SMB, "filename = %s\n", filename); delete_pending = ksmbd_inode_pending_delete(fp); @@ -4295,7 +4319,8 @@ static void get_file_stream_info(struct ksmbd_work *work, ssize_t xattr_list_len; int nbytes = 0, streamlen, stream_name_len, next, idx = 0; - generic_fillattr(&init_user_ns, file_inode(fp->filp), &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), + &stat); file_info = (struct smb2_file_stream_info *)rsp->Buffer; xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list); @@ -4374,7 +4399,8 @@ static void get_file_internal_info(struct smb2_query_info_rsp *rsp, struct smb2_file_internal_info *file_info; struct kstat stat; - generic_fillattr(&init_user_ns, file_inode(fp->filp), &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), + &stat); file_info = (struct smb2_file_internal_info *)rsp->Buffer; file_info->IndexNumber = cpu_to_le64(stat.ino); rsp->OutputBufferLength = @@ -4399,7 +4425,7 @@ static int get_file_network_open_info(struct smb2_query_info_rsp *rsp, file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer; inode = file_inode(fp->filp); - generic_fillattr(&init_user_ns, inode, &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), inode, &stat); file_info->CreationTime = cpu_to_le64(fp->create_time); time = ksmbd_UnixTimeToNT(stat.atime); @@ -4460,7 +4486,8 @@ static void get_file_compression_info(struct smb2_query_info_rsp *rsp, struct smb2_file_comp_info *file_info; struct kstat stat; - generic_fillattr(&init_user_ns, file_inode(fp->filp), &stat); + generic_fillattr(file_mnt_user_ns(fp->filp), file_inode(fp->filp), + &stat); file_info = (struct smb2_file_comp_info *)rsp->Buffer; file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9); @@ -4933,9 +4960,11 @@ static int smb2_get_info_sec(struct ksmbd_work *work, if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) - ksmbd_vfs_get_sd_xattr(work->conn, fp->filp->f_path.dentry, &ppntsd); + ksmbd_vfs_get_sd_xattr(work->conn, file_mnt_user_ns(fp->filp), + fp->filp->f_path.dentry, &ppntsd); - rc = build_sec_desc(pntsd, ppntsd, addition_info, &secdesclen, &fattr); + rc = build_sec_desc(file_mnt_user_ns(fp->filp), + pntsd, ppntsd, addition_info, &secdesclen, &fattr); posix_acl_release(fattr.cf_acls); posix_acl_release(fattr.cf_dacls); kfree(ppntsd); @@ -5228,7 +5257,8 @@ static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp, if (rc) goto out; - rc = ksmbd_vfs_setxattr(fp->filp->f_path.dentry, + rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp), + fp->filp->f_path.dentry, xattr_stream_name, NULL, 0, 0); if (rc < 0) { @@ -5412,7 +5442,8 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME | XATTR_DOSINFO_ITIME; - rc = ksmbd_vfs_set_dos_attrib_xattr(filp->f_path.dentry, &da); + rc = ksmbd_vfs_set_dos_attrib_xattr(file_mnt_user_ns(filp), + filp->f_path.dentry, &da); if (rc) ksmbd_debug(SMB, "failed to restore file attribute in EA\n"); @@ -5433,14 +5464,14 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) return -EACCES; - rc = setattr_prepare(&init_user_ns, dentry, &attrs); + rc = setattr_prepare(file_mnt_user_ns(filp), dentry, &attrs); if (rc) return -EINVAL; inode_lock(inode); - setattr_copy(&init_user_ns, inode, &attrs); + setattr_copy(file_mnt_user_ns(filp), inode, &attrs); attrs.ia_valid &= ~ATTR_CTIME; - rc = notify_change(&init_user_ns, dentry, &attrs, NULL); + rc = notify_change(file_mnt_user_ns(filp), dentry, &attrs, NULL); inode_unlock(inode); } return 0; @@ -7188,12 +7219,14 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) { struct xattr_dos_attrib da; - ret = ksmbd_vfs_get_dos_attrib_xattr(fp->filp->f_path.dentry, &da); + ret = ksmbd_vfs_get_dos_attrib_xattr(file_mnt_user_ns(fp->filp), + fp->filp->f_path.dentry, &da); if (ret <= 0) goto out; da.attr = le32_to_cpu(fp->f_ci->m_fattr); - ret = ksmbd_vfs_set_dos_attrib_xattr(fp->filp->f_path.dentry, &da); + ret = ksmbd_vfs_set_dos_attrib_xattr(file_mnt_user_ns(fp->filp), + fp->filp->f_path.dentry, &da); if (ret) fp->f_ci->m_fattr = old_fattr; } diff --git a/fs/ksmbd/smb_common.c b/fs/ksmbd/smb_common.c index b573575..f770f3f 100644 --- a/fs/ksmbd/smb_common.c +++ b/fs/ksmbd/smb_common.c @@ -274,6 +274,7 @@ 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; @@ -300,9 +301,11 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, ksmbd_kstat.kstat = &kstat; ksmbd_vfs_fill_dentry_attrs(work, + file_mnt_user_ns(dir->filp), dir->filp->f_path.dentry->d_parent, &ksmbd_kstat); - rc = fn(conn, info_level, d_info, &ksmbd_kstat); + rc = fn(conn, info_level, d_info, + file_mnt_user_ns(dir->filp), &ksmbd_kstat); if (rc) break; if (d_info->out_buf_len <= 0) diff --git a/fs/ksmbd/smb_common.h b/fs/ksmbd/smb_common.h index 8489b92..6ab28aa3 100644 --- a/fs/ksmbd/smb_common.h +++ b/fs/ksmbd/smb_common.h @@ -514,6 +514,7 @@ 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, diff --git a/fs/ksmbd/smbacl.c b/fs/ksmbd/smbacl.c index e0825d3..4ee714b 100644 --- a/fs/ksmbd/smbacl.c +++ b/fs/ksmbd/smbacl.c @@ -253,7 +253,8 @@ void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid) ssid->num_subauth++; } -static int sid_to_id(struct smb_sid *psid, uint sidtype, +static int sid_to_id(struct user_namespace *user_ns, + struct smb_sid *psid, uint sidtype, struct smb_fattr *fattr) { int rc = -EINVAL; @@ -274,8 +275,8 @@ static int sid_to_id(struct smb_sid *psid, uint sidtype, id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]); if (id > 0) { - uid = make_kuid(&init_user_ns, id); - if (uid_valid(uid) && kuid_has_mapping(&init_user_ns, uid)) { + uid = make_kuid(user_ns, id); + if (uid_valid(uid) && kuid_has_mapping(user_ns, uid)) { fattr->cf_uid = uid; rc = 0; } @@ -286,8 +287,8 @@ static int sid_to_id(struct smb_sid *psid, uint sidtype, id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]); if (id > 0) { - gid = make_kgid(&init_user_ns, id); - if (gid_valid(gid) && kgid_has_mapping(&init_user_ns, gid)) { + gid = make_kgid(user_ns, id); + if (gid_valid(gid) && kgid_has_mapping(user_ns, gid)) { fattr->cf_gid = gid; rc = 0; } @@ -362,7 +363,8 @@ void free_acl_state(struct posix_acl_state *state) kfree(state->groups); } -static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, +static void parse_dacl(struct user_namespace *user_ns, + struct smb_acl *pdacl, char *end_of_acl, struct smb_sid *pownersid, struct smb_sid *pgrpsid, struct smb_fattr *fattr) { @@ -474,7 +476,7 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, acl_mode = access_flags_to_mode(fattr, ppace[i]->access_req, ppace[i]->type); temp_fattr.cf_uid = INVALID_UID; - ret = sid_to_id(&ppace[i]->sid, SIDOWNER, &temp_fattr); + ret = sid_to_id(user_ns, &ppace[i]->sid, SIDOWNER, &temp_fattr); if (ret || uid_eq(temp_fattr.cf_uid, INVALID_UID)) { pr_err("%s: Error %d mapping Owner SID to uid\n", __func__, ret); @@ -553,7 +555,8 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl, free_acl_state(&default_acl_state); } -static void set_posix_acl_entries_dacl(struct smb_ace *pndace, +static void set_posix_acl_entries_dacl(struct user_namespace *user_ns, + struct smb_ace *pndace, struct smb_fattr *fattr, u32 *num_aces, u16 *size, u32 nt_aces_num) { @@ -577,14 +580,14 @@ static void set_posix_acl_entries_dacl(struct smb_ace *pndace, uid_t uid; unsigned int sid_type = SIDOWNER; - uid = from_kuid(&init_user_ns, pace->e_uid); + uid = from_kuid(user_ns, pace->e_uid); 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(&init_user_ns, pace->e_gid); + gid = from_kgid(user_ns, pace->e_gid); id_to_sid(gid, SIDUNIX_GROUP, sid); } else if (pace->e_tag == ACL_OTHER && !nt_aces_num) { smb_copy_sid(sid, &sid_everyone); @@ -643,12 +646,12 @@ posix_default_acl: if (pace->e_tag == ACL_USER) { uid_t uid; - uid = from_kuid(&init_user_ns, pace->e_uid); + uid = from_kuid(user_ns, pace->e_uid); id_to_sid(uid, SIDCREATOR_OWNER, sid); } else if (pace->e_tag == ACL_GROUP) { gid_t gid; - gid = from_kgid(&init_user_ns, pace->e_gid); + gid = from_kgid(user_ns, pace->e_gid); id_to_sid(gid, SIDCREATOR_GROUP, sid); } else { kfree(sid); @@ -666,7 +669,9 @@ posix_default_acl: } } -static void set_ntacl_dacl(struct smb_acl *pndacl, struct smb_acl *nt_dacl, +static void set_ntacl_dacl(struct user_namespace *user_ns, + struct smb_acl *pndacl, + struct smb_acl *nt_dacl, const struct smb_sid *pownersid, const struct smb_sid *pgrpsid, struct smb_fattr *fattr) @@ -687,12 +692,14 @@ static void set_ntacl_dacl(struct smb_acl *pndacl, struct smb_acl *nt_dacl, } } - set_posix_acl_entries_dacl(pndace, fattr, &num_aces, &size, nt_num_aces); + set_posix_acl_entries_dacl(user_ns, pndace, fattr, + &num_aces, &size, nt_num_aces); pndacl->num_aces = cpu_to_le32(num_aces); pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size); } -static void set_mode_dacl(struct smb_acl *pndacl, struct smb_fattr *fattr) +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; @@ -703,12 +710,13 @@ static void set_mode_dacl(struct smb_acl *pndacl, struct smb_fattr *fattr) pace = pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl)); if (fattr->cf_acls) { - set_posix_acl_entries_dacl(pndace, fattr, &num_aces, &size, num_aces); + set_posix_acl_entries_dacl(user_ns, pndace, fattr, + &num_aces, &size, num_aces); goto out; } /* owner RID */ - uid = from_kuid(&init_user_ns, fattr->cf_uid); + uid = from_kuid(user_ns, fattr->cf_uid); if (uid) sid = &server_conf.domain_sid; else @@ -725,7 +733,7 @@ static void set_mode_dacl(struct smb_acl *pndacl, struct smb_fattr *fattr) 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(&init_user_ns, fattr->cf_gid)); + cpu_to_le32(from_kgid(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); @@ -771,8 +779,8 @@ static int parse_sid(struct smb_sid *psid, char *end_of_acl) } /* Convert CIFS ACL to POSIX form */ -int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len, - struct smb_fattr *fattr) +int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, + int acl_len, struct smb_fattr *fattr) { int rc = 0; struct smb_sid *owner_sid_ptr, *group_sid_ptr; @@ -811,7 +819,7 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len, return rc; } - rc = sid_to_id(owner_sid_ptr, SIDOWNER, fattr); + rc = sid_to_id(user_ns, owner_sid_ptr, SIDOWNER, fattr); if (rc) { pr_err("%s: Error %d mapping Owner SID to uid\n", __func__, rc); @@ -826,7 +834,7 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len, __func__, rc); return rc; } - rc = sid_to_id(group_sid_ptr, SIDUNIX_GROUP, fattr); + rc = sid_to_id(user_ns, group_sid_ptr, SIDUNIX_GROUP, fattr); if (rc) { pr_err("%s: Error %d mapping Group SID to gid\n", __func__, rc); @@ -841,15 +849,16 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len, pntsd->type |= cpu_to_le16(DACL_PROTECTED); if (dacloffset) { - parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, - fattr); + parse_dacl(user_ns, dacl_ptr, end_of_acl, + owner_sid_ptr, group_sid_ptr, fattr); } return 0; } /* Convert permission bits from mode to equivalent CIFS ACL */ -int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, +int build_sec_desc(struct user_namespace *user_ns, + struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, int addition_info, __u32 *secdesclen, struct smb_fattr *fattr) { @@ -866,7 +875,7 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, if (!nowner_sid_ptr) return -ENOMEM; - uid = from_kuid(&init_user_ns, fattr->cf_uid); + uid = from_kuid(user_ns, fattr->cf_uid); if (!uid) sid_type = SIDUNIX_USER; id_to_sid(uid, sid_type, nowner_sid_ptr); @@ -877,7 +886,7 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, return -ENOMEM; } - gid = from_kgid(&init_user_ns, fattr->cf_gid); + gid = from_kgid(user_ns, fattr->cf_gid); id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr); offset = sizeof(struct smb_ntsd); @@ -909,7 +918,7 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, dacl_ptr->num_aces = 0; if (!ppntsd) { - set_mode_dacl(dacl_ptr, fattr); + set_mode_dacl(user_ns, dacl_ptr, fattr); } else if (!ppntsd->dacloffset) { goto out; } else { @@ -917,8 +926,8 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, ppdacl_ptr = (struct smb_acl *)((char *)ppntsd + le32_to_cpu(ppntsd->dacloffset)); - set_ntacl_dacl(dacl_ptr, ppdacl_ptr, nowner_sid_ptr, - ngroup_sid_ptr, fattr); + set_ntacl_dacl(user_ns, dacl_ptr, ppdacl_ptr, + nowner_sid_ptr, ngroup_sid_ptr, fattr); } pntsd->dacloffset = cpu_to_le32(offset); offset += le16_to_cpu(dacl_ptr->size); @@ -956,7 +965,8 @@ int smb_inherit_dacl(struct ksmbd_conn *conn, char *aces_base; bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode); - acl_len = ksmbd_vfs_get_sd_xattr(conn, parent, &parent_pntsd); + acl_len = ksmbd_vfs_get_sd_xattr(conn, mnt_user_ns(path->mnt), + parent, &parent_pntsd); if (acl_len <= 0) return rc; dacloffset = le32_to_cpu(parent_pntsd->dacloffset); @@ -1087,7 +1097,8 @@ pass: pntsd_size += sizeof(struct smb_acl) + nt_size; } - ksmbd_vfs_set_sd_xattr(conn, path->dentry, pntsd, pntsd_size); + ksmbd_vfs_set_sd_xattr(conn, mnt_user_ns(path->mnt), + path->dentry, pntsd, pntsd_size); kfree(pntsd); rc = 0; } @@ -1128,7 +1139,8 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path, char *end_of_acl; ksmbd_debug(SMB, "check permission using windows acl\n"); - acl_size = ksmbd_vfs_get_sd_xattr(conn, path->dentry, &pntsd); + acl_size = ksmbd_vfs_get_sd_xattr(conn, mnt_user_ns(path->mnt), + path->dentry, &pntsd); if (acl_size <= 0 || !pntsd || !pntsd->dacloffset) { kfree(pntsd); return 0; @@ -1209,9 +1221,11 @@ 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(&init_user_ns, pa_entry->e_uid); + id = from_kuid(mnt_user_ns(path->mnt), + pa_entry->e_uid); else if (pa_entry->e_tag == ACL_GROUP) - id = from_kgid(&init_user_ns, pa_entry->e_gid); + id = from_kgid(mnt_user_ns(path->mnt), + pa_entry->e_gid); else continue; @@ -1273,7 +1287,7 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, fattr.cf_gid = INVALID_GID; fattr.cf_mode = inode->i_mode; - rc = parse_sec_desc(pntsd, ntsd_len, &fattr); + rc = parse_sec_desc(mnt_user_ns(path->mnt), pntsd, ntsd_len, &fattr); if (rc) goto out; @@ -1284,13 +1298,13 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, inode->i_gid = fattr.cf_gid; mark_inode_dirty(inode); - ksmbd_vfs_remove_acl_xattrs(path->dentry); + ksmbd_vfs_remove_acl_xattrs(mnt_user_ns(path->mnt), path->dentry); /* Update posix acls */ if (fattr.cf_dacls) { - rc = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS, - fattr.cf_acls); + rc = set_posix_acl(mnt_user_ns(path->mnt), inode, + ACL_TYPE_ACCESS, fattr.cf_acls); if (S_ISDIR(inode->i_mode) && fattr.cf_dacls) - rc = set_posix_acl(&init_user_ns, inode, + rc = set_posix_acl(mnt_user_ns(path->mnt), inode, ACL_TYPE_DEFAULT, fattr.cf_dacls); } @@ -1300,8 +1314,9 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) { /* Update WinACL in xattr */ - ksmbd_vfs_remove_sd_xattrs(path->dentry); - ksmbd_vfs_set_sd_xattr(conn, path->dentry, pntsd, ntsd_len); + ksmbd_vfs_remove_sd_xattrs(mnt_user_ns(path->mnt), path->dentry); + ksmbd_vfs_set_sd_xattr(conn, mnt_user_ns(path->mnt), + path->dentry, pntsd, ntsd_len); } out: diff --git a/fs/ksmbd/smbacl.h b/fs/ksmbd/smbacl.h index 4ee7bda3..940f686 100644 --- a/fs/ksmbd/smbacl.h +++ b/fs/ksmbd/smbacl.h @@ -189,11 +189,11 @@ struct posix_acl_state { struct posix_ace_state_array *groups; }; -int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len, - struct smb_fattr *fattr); -int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd, - int addition_info, __u32 *secdesclen, - struct smb_fattr *fattr); +int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, + int acl_len, struct smb_fattr *fattr); +int build_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd, + struct smb_ntsd *ppntsd, int addition_info, + __u32 *secdesclen, struct smb_fattr *fattr); int init_acl_state(struct posix_acl_state *state, int cnt); void free_acl_state(struct posix_acl_state *state); void posix_state_to_acl(struct posix_acl_state *state, diff --git a/fs/ksmbd/vfs.c b/fs/ksmbd/vfs.c index 7021662..0f5a4fb 100644 --- a/fs/ksmbd/vfs.c +++ b/fs/ksmbd/vfs.c @@ -95,7 +95,8 @@ out_err: return ret; } -int ksmbd_vfs_may_delete(struct dentry *dentry) +int ksmbd_vfs_may_delete(struct user_namespace *user_ns, + struct dentry *dentry) { struct dentry *parent; int ret; @@ -107,7 +108,7 @@ int ksmbd_vfs_may_delete(struct dentry *dentry) return ret; } - ret = inode_permission(&init_user_ns, d_inode(parent), + ret = inode_permission(user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE); inode_unlock(d_inode(parent)); @@ -115,23 +116,24 @@ int ksmbd_vfs_may_delete(struct dentry *dentry) return ret; } -int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess) +int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns, + struct dentry *dentry, __le32 *daccess) { struct dentry *parent; int ret = 0; *daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL); - if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE)) + if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_WRITE)) *daccess |= cpu_to_le32(WRITE_DAC | WRITE_OWNER | SYNCHRONIZE | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES | FILE_DELETE_CHILD); - if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_READ)) + if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_READ)) *daccess |= FILE_READ_DATA_LE | FILE_READ_EA_LE; - if (!inode_permission(&init_user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC)) + if (!inode_permission(user_ns, d_inode(dentry), MAY_OPEN | MAY_EXEC)) *daccess |= FILE_EXECUTE_LE; parent = dget_parent(dentry); @@ -141,7 +143,7 @@ int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess) return ret; } - if (!inode_permission(&init_user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE)) + if (!inode_permission(user_ns, d_inode(parent), MAY_EXEC | MAY_WRITE)) *daccess |= FILE_DELETE_LE; inode_unlock(d_inode(parent)); @@ -173,7 +175,8 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode) } mode |= S_IFREG; - err = vfs_create(&init_user_ns, d_inode(path.dentry), dentry, mode, true); + err = vfs_create(mnt_user_ns(path.mnt), d_inode(path.dentry), + dentry, mode, true); if (!err) { ksmbd_vfs_inherit_owner(work, d_inode(path.dentry), d_inode(dentry)); @@ -208,7 +211,8 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode) } mode |= S_IFDIR; - err = vfs_mkdir(&init_user_ns, d_inode(path.dentry), dentry, mode); + err = vfs_mkdir(mnt_user_ns(path.mnt), d_inode(path.dentry), + dentry, mode); if (err) { goto out; } else if (d_unhashed(dentry)) { @@ -236,7 +240,8 @@ out: return err; } -static ssize_t ksmbd_vfs_getcasexattr(struct dentry *dentry, char *attr_name, +static ssize_t ksmbd_vfs_getcasexattr(struct user_namespace *user_ns, + struct dentry *dentry, char *attr_name, int attr_name_len, char **attr_value) { char *name, *xattr_list = NULL; @@ -252,7 +257,8 @@ static ssize_t ksmbd_vfs_getcasexattr(struct dentry *dentry, char *attr_name, if (strncasecmp(attr_name, name, attr_name_len)) continue; - value_len = ksmbd_vfs_getxattr(dentry, + value_len = ksmbd_vfs_getxattr(user_ns, + dentry, name, attr_value); if (value_len < 0) @@ -274,7 +280,8 @@ static int ksmbd_vfs_stream_read(struct ksmbd_file *fp, char *buf, loff_t *pos, ksmbd_debug(VFS, "read stream data pos : %llu, count : %zd\n", *pos, count); - v_len = ksmbd_vfs_getcasexattr(fp->filp->f_path.dentry, + v_len = ksmbd_vfs_getcasexattr(file_mnt_user_ns(fp->filp), + fp->filp->f_path.dentry, fp->stream.name, fp->stream.size, &stream_buf); @@ -411,7 +418,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, count = (*pos + count) - XATTR_SIZE_MAX; } - v_len = ksmbd_vfs_getcasexattr(fp->filp->f_path.dentry, + v_len = ksmbd_vfs_getcasexattr(file_mnt_user_ns(fp->filp), + fp->filp->f_path.dentry, fp->stream.name, fp->stream.size, &stream_buf); @@ -436,7 +444,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos, memcpy(&stream_buf[*pos], buf, count); - err = ksmbd_vfs_setxattr(fp->filp->f_path.dentry, + err = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp), + fp->filp->f_path.dentry, fp->stream.name, (void *)stream_buf, size, @@ -606,13 +615,14 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name) } if (S_ISDIR(d_inode(path.dentry)->i_mode)) { - err = vfs_rmdir(&init_user_ns, d_inode(parent), path.dentry); + err = vfs_rmdir(mnt_user_ns(path.mnt), d_inode(parent), + path.dentry); if (err && err != -ENOTEMPTY) ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name, err); } else { - err = vfs_unlink(&init_user_ns, d_inode(parent), path.dentry, - NULL); + err = vfs_unlink(mnt_user_ns(path.mnt), d_inode(parent), + path.dentry, NULL); if (err) ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name, err); @@ -669,7 +679,8 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname, goto out3; } - err = vfs_link(oldpath.dentry, &init_user_ns, d_inode(newpath.dentry), + err = vfs_link(oldpath.dentry, mnt_user_ns(newpath.mnt), + d_inode(newpath.dentry), dentry, NULL); if (err) ksmbd_debug(VFS, "vfs_link failed err %d\n", err); @@ -707,8 +718,10 @@ static int ksmbd_validate_entry_in_use(struct dentry *src_dent) } static int __ksmbd_vfs_rename(struct ksmbd_work *work, + struct user_namespace *src_user_ns, struct dentry *src_dent_parent, struct dentry *src_dent, + struct user_namespace *dst_user_ns, struct dentry *dst_dent_parent, struct dentry *trap_dent, char *dst_name) @@ -744,10 +757,10 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work, err = -ENOTEMPTY; if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) { struct renamedata rd = { - .old_mnt_userns = &init_user_ns, + .old_mnt_userns = src_user_ns, .old_dir = d_inode(src_dent_parent), .old_dentry = src_dent, - .new_mnt_userns = &init_user_ns, + .new_mnt_userns = dst_user_ns, .new_dir = d_inode(dst_dent_parent), .new_dentry = dst_dent, }; @@ -809,8 +822,10 @@ 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), src_dent_parent, src_dent, + mnt_user_ns(dst_path.mnt), dst_dent_parent, trap_dent, dst_name); @@ -917,27 +932,30 @@ ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list) return size; } -static ssize_t ksmbd_vfs_xattr_len(struct dentry *dentry, char *xattr_name) +static ssize_t ksmbd_vfs_xattr_len(struct user_namespace *user_ns, + struct dentry *dentry, char *xattr_name) { - return vfs_getxattr(&init_user_ns, dentry, xattr_name, NULL, 0); + return vfs_getxattr(user_ns, dentry, xattr_name, NULL, 0); } /** * ksmbd_vfs_getxattr() - vfs helper for smb get extended attributes value + * @user_ns: user namespace * @dentry: dentry of file for getting xattrs * @xattr_name: name of xattr name to query * @xattr_buf: destination buffer xattr value * * Return: read xattr value length on success, otherwise error */ -ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name, - char **xattr_buf) +ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns, + struct dentry *dentry, + char *xattr_name, char **xattr_buf) { ssize_t xattr_len; char *buf; *xattr_buf = NULL; - xattr_len = ksmbd_vfs_xattr_len(dentry, xattr_name); + xattr_len = ksmbd_vfs_xattr_len(user_ns, dentry, xattr_name); if (xattr_len < 0) return xattr_len; @@ -945,7 +963,7 @@ ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name, if (!buf) return -ENOMEM; - xattr_len = vfs_getxattr(&init_user_ns, dentry, xattr_name, + xattr_len = vfs_getxattr(user_ns, dentry, xattr_name, (void *)buf, xattr_len); if (xattr_len > 0) *xattr_buf = buf; @@ -956,6 +974,7 @@ ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name, /** * ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value + * @user_ns: user namespace * @dentry: dentry to set XATTR at * @name: xattr name for setxattr * @value: xattr value to set @@ -964,12 +983,14 @@ ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name, * * Return: 0 on success, otherwise error */ -int ksmbd_vfs_setxattr(struct dentry *dentry, const char *attr_name, +int ksmbd_vfs_setxattr(struct user_namespace *user_ns, + struct dentry *dentry, const char *attr_name, const void *attr_value, size_t attr_size, int flags) { int err; - err = vfs_setxattr(&init_user_ns, dentry, + err = vfs_setxattr(user_ns, + dentry, attr_name, attr_value, attr_size, @@ -1076,12 +1097,14 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length, return ret; } -int ksmbd_vfs_remove_xattr(struct dentry *dentry, char *attr_name) +int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns, + struct dentry *dentry, char *attr_name) { - return vfs_removexattr(&init_user_ns, dentry, attr_name); + return vfs_removexattr(user_ns, dentry, attr_name); } -int ksmbd_vfs_unlink(struct dentry *dir, struct dentry *dentry) +int ksmbd_vfs_unlink(struct user_namespace *user_ns, + struct dentry *dir, struct dentry *dentry) { int err = 0; @@ -1091,9 +1114,9 @@ int ksmbd_vfs_unlink(struct dentry *dir, struct dentry *dentry) dget(dentry); if (S_ISDIR(d_inode(dentry)->i_mode)) - err = vfs_rmdir(&init_user_ns, d_inode(dir), dentry); + err = vfs_rmdir(user_ns, d_inode(dir), dentry); else - err = vfs_unlink(&init_user_ns, d_inode(dir), dentry, NULL); + err = vfs_unlink(user_ns, d_inode(dir), dentry, NULL); dput(dentry); inode_unlock(d_inode(dir)); @@ -1267,7 +1290,8 @@ out: return err; } -int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry) +int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns, + struct dentry *dentry) { char *name, *xattr_list = NULL; ssize_t xattr_list_len; @@ -1289,7 +1313,7 @@ int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry) sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) || !strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) { - err = ksmbd_vfs_remove_xattr(dentry, name); + err = ksmbd_vfs_remove_xattr(user_ns, dentry, name); if (err) ksmbd_debug(SMB, "remove acl xattr failed : %s\n", name); @@ -1300,7 +1324,8 @@ out: return err; } -int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry) +int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns, + struct dentry *dentry) { char *name, *xattr_list = NULL; ssize_t xattr_list_len; @@ -1319,7 +1344,7 @@ int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry) ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name)); if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) { - err = ksmbd_vfs_remove_xattr(dentry, name); + err = ksmbd_vfs_remove_xattr(user_ns, dentry, name); if (err) ksmbd_debug(SMB, "remove xattr failed : %s\n", name); } @@ -1329,7 +1354,8 @@ out: return err; } -static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode, +static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespace *user_ns, + struct inode *inode, int acl_type) { struct xattr_smb_acl *smb_acl = NULL; @@ -1355,14 +1381,14 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode, switch (pa_entry->e_tag) { case ACL_USER: xa_entry->type = SMB_ACL_USER; - xa_entry->uid = from_kuid(&init_user_ns, pa_entry->e_uid); + xa_entry->uid = from_kuid(user_ns, pa_entry->e_uid); 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(&init_user_ns, pa_entry->e_gid); + xa_entry->gid = from_kgid(user_ns, pa_entry->e_gid); break; case ACL_GROUP_OBJ: xa_entry->type = SMB_ACL_GROUP_OBJ; @@ -1390,7 +1416,9 @@ out: return smb_acl; } -int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry, +int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, + struct user_namespace *user_ns, + struct dentry *dentry, struct smb_ntsd *pntsd, int len) { int rc; @@ -1422,12 +1450,14 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry, return rc; } - smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode, ACL_TYPE_ACCESS); + smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode, + ACL_TYPE_ACCESS); if (S_ISDIR(inode->i_mode)) - def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode, + def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT); - rc = ndr_encode_posix_acl(&acl_ndr, inode, smb_acl, def_smb_acl); + rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, + smb_acl, def_smb_acl); if (rc) { pr_err("failed to encode ndr to posix acl\n"); goto out; @@ -1446,7 +1476,8 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry, goto out; } - rc = ksmbd_vfs_setxattr(dentry, XATTR_NAME_SD, sd_ndr.data, + rc = ksmbd_vfs_setxattr(user_ns, dentry, + XATTR_NAME_SD, sd_ndr.data, sd_ndr.offset, 0); if (rc < 0) pr_err("Failed to store XATTR ntacl :%d\n", rc); @@ -1459,13 +1490,15 @@ out: return rc; } -int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry, +int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, + struct user_namespace *user_ns, + struct dentry *dentry, struct smb_ntsd **pntsd) { int rc; struct ndr n; - rc = ksmbd_vfs_getxattr(dentry, XATTR_NAME_SD, &n.data); + rc = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_SD, &n.data); if (rc > 0) { struct inode *inode = d_inode(dentry); struct ndr acl_ndr = {0}; @@ -1478,13 +1511,15 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry, if (rc) return rc; - smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode, + smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, inode, ACL_TYPE_ACCESS); if (S_ISDIR(inode->i_mode)) - def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(inode, + def_smb_acl = ksmbd_vfs_make_xattr_posix_acl(user_ns, + inode, ACL_TYPE_DEFAULT); - rc = ndr_encode_posix_acl(&acl_ndr, inode, smb_acl, def_smb_acl); + rc = ndr_encode_posix_acl(&acl_ndr, user_ns, inode, + smb_acl, def_smb_acl); if (rc) { pr_err("failed to encode ndr to posix acl\n"); goto out; @@ -1522,7 +1557,8 @@ out: return rc; } -int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry, +int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns, + struct dentry *dentry, struct xattr_dos_attrib *da) { struct ndr n; @@ -1532,7 +1568,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry, if (err) return err; - err = ksmbd_vfs_setxattr(dentry, XATTR_NAME_DOS_ATTRIBUTE, + err = ksmbd_vfs_setxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE, (void *)n.data, n.offset, 0); if (err) ksmbd_debug(SMB, "failed to store dos attribute in xattr\n"); @@ -1541,13 +1577,14 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry, return err; } -int ksmbd_vfs_get_dos_attrib_xattr(struct dentry *dentry, +int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns, + struct dentry *dentry, struct xattr_dos_attrib *da) { struct ndr n; int err; - err = ksmbd_vfs_getxattr(dentry, XATTR_NAME_DOS_ATTRIBUTE, + err = ksmbd_vfs_getxattr(user_ns, dentry, XATTR_NAME_DOS_ATTRIBUTE, (char **)&n.data); if (err > 0) { n.length = err; @@ -1593,13 +1630,15 @@ void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat) return info; } -int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry, +int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, + struct user_namespace *user_ns, + struct dentry *dentry, struct ksmbd_kstat *ksmbd_kstat) { u64 time; int rc; - generic_fillattr(&init_user_ns, d_inode(dentry), ksmbd_kstat->kstat); + generic_fillattr(user_ns, d_inode(dentry), ksmbd_kstat->kstat); time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime); ksmbd_kstat->create_time = time; @@ -1617,7 +1656,7 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry, KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) { struct xattr_dos_attrib da; - rc = ksmbd_vfs_get_dos_attrib_xattr(dentry, &da); + rc = ksmbd_vfs_get_dos_attrib_xattr(user_ns, dentry, &da); if (rc > 0) { ksmbd_kstat->file_attributes = cpu_to_le32(da.attr); ksmbd_kstat->create_time = da.create_time; @@ -1629,7 +1668,8 @@ int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry, return 0; } -ssize_t ksmbd_vfs_casexattr_len(struct dentry *dentry, char *attr_name, +ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns, + struct dentry *dentry, char *attr_name, int attr_name_len) { char *name, *xattr_list = NULL; @@ -1645,7 +1685,7 @@ ssize_t ksmbd_vfs_casexattr_len(struct dentry *dentry, char *attr_name, if (strncasecmp(attr_name, name, attr_name_len)) continue; - value_len = ksmbd_vfs_xattr_len(dentry, name); + value_len = ksmbd_vfs_xattr_len(user_ns, dentry, name); break; } @@ -1775,7 +1815,8 @@ void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock) locks_delete_block(flock); } -int ksmbd_vfs_set_init_posix_acl(struct inode *inode) +int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns, + struct inode *inode) { struct posix_acl_state acl_state; struct posix_acl *acls; @@ -1804,13 +1845,13 @@ int ksmbd_vfs_set_init_posix_acl(struct inode *inode) return -ENOMEM; } posix_state_to_acl(&acl_state, acls->a_entries); - rc = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS, acls); + rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls); if (rc < 0) ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n", rc); else if (S_ISDIR(inode->i_mode)) { posix_state_to_acl(&acl_state, acls->a_entries); - rc = set_posix_acl(&init_user_ns, inode, ACL_TYPE_DEFAULT, + rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT, acls); if (rc < 0) ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n", @@ -1821,7 +1862,8 @@ int ksmbd_vfs_set_init_posix_acl(struct inode *inode) return rc; } -int ksmbd_vfs_inherit_posix_acl(struct inode *inode, struct inode *parent_inode) +int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns, + struct inode *inode, struct inode *parent_inode) { struct posix_acl *acls; struct posix_acl_entry *pace; @@ -1839,12 +1881,12 @@ int ksmbd_vfs_inherit_posix_acl(struct inode *inode, struct inode *parent_inode) } } - rc = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS, acls); + rc = set_posix_acl(user_ns, inode, ACL_TYPE_ACCESS, acls); if (rc < 0) ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n", rc); if (S_ISDIR(inode->i_mode)) { - rc = set_posix_acl(&init_user_ns, inode, ACL_TYPE_DEFAULT, + rc = set_posix_acl(user_ns, inode, ACL_TYPE_DEFAULT, acls); if (rc < 0) ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n", diff --git a/fs/ksmbd/vfs.h b/fs/ksmbd/vfs.h index e30174a..b255f90 100644 --- a/fs/ksmbd/vfs.h +++ b/fs/ksmbd/vfs.h @@ -108,8 +108,9 @@ struct ksmbd_kstat { }; int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child); -int ksmbd_vfs_may_delete(struct dentry *dentry); -int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess); +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); 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); int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp, @@ -136,15 +137,20 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work, unsigned int *chunk_size_written, loff_t *total_size_written); ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list); -ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name, +ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns, + struct dentry *dentry, + char *xattr_name, char **xattr_buf); -ssize_t ksmbd_vfs_casexattr_len(struct dentry *dentry, char *attr_name, +ssize_t ksmbd_vfs_casexattr_len(struct user_namespace *user_ns, + struct dentry *dentry, char *attr_name, int attr_name_len); -int ksmbd_vfs_setxattr(struct dentry *dentry, const char *attr_name, +int ksmbd_vfs_setxattr(struct user_namespace *user_ns, + struct dentry *dentry, const char *attr_name, const void *attr_value, size_t attr_size, int flags); int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name, size_t *xattr_stream_name_size, int s_type); -int ksmbd_vfs_remove_xattr(struct dentry *dentry, char *attr_name); +int ksmbd_vfs_remove_xattr(struct user_namespace *user_ns, + struct dentry *dentry, char *attr_name); int ksmbd_vfs_kern_path(char *name, unsigned int flags, struct path *path, bool caseless); int ksmbd_vfs_empty_dir(struct ksmbd_file *fp); @@ -155,24 +161,37 @@ struct file_allocated_range_buffer; int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length, struct file_allocated_range_buffer *ranges, int in_count, int *out_count); -int ksmbd_vfs_unlink(struct dentry *dir, struct dentry *dentry); +int ksmbd_vfs_unlink(struct user_namespace *user_ns, + struct dentry *dir, struct dentry *dentry); void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat); -int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, struct dentry *dentry, +int ksmbd_vfs_fill_dentry_attrs(struct ksmbd_work *work, + struct user_namespace *user_ns, + struct dentry *dentry, struct ksmbd_kstat *ksmbd_kstat); int ksmbd_vfs_posix_lock_wait(struct file_lock *flock); int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout); void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock); -int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry); -int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry); -int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry, +int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns, + struct dentry *dentry); +int ksmbd_vfs_remove_sd_xattrs(struct user_namespace *user_ns, + struct dentry *dentry); +int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, + struct user_namespace *user_ns, + struct dentry *dentry, struct smb_ntsd *pntsd, int len); -int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry, +int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, + struct user_namespace *user_ns, + struct dentry *dentry, struct smb_ntsd **pntsd); -int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry, +int ksmbd_vfs_set_dos_attrib_xattr(struct user_namespace *user_ns, + struct dentry *dentry, struct xattr_dos_attrib *da); -int ksmbd_vfs_get_dos_attrib_xattr(struct dentry *dentry, +int ksmbd_vfs_get_dos_attrib_xattr(struct user_namespace *user_ns, + struct dentry *dentry, struct xattr_dos_attrib *da); -int ksmbd_vfs_set_init_posix_acl(struct inode *inode); -int ksmbd_vfs_inherit_posix_acl(struct inode *inode, +int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns, + struct inode *inode); +int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns, + struct inode *inode, struct inode *parent_inode); #endif /* __KSMBD_VFS_H__ */ diff --git a/fs/ksmbd/vfs_cache.c b/fs/ksmbd/vfs_cache.c index 5c9efcf..1941ad3 100644 --- a/fs/ksmbd/vfs_cache.c +++ b/fs/ksmbd/vfs_cache.c @@ -251,7 +251,8 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp) filp = fp->filp; if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) { ci->m_flags &= ~S_DEL_ON_CLS_STREAM; - err = ksmbd_vfs_remove_xattr(filp->f_path.dentry, + err = ksmbd_vfs_remove_xattr(file_mnt_user_ns(filp), + filp->f_path.dentry, fp->stream.name); if (err) pr_err("remove xattr failed : %s\n", @@ -265,7 +266,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp) dir = dentry->d_parent; ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING); write_unlock(&ci->m_lock); - ksmbd_vfs_unlink(dir, dentry); + ksmbd_vfs_unlink(file_mnt_user_ns(filp), dir, dentry); write_lock(&ci->m_lock); } write_unlock(&ci->m_lock); -- 2.7.4