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 <EXPORT DIR>/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 <EXPORT DIR>/foo. But fail with a bind mount for /home/foo. Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hyunchul Lee <hyc.lee@gmail.com> Signed-off-by: Namjae Jeon <namjae.jeon@samsung.com> Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
ef24c962d0
commit
af34983e83
@ -222,7 +222,9 @@ static int ndr_encode_posix_acl_entry(struct ndr *n, struct xattr_smb_acl *acl)
|
|||||||
return 0;
|
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 *acl,
|
||||||
struct xattr_smb_acl *def_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_int32(n, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ndr_write_int64(n, from_kuid(&init_user_ns, inode->i_uid));
|
ndr_write_int64(n, from_kuid(user_ns, inode->i_uid));
|
||||||
ndr_write_int64(n, from_kgid(&init_user_ns, inode->i_gid));
|
ndr_write_int64(n, from_kgid(user_ns, inode->i_gid));
|
||||||
ndr_write_int32(n, inode->i_mode);
|
ndr_write_int32(n, inode->i_mode);
|
||||||
|
|
||||||
if (acl) {
|
if (acl) {
|
||||||
|
@ -14,8 +14,8 @@ struct ndr {
|
|||||||
|
|
||||||
int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
|
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_decode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da);
|
||||||
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 xattr_smb_acl *acl,
|
struct inode *inode, struct xattr_smb_acl *acl,
|
||||||
struct xattr_smb_acl *def_acl);
|
struct xattr_smb_acl *def_acl);
|
||||||
int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *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);
|
int ndr_encode_v3_ntacl(struct ndr *n, struct xattr_ntacl *acl);
|
||||||
|
@ -1612,9 +1612,9 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp)
|
|||||||
buf->nlink = cpu_to_le32(inode->i_nlink);
|
buf->nlink = cpu_to_le32(inode->i_nlink);
|
||||||
buf->reparse_tag = cpu_to_le32(fp->volatile_id);
|
buf->reparse_tag = cpu_to_le32(fp->volatile_id);
|
||||||
buf->mode = cpu_to_le32(inode->i_mode);
|
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]);
|
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]);
|
SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2081,14 +2081,16 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, struct path *path)
|
|||||||
value = (char *)&eabuf->name + eabuf->EaNameLength + 1;
|
value = (char *)&eabuf->name + eabuf->EaNameLength + 1;
|
||||||
|
|
||||||
if (!eabuf->EaValueLength) {
|
if (!eabuf->EaValueLength) {
|
||||||
rc = ksmbd_vfs_casexattr_len(path->dentry,
|
rc = ksmbd_vfs_casexattr_len(mnt_user_ns(path->mnt),
|
||||||
|
path->dentry,
|
||||||
attr_name,
|
attr_name,
|
||||||
XATTR_USER_PREFIX_LEN +
|
XATTR_USER_PREFIX_LEN +
|
||||||
eabuf->EaNameLength);
|
eabuf->EaNameLength);
|
||||||
|
|
||||||
/* delete the EA only when it exits */
|
/* delete the EA only when it exits */
|
||||||
if (rc > 0) {
|
if (rc > 0) {
|
||||||
rc = ksmbd_vfs_remove_xattr(path->dentry,
|
rc = ksmbd_vfs_remove_xattr(mnt_user_ns(path->mnt),
|
||||||
|
path->dentry,
|
||||||
attr_name);
|
attr_name);
|
||||||
|
|
||||||
if (rc < 0) {
|
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. */
|
/* if the EA doesn't exist, just do nothing. */
|
||||||
rc = 0;
|
rc = 0;
|
||||||
} else {
|
} 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);
|
le16_to_cpu(eabuf->EaValueLength), 0);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
ksmbd_debug(SMB,
|
ksmbd_debug(SMB,
|
||||||
@ -2155,7 +2158,8 @@ static noinline int smb2_set_stream_name_xattr(struct path *path,
|
|||||||
fp->stream.size = xattr_stream_size;
|
fp->stream.size = xattr_stream_size;
|
||||||
|
|
||||||
/* Check if there is stream prefix in xattr space */
|
/* 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_name,
|
||||||
xattr_stream_size);
|
xattr_stream_size);
|
||||||
if (rc >= 0)
|
if (rc >= 0)
|
||||||
@ -2166,7 +2170,8 @@ static noinline int smb2_set_stream_name_xattr(struct path *path,
|
|||||||
return -EBADF;
|
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)
|
if (rc < 0)
|
||||||
pr_err("Failed to store XATTR stream name :%d\n", rc);
|
pr_err("Failed to store XATTR stream name :%d\n", rc);
|
||||||
return 0;
|
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))
|
strncmp(&name[XATTR_USER_PREFIX_LEN], STREAM_PREFIX, STREAM_PREFIX_LEN))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
err = ksmbd_vfs_remove_xattr(path->dentry, name);
|
err = ksmbd_vfs_remove_xattr(mnt_user_ns(path->mnt),
|
||||||
|
path->dentry, name);
|
||||||
if (err)
|
if (err)
|
||||||
ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
|
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 |
|
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
|
||||||
XATTR_DOSINFO_ITIME;
|
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)
|
if (rc)
|
||||||
ksmbd_debug(SMB, "failed to store file attribute into xattr\n");
|
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))
|
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS))
|
||||||
return;
|
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) {
|
if (rc > 0) {
|
||||||
fp->f_ci->m_fattr = cpu_to_le32(da.attr);
|
fp->f_ci->m_fattr = cpu_to_le32(da.attr);
|
||||||
fp->create_time = da.create_time;
|
fp->create_time = da.create_time;
|
||||||
@ -2634,7 +2642,7 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
rc = 0;
|
rc = 0;
|
||||||
} else {
|
} else {
|
||||||
file_present = true;
|
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 (stream_name) {
|
||||||
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
|
if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) {
|
||||||
@ -2695,7 +2703,8 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
if (!file_present) {
|
if (!file_present) {
|
||||||
daccess = cpu_to_le32(GENERIC_ALL_FLAGS);
|
daccess = cpu_to_le32(GENERIC_ALL_FLAGS);
|
||||||
} else {
|
} else {
|
||||||
rc = ksmbd_vfs_query_maximal_access(path.dentry,
|
rc = ksmbd_vfs_query_maximal_access(mnt_user_ns(path.mnt),
|
||||||
|
path.dentry,
|
||||||
&daccess);
|
&daccess);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
@ -2738,7 +2747,7 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
* is already granted.
|
* is already granted.
|
||||||
*/
|
*/
|
||||||
if (daccess & ~(FILE_READ_ATTRIBUTES_LE | FILE_READ_CONTROL_LE)) {
|
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),
|
d_inode(path.dentry),
|
||||||
may_flags);
|
may_flags);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -2746,7 +2755,8 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
|
|
||||||
if ((daccess & FILE_DELETE_LE) ||
|
if ((daccess & FILE_DELETE_LE) ||
|
||||||
(req->CreateOptions & FILE_DELETE_ON_CLOSE_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)
|
if (rc)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
@ -2809,7 +2819,9 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
int posix_acl_rc;
|
int posix_acl_rc;
|
||||||
struct inode *inode = d_inode(path.dentry);
|
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)
|
if (posix_acl_rc)
|
||||||
ksmbd_debug(SMB, "inherit posix acl failed : %d\n", 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);
|
rc = smb2_create_sd_buffer(work, req, &path);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
if (posix_acl_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,
|
if (test_share_config_flag(work->tcon->share_conf,
|
||||||
KSMBD_SHARE_FLAG_ACL_XATTR)) {
|
KSMBD_SHARE_FLAG_ACL_XATTR)) {
|
||||||
@ -2845,15 +2858,17 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
if (!pntsd)
|
if (!pntsd)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
|
|
||||||
rc = build_sec_desc(pntsd, NULL,
|
rc = build_sec_desc(mnt_user_ns(path.mnt),
|
||||||
|
pntsd, NULL,
|
||||||
OWNER_SECINFO |
|
OWNER_SECINFO |
|
||||||
GROUP_SECINFO |
|
GROUP_SECINFO |
|
||||||
DACL_SECINFO,
|
DACL_SECINFO,
|
||||||
&pntsd_size, &fattr);
|
&pntsd_size, &fattr);
|
||||||
posix_acl_release(fattr.cf_acls);
|
posix_acl_release(fattr.cf_acls);
|
||||||
posix_acl_release(fattr.cf_dacls);
|
posix_acl_release(fattr.cf_dacls);
|
||||||
|
|
||||||
rc = ksmbd_vfs_set_sd_xattr(conn,
|
rc = ksmbd_vfs_set_sd_xattr(conn,
|
||||||
|
mnt_user_ns(path.mnt),
|
||||||
path.dentry,
|
path.dentry,
|
||||||
pntsd,
|
pntsd,
|
||||||
pntsd_size);
|
pntsd_size);
|
||||||
@ -2895,7 +2910,7 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
|
|
||||||
rc = ksmbd_vfs_getattr(&path, &stat);
|
rc = ksmbd_vfs_getattr(&path, &stat);
|
||||||
if (rc) {
|
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;
|
rc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2996,7 +3011,8 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
|
|
||||||
memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
|
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);
|
rsp->StructureSize = cpu_to_le16(89);
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
@ -3048,7 +3064,8 @@ int smb2_open(struct ksmbd_work *work)
|
|||||||
struct create_context *mxac_ccontext;
|
struct create_context *mxac_ccontext;
|
||||||
|
|
||||||
if (maximal_access == 0)
|
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);
|
&maximal_access);
|
||||||
mxac_ccontext = (struct create_context *)(rsp->Buffer +
|
mxac_ccontext = (struct create_context *)(rsp->Buffer +
|
||||||
le32_to_cpu(rsp->CreateContextsLength));
|
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
|
* @conn: connection instance
|
||||||
* @info_level: smb information level
|
* @info_level: smb information level
|
||||||
* @d_info: structure included variables for query dir
|
* @d_info: structure included variables for query dir
|
||||||
|
* @user_ns: user namespace
|
||||||
* @ksmbd_kstat: ksmbd wrapper of dirent stat information
|
* @ksmbd_kstat: ksmbd wrapper of dirent stat information
|
||||||
*
|
*
|
||||||
* if directory has many entries, find first can't read it fully.
|
* 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,
|
static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
|
||||||
struct ksmbd_dir_info *d_info,
|
struct ksmbd_dir_info *d_info,
|
||||||
|
struct user_namespace *user_ns,
|
||||||
struct ksmbd_kstat *ksmbd_kstat)
|
struct ksmbd_kstat *ksmbd_kstat)
|
||||||
{
|
{
|
||||||
int next_entry_offset = 0;
|
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;
|
S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE;
|
||||||
if (d_info->hide_dot_file && d_info->name[0] == '.')
|
if (d_info->hide_dot_file && d_info->name[0] == '.')
|
||||||
posix_info->DosAttributes |= ATTR_HIDDEN_LE;
|
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]);
|
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]);
|
SIDNFS_GROUP, (struct smb_sid *)&posix_info->SidBuffer[20]);
|
||||||
memcpy(posix_info->name, conv_name, conv_len);
|
memcpy(posix_info->name, conv_name, conv_len);
|
||||||
posix_info->name_len = cpu_to_le32(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;
|
ksmbd_kstat.kstat = &kstat;
|
||||||
if (priv->info_level != FILE_NAMES_INFORMATION)
|
if (priv->info_level != FILE_NAMES_INFORMATION)
|
||||||
ksmbd_vfs_fill_dentry_attrs(priv->work,
|
ksmbd_vfs_fill_dentry_attrs(priv->work,
|
||||||
|
file_mnt_user_ns(priv->dir_fp->filp),
|
||||||
dent,
|
dent,
|
||||||
&ksmbd_kstat);
|
&ksmbd_kstat);
|
||||||
|
|
||||||
rc = smb2_populate_readdir_entry(priv->work->conn,
|
rc = smb2_populate_readdir_entry(priv->work->conn,
|
||||||
priv->info_level,
|
priv->info_level,
|
||||||
priv->d_info,
|
priv->d_info,
|
||||||
|
file_mnt_user_ns(priv->dir_fp->filp),
|
||||||
&ksmbd_kstat);
|
&ksmbd_kstat);
|
||||||
dput(dent);
|
dput(dent);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -3710,7 +3731,8 @@ int smb2_query_dir(struct ksmbd_work *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(dir_fp->daccess & FILE_LIST_DIRECTORY_LE) ||
|
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)) {
|
MAY_READ | MAY_EXEC)) {
|
||||||
pr_err("no right to enumerate directory (%pd)\n",
|
pr_err("no right to enumerate directory (%pd)\n",
|
||||||
dir_fp->filp->f_path.dentry);
|
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) +
|
buf_free_len -= (offsetof(struct smb2_ea_info, name) +
|
||||||
name_len + 1);
|
name_len + 1);
|
||||||
/* bailout if xattr can't fit in buf_free_len */
|
/* 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) {
|
if (value_len <= 0) {
|
||||||
rc = -ENOENT;
|
rc = -ENOENT;
|
||||||
rsp->hdr.Status = STATUS_INVALID_HANDLE;
|
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;
|
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);
|
basic_info->CreationTime = cpu_to_le64(fp->create_time);
|
||||||
time = ksmbd_UnixTimeToNT(stat.atime);
|
time = ksmbd_UnixTimeToNT(stat.atime);
|
||||||
basic_info->LastAccessTime = cpu_to_le64(time);
|
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;
|
struct kstat stat;
|
||||||
|
|
||||||
inode = file_inode(fp->filp);
|
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;
|
sinfo = (struct smb2_file_standard_info *)rsp->Buffer;
|
||||||
delete_pending = ksmbd_inode_pending_delete(fp);
|
delete_pending = ksmbd_inode_pending_delete(fp);
|
||||||
@ -4220,7 +4244,7 @@ static int get_file_all_info(struct ksmbd_work *work,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
inode = file_inode(fp->filp);
|
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);
|
ksmbd_debug(SMB, "filename = %s\n", filename);
|
||||||
delete_pending = ksmbd_inode_pending_delete(fp);
|
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;
|
ssize_t xattr_list_len;
|
||||||
int nbytes = 0, streamlen, stream_name_len, next, idx = 0;
|
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;
|
file_info = (struct smb2_file_stream_info *)rsp->Buffer;
|
||||||
|
|
||||||
xattr_list_len = ksmbd_vfs_listxattr(path->dentry, &xattr_list);
|
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 smb2_file_internal_info *file_info;
|
||||||
struct kstat stat;
|
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 = (struct smb2_file_internal_info *)rsp->Buffer;
|
||||||
file_info->IndexNumber = cpu_to_le64(stat.ino);
|
file_info->IndexNumber = cpu_to_le64(stat.ino);
|
||||||
rsp->OutputBufferLength =
|
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;
|
file_info = (struct smb2_file_ntwrk_info *)rsp->Buffer;
|
||||||
|
|
||||||
inode = file_inode(fp->filp);
|
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);
|
file_info->CreationTime = cpu_to_le64(fp->create_time);
|
||||||
time = ksmbd_UnixTimeToNT(stat.atime);
|
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 smb2_file_comp_info *file_info;
|
||||||
struct kstat stat;
|
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 = (struct smb2_file_comp_info *)rsp->Buffer;
|
||||||
file_info->CompressedFileSize = cpu_to_le64(stat.blocks << 9);
|
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,
|
if (test_share_config_flag(work->tcon->share_conf,
|
||||||
KSMBD_SHARE_FLAG_ACL_XATTR))
|
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_acls);
|
||||||
posix_acl_release(fattr.cf_dacls);
|
posix_acl_release(fattr.cf_dacls);
|
||||||
kfree(ppntsd);
|
kfree(ppntsd);
|
||||||
@ -5228,7 +5257,8 @@ static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
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,
|
xattr_stream_name,
|
||||||
NULL, 0, 0);
|
NULL, 0, 0);
|
||||||
if (rc < 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 |
|
da.flags = XATTR_DOSINFO_ATTRIB | XATTR_DOSINFO_CREATE_TIME |
|
||||||
XATTR_DOSINFO_ITIME;
|
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)
|
if (rc)
|
||||||
ksmbd_debug(SMB,
|
ksmbd_debug(SMB,
|
||||||
"failed to restore file attribute in EA\n");
|
"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))
|
if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
rc = setattr_prepare(&init_user_ns, dentry, &attrs);
|
rc = setattr_prepare(file_mnt_user_ns(filp), dentry, &attrs);
|
||||||
if (rc)
|
if (rc)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
setattr_copy(&init_user_ns, inode, &attrs);
|
setattr_copy(file_mnt_user_ns(filp), inode, &attrs);
|
||||||
attrs.ia_valid &= ~ATTR_CTIME;
|
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);
|
inode_unlock(inode);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -7188,12 +7219,14 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
|
|||||||
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
|
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
|
||||||
struct xattr_dos_attrib da;
|
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)
|
if (ret <= 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
da.attr = le32_to_cpu(fp->f_ci->m_fattr);
|
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)
|
if (ret)
|
||||||
fp->f_ci->m_fattr = old_fattr;
|
fp->f_ci->m_fattr = old_fattr;
|
||||||
}
|
}
|
||||||
|
@ -274,6 +274,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
|
|||||||
char *search_pattern,
|
char *search_pattern,
|
||||||
int (*fn)(struct ksmbd_conn *, int,
|
int (*fn)(struct ksmbd_conn *, int,
|
||||||
struct ksmbd_dir_info *,
|
struct ksmbd_dir_info *,
|
||||||
|
struct user_namespace *,
|
||||||
struct ksmbd_kstat *))
|
struct ksmbd_kstat *))
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
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_kstat.kstat = &kstat;
|
||||||
ksmbd_vfs_fill_dentry_attrs(work,
|
ksmbd_vfs_fill_dentry_attrs(work,
|
||||||
|
file_mnt_user_ns(dir->filp),
|
||||||
dir->filp->f_path.dentry->d_parent,
|
dir->filp->f_path.dentry->d_parent,
|
||||||
&ksmbd_kstat);
|
&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)
|
if (rc)
|
||||||
break;
|
break;
|
||||||
if (d_info->out_buf_len <= 0)
|
if (d_info->out_buf_len <= 0)
|
||||||
|
@ -514,6 +514,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
|
|||||||
int (*fn)(struct ksmbd_conn *,
|
int (*fn)(struct ksmbd_conn *,
|
||||||
int,
|
int,
|
||||||
struct ksmbd_dir_info *,
|
struct ksmbd_dir_info *,
|
||||||
|
struct user_namespace *,
|
||||||
struct ksmbd_kstat *));
|
struct ksmbd_kstat *));
|
||||||
|
|
||||||
int ksmbd_extract_shortname(struct ksmbd_conn *conn,
|
int ksmbd_extract_shortname(struct ksmbd_conn *conn,
|
||||||
|
@ -253,7 +253,8 @@ void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid)
|
|||||||
ssid->num_subauth++;
|
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)
|
struct smb_fattr *fattr)
|
||||||
{
|
{
|
||||||
int rc = -EINVAL;
|
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]);
|
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
uid = make_kuid(&init_user_ns, id);
|
uid = make_kuid(user_ns, id);
|
||||||
if (uid_valid(uid) && kuid_has_mapping(&init_user_ns, uid)) {
|
if (uid_valid(uid) && kuid_has_mapping(user_ns, uid)) {
|
||||||
fattr->cf_uid = uid;
|
fattr->cf_uid = uid;
|
||||||
rc = 0;
|
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]);
|
id = le32_to_cpu(psid->sub_auth[psid->num_subauth - 1]);
|
||||||
if (id > 0) {
|
if (id > 0) {
|
||||||
gid = make_kgid(&init_user_ns, id);
|
gid = make_kgid(user_ns, id);
|
||||||
if (gid_valid(gid) && kgid_has_mapping(&init_user_ns, gid)) {
|
if (gid_valid(gid) && kgid_has_mapping(user_ns, gid)) {
|
||||||
fattr->cf_gid = gid;
|
fattr->cf_gid = gid;
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
@ -362,7 +363,8 @@ void free_acl_state(struct posix_acl_state *state)
|
|||||||
kfree(state->groups);
|
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_sid *pownersid, struct smb_sid *pgrpsid,
|
||||||
struct smb_fattr *fattr)
|
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,
|
acl_mode = access_flags_to_mode(fattr, ppace[i]->access_req,
|
||||||
ppace[i]->type);
|
ppace[i]->type);
|
||||||
temp_fattr.cf_uid = INVALID_UID;
|
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)) {
|
if (ret || uid_eq(temp_fattr.cf_uid, INVALID_UID)) {
|
||||||
pr_err("%s: Error %d mapping Owner SID to uid\n",
|
pr_err("%s: Error %d mapping Owner SID to uid\n",
|
||||||
__func__, ret);
|
__func__, ret);
|
||||||
@ -553,7 +555,8 @@ static void parse_dacl(struct smb_acl *pdacl, char *end_of_acl,
|
|||||||
free_acl_state(&default_acl_state);
|
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,
|
struct smb_fattr *fattr, u32 *num_aces,
|
||||||
u16 *size, u32 nt_aces_num)
|
u16 *size, u32 nt_aces_num)
|
||||||
{
|
{
|
||||||
@ -577,14 +580,14 @@ static void set_posix_acl_entries_dacl(struct smb_ace *pndace,
|
|||||||
uid_t uid;
|
uid_t uid;
|
||||||
unsigned int sid_type = SIDOWNER;
|
unsigned int sid_type = SIDOWNER;
|
||||||
|
|
||||||
uid = from_kuid(&init_user_ns, pace->e_uid);
|
uid = from_kuid(user_ns, pace->e_uid);
|
||||||
if (!uid)
|
if (!uid)
|
||||||
sid_type = SIDUNIX_USER;
|
sid_type = SIDUNIX_USER;
|
||||||
id_to_sid(uid, sid_type, sid);
|
id_to_sid(uid, sid_type, sid);
|
||||||
} else if (pace->e_tag == ACL_GROUP) {
|
} else if (pace->e_tag == ACL_GROUP) {
|
||||||
gid_t gid;
|
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);
|
id_to_sid(gid, SIDUNIX_GROUP, sid);
|
||||||
} else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
|
} else if (pace->e_tag == ACL_OTHER && !nt_aces_num) {
|
||||||
smb_copy_sid(sid, &sid_everyone);
|
smb_copy_sid(sid, &sid_everyone);
|
||||||
@ -643,12 +646,12 @@ static void set_posix_acl_entries_dacl(struct smb_ace *pndace,
|
|||||||
if (pace->e_tag == ACL_USER) {
|
if (pace->e_tag == ACL_USER) {
|
||||||
uid_t uid;
|
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);
|
id_to_sid(uid, SIDCREATOR_OWNER, sid);
|
||||||
} else if (pace->e_tag == ACL_GROUP) {
|
} else if (pace->e_tag == ACL_GROUP) {
|
||||||
gid_t gid;
|
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);
|
id_to_sid(gid, SIDCREATOR_GROUP, sid);
|
||||||
} else {
|
} else {
|
||||||
kfree(sid);
|
kfree(sid);
|
||||||
@ -666,7 +669,9 @@ static void set_posix_acl_entries_dacl(struct smb_ace *pndace,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *pownersid,
|
||||||
const struct smb_sid *pgrpsid,
|
const struct smb_sid *pgrpsid,
|
||||||
struct smb_fattr *fattr)
|
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->num_aces = cpu_to_le32(num_aces);
|
||||||
pndacl->size = cpu_to_le16(le16_to_cpu(pndacl->size) + size);
|
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;
|
struct smb_ace *pace, *pndace;
|
||||||
u32 num_aces = 0;
|
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));
|
pace = pndace = (struct smb_ace *)((char *)pndacl + sizeof(struct smb_acl));
|
||||||
|
|
||||||
if (fattr->cf_acls) {
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* owner RID */
|
/* owner RID */
|
||||||
uid = from_kuid(&init_user_ns, fattr->cf_uid);
|
uid = from_kuid(user_ns, fattr->cf_uid);
|
||||||
if (uid)
|
if (uid)
|
||||||
sid = &server_conf.domain_sid;
|
sid = &server_conf.domain_sid;
|
||||||
else
|
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,
|
ace_size = fill_ace_for_sid(pace, &sid_unix_groups,
|
||||||
ACCESS_ALLOWED, 0, fattr->cf_mode, 0070);
|
ACCESS_ALLOWED, 0, fattr->cf_mode, 0070);
|
||||||
pace->sid.sub_auth[pace->sid.num_subauth++] =
|
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);
|
pace->size = cpu_to_le16(ace_size + 4);
|
||||||
size += le16_to_cpu(pace->size);
|
size += le16_to_cpu(pace->size);
|
||||||
pace = (struct smb_ace *)((char *)pndace + 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 */
|
/* Convert CIFS ACL to POSIX form */
|
||||||
int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
|
int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
|
||||||
struct smb_fattr *fattr)
|
int acl_len, struct smb_fattr *fattr)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct smb_sid *owner_sid_ptr, *group_sid_ptr;
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sid_to_id(owner_sid_ptr, SIDOWNER, fattr);
|
rc = sid_to_id(user_ns, owner_sid_ptr, SIDOWNER, fattr);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: Error %d mapping Owner SID to uid\n",
|
pr_err("%s: Error %d mapping Owner SID to uid\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
@ -826,7 +834,7 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
|
|||||||
__func__, rc);
|
__func__, rc);
|
||||||
return 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) {
|
if (rc) {
|
||||||
pr_err("%s: Error %d mapping Group SID to gid\n",
|
pr_err("%s: Error %d mapping Group SID to gid\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
@ -841,15 +849,16 @@ int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
|
|||||||
pntsd->type |= cpu_to_le16(DACL_PROTECTED);
|
pntsd->type |= cpu_to_le16(DACL_PROTECTED);
|
||||||
|
|
||||||
if (dacloffset) {
|
if (dacloffset) {
|
||||||
parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr,
|
parse_dacl(user_ns, dacl_ptr, end_of_acl,
|
||||||
fattr);
|
owner_sid_ptr, group_sid_ptr, fattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert permission bits from mode to equivalent CIFS ACL */
|
/* 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,
|
int addition_info, __u32 *secdesclen,
|
||||||
struct smb_fattr *fattr)
|
struct smb_fattr *fattr)
|
||||||
{
|
{
|
||||||
@ -866,7 +875,7 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
|
|||||||
if (!nowner_sid_ptr)
|
if (!nowner_sid_ptr)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
uid = from_kuid(&init_user_ns, fattr->cf_uid);
|
uid = from_kuid(user_ns, fattr->cf_uid);
|
||||||
if (!uid)
|
if (!uid)
|
||||||
sid_type = SIDUNIX_USER;
|
sid_type = SIDUNIX_USER;
|
||||||
id_to_sid(uid, sid_type, nowner_sid_ptr);
|
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;
|
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);
|
id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr);
|
||||||
|
|
||||||
offset = sizeof(struct smb_ntsd);
|
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;
|
dacl_ptr->num_aces = 0;
|
||||||
|
|
||||||
if (!ppntsd) {
|
if (!ppntsd) {
|
||||||
set_mode_dacl(dacl_ptr, fattr);
|
set_mode_dacl(user_ns, dacl_ptr, fattr);
|
||||||
} else if (!ppntsd->dacloffset) {
|
} else if (!ppntsd->dacloffset) {
|
||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
@ -917,8 +926,8 @@ int build_sec_desc(struct smb_ntsd *pntsd, struct smb_ntsd *ppntsd,
|
|||||||
|
|
||||||
ppdacl_ptr = (struct smb_acl *)((char *)ppntsd +
|
ppdacl_ptr = (struct smb_acl *)((char *)ppntsd +
|
||||||
le32_to_cpu(ppntsd->dacloffset));
|
le32_to_cpu(ppntsd->dacloffset));
|
||||||
set_ntacl_dacl(dacl_ptr, ppdacl_ptr, nowner_sid_ptr,
|
set_ntacl_dacl(user_ns, dacl_ptr, ppdacl_ptr,
|
||||||
ngroup_sid_ptr, fattr);
|
nowner_sid_ptr, ngroup_sid_ptr, fattr);
|
||||||
}
|
}
|
||||||
pntsd->dacloffset = cpu_to_le32(offset);
|
pntsd->dacloffset = cpu_to_le32(offset);
|
||||||
offset += le16_to_cpu(dacl_ptr->size);
|
offset += le16_to_cpu(dacl_ptr->size);
|
||||||
@ -956,7 +965,8 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
|
|||||||
char *aces_base;
|
char *aces_base;
|
||||||
bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
|
bool is_dir = S_ISDIR(d_inode(path->dentry)->i_mode);
|
||||||
|
|
||||||
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)
|
if (acl_len <= 0)
|
||||||
return rc;
|
return rc;
|
||||||
dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
|
dacloffset = le32_to_cpu(parent_pntsd->dacloffset);
|
||||||
@ -1087,7 +1097,8 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
|
|||||||
pntsd_size += sizeof(struct smb_acl) + nt_size;
|
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);
|
kfree(pntsd);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
@ -1128,7 +1139,8 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
|
|||||||
char *end_of_acl;
|
char *end_of_acl;
|
||||||
|
|
||||||
ksmbd_debug(SMB, "check permission using windows acl\n");
|
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) {
|
if (acl_size <= 0 || !pntsd || !pntsd->dacloffset) {
|
||||||
kfree(pntsd);
|
kfree(pntsd);
|
||||||
return 0;
|
return 0;
|
||||||
@ -1209,9 +1221,11 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path,
|
|||||||
pa_entry = posix_acls->a_entries;
|
pa_entry = posix_acls->a_entries;
|
||||||
for (i = 0; i < posix_acls->a_count; i++, pa_entry++) {
|
for (i = 0; i < posix_acls->a_count; i++, pa_entry++) {
|
||||||
if (pa_entry->e_tag == ACL_USER)
|
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)
|
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
|
else
|
||||||
continue;
|
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_gid = INVALID_GID;
|
||||||
fattr.cf_mode = inode->i_mode;
|
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)
|
if (rc)
|
||||||
goto out;
|
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;
|
inode->i_gid = fattr.cf_gid;
|
||||||
mark_inode_dirty(inode);
|
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 */
|
/* Update posix acls */
|
||||||
if (fattr.cf_dacls) {
|
if (fattr.cf_dacls) {
|
||||||
rc = set_posix_acl(&init_user_ns, inode, ACL_TYPE_ACCESS,
|
rc = set_posix_acl(mnt_user_ns(path->mnt), inode,
|
||||||
fattr.cf_acls);
|
ACL_TYPE_ACCESS, fattr.cf_acls);
|
||||||
if (S_ISDIR(inode->i_mode) && fattr.cf_dacls)
|
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);
|
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)) {
|
if (test_share_config_flag(tcon->share_conf, KSMBD_SHARE_FLAG_ACL_XATTR)) {
|
||||||
/* Update WinACL in xattr */
|
/* Update WinACL in xattr */
|
||||||
ksmbd_vfs_remove_sd_xattrs(path->dentry);
|
ksmbd_vfs_remove_sd_xattrs(mnt_user_ns(path->mnt), path->dentry);
|
||||||
ksmbd_vfs_set_sd_xattr(conn, path->dentry, pntsd, ntsd_len);
|
ksmbd_vfs_set_sd_xattr(conn, mnt_user_ns(path->mnt),
|
||||||
|
path->dentry, pntsd, ntsd_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -189,11 +189,11 @@ struct posix_acl_state {
|
|||||||
struct posix_ace_state_array *groups;
|
struct posix_ace_state_array *groups;
|
||||||
};
|
};
|
||||||
|
|
||||||
int parse_sec_desc(struct smb_ntsd *pntsd, int acl_len,
|
int parse_sec_desc(struct user_namespace *user_ns, struct smb_ntsd *pntsd,
|
||||||
struct smb_fattr *fattr);
|
int acl_len, struct smb_fattr *fattr);
|
||||||
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,
|
||||||
int addition_info, __u32 *secdesclen,
|
struct smb_ntsd *ppntsd, int addition_info,
|
||||||
struct smb_fattr *fattr);
|
__u32 *secdesclen, struct smb_fattr *fattr);
|
||||||
int init_acl_state(struct posix_acl_state *state, int cnt);
|
int init_acl_state(struct posix_acl_state *state, int cnt);
|
||||||
void free_acl_state(struct posix_acl_state *state);
|
void free_acl_state(struct posix_acl_state *state);
|
||||||
void posix_state_to_acl(struct posix_acl_state *state,
|
void posix_state_to_acl(struct posix_acl_state *state,
|
||||||
|
172
fs/ksmbd/vfs.c
172
fs/ksmbd/vfs.c
@ -95,7 +95,8 @@ int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
|
|||||||
return ret;
|
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;
|
struct dentry *parent;
|
||||||
int ret;
|
int ret;
|
||||||
@ -107,7 +108,7 @@ int ksmbd_vfs_may_delete(struct dentry *dentry)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = inode_permission(&init_user_ns, d_inode(parent),
|
ret = inode_permission(user_ns, d_inode(parent),
|
||||||
MAY_EXEC | MAY_WRITE);
|
MAY_EXEC | MAY_WRITE);
|
||||||
|
|
||||||
inode_unlock(d_inode(parent));
|
inode_unlock(d_inode(parent));
|
||||||
@ -115,23 +116,24 @@ int ksmbd_vfs_may_delete(struct dentry *dentry)
|
|||||||
return ret;
|
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;
|
struct dentry *parent;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
*daccess = cpu_to_le32(FILE_READ_ATTRIBUTES | READ_CONTROL);
|
*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 |
|
*daccess |= cpu_to_le32(WRITE_DAC | WRITE_OWNER | SYNCHRONIZE |
|
||||||
FILE_WRITE_DATA | FILE_APPEND_DATA |
|
FILE_WRITE_DATA | FILE_APPEND_DATA |
|
||||||
FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |
|
FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES |
|
||||||
FILE_DELETE_CHILD);
|
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;
|
*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;
|
*daccess |= FILE_EXECUTE_LE;
|
||||||
|
|
||||||
parent = dget_parent(dentry);
|
parent = dget_parent(dentry);
|
||||||
@ -141,7 +143,7 @@ int ksmbd_vfs_query_maximal_access(struct dentry *dentry, __le32 *daccess)
|
|||||||
return ret;
|
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;
|
*daccess |= FILE_DELETE_LE;
|
||||||
|
|
||||||
inode_unlock(d_inode(parent));
|
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;
|
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) {
|
if (!err) {
|
||||||
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
|
ksmbd_vfs_inherit_owner(work, d_inode(path.dentry),
|
||||||
d_inode(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;
|
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) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
} else if (d_unhashed(dentry)) {
|
} else if (d_unhashed(dentry)) {
|
||||||
@ -236,7 +240,8 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
|
|||||||
return err;
|
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)
|
int attr_name_len, char **attr_value)
|
||||||
{
|
{
|
||||||
char *name, *xattr_list = NULL;
|
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))
|
if (strncasecmp(attr_name, name, attr_name_len))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
value_len = ksmbd_vfs_getxattr(dentry,
|
value_len = ksmbd_vfs_getxattr(user_ns,
|
||||||
|
dentry,
|
||||||
name,
|
name,
|
||||||
attr_value);
|
attr_value);
|
||||||
if (value_len < 0)
|
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",
|
ksmbd_debug(VFS, "read stream data pos : %llu, count : %zd\n",
|
||||||
*pos, count);
|
*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.name,
|
||||||
fp->stream.size,
|
fp->stream.size,
|
||||||
&stream_buf);
|
&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;
|
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.name,
|
||||||
fp->stream.size,
|
fp->stream.size,
|
||||||
&stream_buf);
|
&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);
|
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,
|
fp->stream.name,
|
||||||
(void *)stream_buf,
|
(void *)stream_buf,
|
||||||
size,
|
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)) {
|
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)
|
if (err && err != -ENOTEMPTY)
|
||||||
ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
|
ksmbd_debug(VFS, "%s: rmdir failed, err %d\n", name,
|
||||||
err);
|
err);
|
||||||
} else {
|
} else {
|
||||||
err = vfs_unlink(&init_user_ns, d_inode(parent), path.dentry,
|
err = vfs_unlink(mnt_user_ns(path.mnt), d_inode(parent),
|
||||||
NULL);
|
path.dentry, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
|
ksmbd_debug(VFS, "%s: unlink failed, err %d\n", name,
|
||||||
err);
|
err);
|
||||||
@ -669,7 +679,8 @@ int ksmbd_vfs_link(struct ksmbd_work *work, const char *oldname,
|
|||||||
goto out3;
|
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);
|
dentry, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
ksmbd_debug(VFS, "vfs_link failed err %d\n", 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,
|
static int __ksmbd_vfs_rename(struct ksmbd_work *work,
|
||||||
|
struct user_namespace *src_user_ns,
|
||||||
struct dentry *src_dent_parent,
|
struct dentry *src_dent_parent,
|
||||||
struct dentry *src_dent,
|
struct dentry *src_dent,
|
||||||
|
struct user_namespace *dst_user_ns,
|
||||||
struct dentry *dst_dent_parent,
|
struct dentry *dst_dent_parent,
|
||||||
struct dentry *trap_dent,
|
struct dentry *trap_dent,
|
||||||
char *dst_name)
|
char *dst_name)
|
||||||
@ -744,10 +757,10 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
|
|||||||
err = -ENOTEMPTY;
|
err = -ENOTEMPTY;
|
||||||
if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
|
if (dst_dent != trap_dent && !d_really_is_positive(dst_dent)) {
|
||||||
struct renamedata rd = {
|
struct renamedata rd = {
|
||||||
.old_mnt_userns = &init_user_ns,
|
.old_mnt_userns = src_user_ns,
|
||||||
.old_dir = d_inode(src_dent_parent),
|
.old_dir = d_inode(src_dent_parent),
|
||||||
.old_dentry = src_dent,
|
.old_dentry = src_dent,
|
||||||
.new_mnt_userns = &init_user_ns,
|
.new_mnt_userns = dst_user_ns,
|
||||||
.new_dir = d_inode(dst_dent_parent),
|
.new_dir = d_inode(dst_dent_parent),
|
||||||
.new_dentry = dst_dent,
|
.new_dentry = dst_dent,
|
||||||
};
|
};
|
||||||
@ -809,8 +822,10 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
|
|||||||
dput(src_child);
|
dput(src_child);
|
||||||
|
|
||||||
err = __ksmbd_vfs_rename(work,
|
err = __ksmbd_vfs_rename(work,
|
||||||
|
file_mnt_user_ns(fp->filp),
|
||||||
src_dent_parent,
|
src_dent_parent,
|
||||||
src_dent,
|
src_dent,
|
||||||
|
mnt_user_ns(dst_path.mnt),
|
||||||
dst_dent_parent,
|
dst_dent_parent,
|
||||||
trap_dent,
|
trap_dent,
|
||||||
dst_name);
|
dst_name);
|
||||||
@ -917,27 +932,30 @@ ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list)
|
|||||||
return size;
|
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
|
* ksmbd_vfs_getxattr() - vfs helper for smb get extended attributes value
|
||||||
|
* @user_ns: user namespace
|
||||||
* @dentry: dentry of file for getting xattrs
|
* @dentry: dentry of file for getting xattrs
|
||||||
* @xattr_name: name of xattr name to query
|
* @xattr_name: name of xattr name to query
|
||||||
* @xattr_buf: destination buffer xattr value
|
* @xattr_buf: destination buffer xattr value
|
||||||
*
|
*
|
||||||
* Return: read xattr value length on success, otherwise error
|
* Return: read xattr value length on success, otherwise error
|
||||||
*/
|
*/
|
||||||
ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
|
ssize_t ksmbd_vfs_getxattr(struct user_namespace *user_ns,
|
||||||
char **xattr_buf)
|
struct dentry *dentry,
|
||||||
|
char *xattr_name, char **xattr_buf)
|
||||||
{
|
{
|
||||||
ssize_t xattr_len;
|
ssize_t xattr_len;
|
||||||
char *buf;
|
char *buf;
|
||||||
|
|
||||||
*xattr_buf = NULL;
|
*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)
|
if (xattr_len < 0)
|
||||||
return xattr_len;
|
return xattr_len;
|
||||||
|
|
||||||
@ -945,7 +963,7 @@ ssize_t ksmbd_vfs_getxattr(struct dentry *dentry, char *xattr_name,
|
|||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
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);
|
(void *)buf, xattr_len);
|
||||||
if (xattr_len > 0)
|
if (xattr_len > 0)
|
||||||
*xattr_buf = buf;
|
*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
|
* ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value
|
||||||
|
* @user_ns: user namespace
|
||||||
* @dentry: dentry to set XATTR at
|
* @dentry: dentry to set XATTR at
|
||||||
* @name: xattr name for setxattr
|
* @name: xattr name for setxattr
|
||||||
* @value: xattr value to set
|
* @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
|
* 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)
|
const void *attr_value, size_t attr_size, int flags)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = vfs_setxattr(&init_user_ns, dentry,
|
err = vfs_setxattr(user_ns,
|
||||||
|
dentry,
|
||||||
attr_name,
|
attr_name,
|
||||||
attr_value,
|
attr_value,
|
||||||
attr_size,
|
attr_size,
|
||||||
@ -1076,12 +1097,14 @@ int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
|
|||||||
return ret;
|
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;
|
int err = 0;
|
||||||
|
|
||||||
@ -1091,9 +1114,9 @@ int ksmbd_vfs_unlink(struct dentry *dir, struct dentry *dentry)
|
|||||||
dget(dentry);
|
dget(dentry);
|
||||||
|
|
||||||
if (S_ISDIR(d_inode(dentry)->i_mode))
|
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
|
else
|
||||||
err = vfs_unlink(&init_user_ns, d_inode(dir), dentry, NULL);
|
err = vfs_unlink(user_ns, d_inode(dir), dentry, NULL);
|
||||||
|
|
||||||
dput(dentry);
|
dput(dentry);
|
||||||
inode_unlock(d_inode(dir));
|
inode_unlock(d_inode(dir));
|
||||||
@ -1267,7 +1290,8 @@ int ksmbd_vfs_kern_path(char *name, unsigned int flags, struct path *path,
|
|||||||
return err;
|
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;
|
char *name, *xattr_list = NULL;
|
||||||
ssize_t xattr_list_len;
|
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) ||
|
sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1) ||
|
||||||
!strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
|
!strncmp(name, XATTR_NAME_POSIX_ACL_DEFAULT,
|
||||||
sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1)) {
|
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)
|
if (err)
|
||||||
ksmbd_debug(SMB,
|
ksmbd_debug(SMB,
|
||||||
"remove acl xattr failed : %s\n", name);
|
"remove acl xattr failed : %s\n", name);
|
||||||
@ -1300,7 +1324,8 @@ int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry)
|
|||||||
return err;
|
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;
|
char *name, *xattr_list = NULL;
|
||||||
ssize_t xattr_list_len;
|
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));
|
ksmbd_debug(SMB, "%s, len %zd\n", name, strlen(name));
|
||||||
|
|
||||||
if (!strncmp(name, XATTR_NAME_SD, XATTR_NAME_SD_LEN)) {
|
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)
|
if (err)
|
||||||
ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
|
ksmbd_debug(SMB, "remove xattr failed : %s\n", name);
|
||||||
}
|
}
|
||||||
@ -1329,7 +1354,8 @@ int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry)
|
|||||||
return err;
|
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)
|
int acl_type)
|
||||||
{
|
{
|
||||||
struct xattr_smb_acl *smb_acl = NULL;
|
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) {
|
switch (pa_entry->e_tag) {
|
||||||
case ACL_USER:
|
case ACL_USER:
|
||||||
xa_entry->type = SMB_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;
|
break;
|
||||||
case ACL_USER_OBJ:
|
case ACL_USER_OBJ:
|
||||||
xa_entry->type = SMB_ACL_USER_OBJ;
|
xa_entry->type = SMB_ACL_USER_OBJ;
|
||||||
break;
|
break;
|
||||||
case ACL_GROUP:
|
case ACL_GROUP:
|
||||||
xa_entry->type = SMB_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;
|
break;
|
||||||
case ACL_GROUP_OBJ:
|
case ACL_GROUP_OBJ:
|
||||||
xa_entry->type = SMB_ACL_GROUP_OBJ;
|
xa_entry->type = SMB_ACL_GROUP_OBJ;
|
||||||
@ -1390,7 +1416,9 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct inode *inode,
|
|||||||
return smb_acl;
|
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)
|
struct smb_ntsd *pntsd, int len)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
@ -1422,12 +1450,14 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
|
|||||||
return rc;
|
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))
|
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);
|
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) {
|
if (rc) {
|
||||||
pr_err("failed to encode ndr to posix acl\n");
|
pr_err("failed to encode ndr to posix acl\n");
|
||||||
goto out;
|
goto out;
|
||||||
@ -1446,7 +1476,8 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
|
|||||||
goto out;
|
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);
|
sd_ndr.offset, 0);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
pr_err("Failed to store XATTR ntacl :%d\n", rc);
|
pr_err("Failed to store XATTR ntacl :%d\n", rc);
|
||||||
@ -1459,13 +1490,15 @@ int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
|
|||||||
return rc;
|
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)
|
struct smb_ntsd **pntsd)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
struct ndr n;
|
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) {
|
if (rc > 0) {
|
||||||
struct inode *inode = d_inode(dentry);
|
struct inode *inode = d_inode(dentry);
|
||||||
struct ndr acl_ndr = {0};
|
struct ndr acl_ndr = {0};
|
||||||
@ -1478,13 +1511,15 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return 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);
|
ACL_TYPE_ACCESS);
|
||||||
if (S_ISDIR(inode->i_mode))
|
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);
|
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) {
|
if (rc) {
|
||||||
pr_err("failed to encode ndr to posix acl\n");
|
pr_err("failed to encode ndr to posix acl\n");
|
||||||
goto out;
|
goto out;
|
||||||
@ -1522,7 +1557,8 @@ int ksmbd_vfs_get_sd_xattr(struct ksmbd_conn *conn, struct dentry *dentry,
|
|||||||
return rc;
|
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 xattr_dos_attrib *da)
|
||||||
{
|
{
|
||||||
struct ndr n;
|
struct ndr n;
|
||||||
@ -1532,7 +1568,7 @@ int ksmbd_vfs_set_dos_attrib_xattr(struct dentry *dentry,
|
|||||||
if (err)
|
if (err)
|
||||||
return 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);
|
(void *)n.data, n.offset, 0);
|
||||||
if (err)
|
if (err)
|
||||||
ksmbd_debug(SMB, "failed to store dos attribute in xattr\n");
|
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;
|
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 xattr_dos_attrib *da)
|
||||||
{
|
{
|
||||||
struct ndr n;
|
struct ndr n;
|
||||||
int err;
|
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);
|
(char **)&n.data);
|
||||||
if (err > 0) {
|
if (err > 0) {
|
||||||
n.length = err;
|
n.length = err;
|
||||||
@ -1593,13 +1630,15 @@ void *ksmbd_vfs_init_kstat(char **p, struct ksmbd_kstat *ksmbd_kstat)
|
|||||||
return info;
|
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)
|
struct ksmbd_kstat *ksmbd_kstat)
|
||||||
{
|
{
|
||||||
u64 time;
|
u64 time;
|
||||||
int rc;
|
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);
|
time = ksmbd_UnixTimeToNT(ksmbd_kstat->kstat->ctime);
|
||||||
ksmbd_kstat->create_time = time;
|
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)) {
|
KSMBD_SHARE_FLAG_STORE_DOS_ATTRS)) {
|
||||||
struct xattr_dos_attrib da;
|
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) {
|
if (rc > 0) {
|
||||||
ksmbd_kstat->file_attributes = cpu_to_le32(da.attr);
|
ksmbd_kstat->file_attributes = cpu_to_le32(da.attr);
|
||||||
ksmbd_kstat->create_time = da.create_time;
|
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;
|
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)
|
int attr_name_len)
|
||||||
{
|
{
|
||||||
char *name, *xattr_list = NULL;
|
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))
|
if (strncasecmp(attr_name, name, attr_name_len))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
value_len = ksmbd_vfs_xattr_len(dentry, name);
|
value_len = ksmbd_vfs_xattr_len(user_ns, dentry, name);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1775,7 +1815,8 @@ void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock)
|
|||||||
locks_delete_block(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_state acl_state;
|
||||||
struct posix_acl *acls;
|
struct posix_acl *acls;
|
||||||
@ -1804,13 +1845,13 @@ int ksmbd_vfs_set_init_posix_acl(struct inode *inode)
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
posix_state_to_acl(&acl_state, acls->a_entries);
|
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)
|
if (rc < 0)
|
||||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
|
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
|
||||||
rc);
|
rc);
|
||||||
else if (S_ISDIR(inode->i_mode)) {
|
else if (S_ISDIR(inode->i_mode)) {
|
||||||
posix_state_to_acl(&acl_state, acls->a_entries);
|
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);
|
acls);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
|
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;
|
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 *acls;
|
||||||
struct posix_acl_entry *pace;
|
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)
|
if (rc < 0)
|
||||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
|
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
|
||||||
rc);
|
rc);
|
||||||
if (S_ISDIR(inode->i_mode)) {
|
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);
|
acls);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
|
ksmbd_debug(SMB, "Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
|
||||||
|
@ -108,8 +108,9 @@ struct ksmbd_kstat {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child);
|
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child);
|
||||||
int ksmbd_vfs_may_delete(struct dentry *dentry);
|
int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry);
|
||||||
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);
|
||||||
int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode);
|
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_mkdir(struct ksmbd_work *work, const char *name, umode_t mode);
|
||||||
int ksmbd_vfs_read(struct ksmbd_work *work, struct ksmbd_file *fp,
|
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,
|
unsigned int *chunk_size_written,
|
||||||
loff_t *total_size_written);
|
loff_t *total_size_written);
|
||||||
ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list);
|
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);
|
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 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);
|
const void *attr_value, size_t attr_size, int flags);
|
||||||
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
|
int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
|
||||||
size_t *xattr_stream_name_size, int s_type);
|
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,
|
int ksmbd_vfs_kern_path(char *name, unsigned int flags, struct path *path,
|
||||||
bool caseless);
|
bool caseless);
|
||||||
int ksmbd_vfs_empty_dir(struct ksmbd_file *fp);
|
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,
|
int ksmbd_vfs_fqar_lseek(struct ksmbd_file *fp, loff_t start, loff_t length,
|
||||||
struct file_allocated_range_buffer *ranges,
|
struct file_allocated_range_buffer *ranges,
|
||||||
int in_count, int *out_count);
|
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);
|
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);
|
struct ksmbd_kstat *ksmbd_kstat);
|
||||||
int ksmbd_vfs_posix_lock_wait(struct file_lock *flock);
|
int ksmbd_vfs_posix_lock_wait(struct file_lock *flock);
|
||||||
int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout);
|
int ksmbd_vfs_posix_lock_wait_timeout(struct file_lock *flock, long timeout);
|
||||||
void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock);
|
void ksmbd_vfs_posix_lock_unblock(struct file_lock *flock);
|
||||||
int ksmbd_vfs_remove_acl_xattrs(struct dentry *dentry);
|
int ksmbd_vfs_remove_acl_xattrs(struct user_namespace *user_ns,
|
||||||
int ksmbd_vfs_remove_sd_xattrs(struct dentry *dentry);
|
struct dentry *dentry);
|
||||||
int ksmbd_vfs_set_sd_xattr(struct ksmbd_conn *conn, 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);
|
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);
|
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);
|
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);
|
struct xattr_dos_attrib *da);
|
||||||
int ksmbd_vfs_set_init_posix_acl(struct inode *inode);
|
int ksmbd_vfs_set_init_posix_acl(struct user_namespace *user_ns,
|
||||||
int ksmbd_vfs_inherit_posix_acl(struct inode *inode,
|
struct inode *inode);
|
||||||
|
int ksmbd_vfs_inherit_posix_acl(struct user_namespace *user_ns,
|
||||||
|
struct inode *inode,
|
||||||
struct inode *parent_inode);
|
struct inode *parent_inode);
|
||||||
#endif /* __KSMBD_VFS_H__ */
|
#endif /* __KSMBD_VFS_H__ */
|
||||||
|
@ -251,7 +251,8 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
|
|||||||
filp = fp->filp;
|
filp = fp->filp;
|
||||||
if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
|
if (ksmbd_stream_fd(fp) && (ci->m_flags & S_DEL_ON_CLS_STREAM)) {
|
||||||
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);
|
fp->stream.name);
|
||||||
if (err)
|
if (err)
|
||||||
pr_err("remove xattr failed : %s\n",
|
pr_err("remove xattr failed : %s\n",
|
||||||
@ -265,7 +266,7 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
|
|||||||
dir = dentry->d_parent;
|
dir = dentry->d_parent;
|
||||||
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
|
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
|
||||||
write_unlock(&ci->m_lock);
|
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_lock(&ci->m_lock);
|
||||||
}
|
}
|
||||||
write_unlock(&ci->m_lock);
|
write_unlock(&ci->m_lock);
|
||||||
|
Loading…
Reference in New Issue
Block a user