Commit bf9f243f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag '5.15-rc-ksmbd-part2' of git://git.samba.org/ksmbd

Pull ksmbd fixes from Steve French:

 - various fixes pointed out by coverity, and a minor cleanup patch

 - id mapping and ownership fixes

 - an smbdirect fix

* tag '5.15-rc-ksmbd-part2' of git://git.samba.org/ksmbd:
  ksmbd: fix control flow issues in sid_to_id()
  ksmbd: fix read of uninitialized variable ret in set_file_basic_info
  ksmbd: add missing assignments to ret on ndr_read_int64 read calls
  ksmbd: add validation for ndr read/write functions
  ksmbd: remove unused ksmbd_file_table_flush function
  ksmbd: smbd: fix dma mapping error in smb_direct_post_send_data
  ksmbd: Reduce error log 'speed is unknown' to debug
  ksmbd: defer notify_change() call
  ksmbd: remove setattr preparations in set_file_basic_info()
  ksmbd: ensure error is surfaced in set_file_basic_info()
  ndr: fix translation in ndr_encode_posix_acl()
  ksmbd: fix translation in sid_to_id()
  ksmbd: fix subauth 0 handling in sid_to_id()
  ksmbd: fix translation in acl entries
  ksmbd: fix translation in ksmbd_acls_fattr()
  ksmbd: fix translation in create_posix_rsp_buf()
  ksmbd: fix translation in smb2_populate_readdir_entry()
  ksmbd: fix lookup on idmapped mounts
parents 8dde2086 4cf0ccd0
This diff is collapsed.
...@@ -1614,9 +1614,11 @@ void create_posix_rsp_buf(char *cc, struct ksmbd_file *fp) ...@@ -1614,9 +1614,11 @@ 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(user_ns, inode->i_uid), id_to_sid(from_kuid_munged(&init_user_ns,
i_uid_into_mnt(user_ns, inode)),
SIDNFS_USER, (struct smb_sid *)&buf->SidBuffer[0]); SIDNFS_USER, (struct smb_sid *)&buf->SidBuffer[0]);
id_to_sid(from_kgid(user_ns, inode->i_gid), id_to_sid(from_kgid_munged(&init_user_ns,
i_gid_into_mnt(user_ns, inode)),
SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]); SIDNFS_GROUP, (struct smb_sid *)&buf->SidBuffer[20]);
} }
......
...@@ -2381,10 +2381,12 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work, ...@@ -2381,10 +2381,12 @@ static int smb2_create_sd_buffer(struct ksmbd_work *work,
le32_to_cpu(sd_buf->ccontext.DataLength), true); le32_to_cpu(sd_buf->ccontext.DataLength), true);
} }
static void ksmbd_acls_fattr(struct smb_fattr *fattr, struct inode *inode) static void ksmbd_acls_fattr(struct smb_fattr *fattr,
struct user_namespace *mnt_userns,
struct inode *inode)
{ {
fattr->cf_uid = inode->i_uid; fattr->cf_uid = i_uid_into_mnt(mnt_userns, inode);
fattr->cf_gid = inode->i_gid; fattr->cf_gid = i_gid_into_mnt(mnt_userns, inode);
fattr->cf_mode = inode->i_mode; fattr->cf_mode = inode->i_mode;
fattr->cf_acls = NULL; fattr->cf_acls = NULL;
fattr->cf_dacls = NULL; fattr->cf_dacls = NULL;
...@@ -2893,7 +2895,7 @@ int smb2_open(struct ksmbd_work *work) ...@@ -2893,7 +2895,7 @@ int smb2_open(struct ksmbd_work *work)
struct smb_ntsd *pntsd; struct smb_ntsd *pntsd;
int pntsd_size, ace_num = 0; int pntsd_size, ace_num = 0;
ksmbd_acls_fattr(&fattr, inode); ksmbd_acls_fattr(&fattr, user_ns, inode);
if (fattr.cf_acls) if (fattr.cf_acls)
ace_num = fattr.cf_acls->a_count; ace_num = fattr.cf_acls->a_count;
if (fattr.cf_dacls) if (fattr.cf_dacls)
...@@ -3324,7 +3326,6 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level) ...@@ -3324,7 +3326,6 @@ static int dentry_name(struct ksmbd_dir_info *d_info, int info_level)
*/ */
static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level, 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;
...@@ -3478,9 +3479,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level, ...@@ -3478,9 +3479,9 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
S_ISDIR(ksmbd_kstat->kstat->mode) ? ATTR_DIRECTORY_LE : ATTR_ARCHIVE_LE; 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(user_ns, ksmbd_kstat->kstat->uid), id_to_sid(from_kuid_munged(&init_user_ns, ksmbd_kstat->kstat->uid),
SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]); SIDNFS_USER, (struct smb_sid *)&posix_info->SidBuffer[0]);
id_to_sid(from_kgid(user_ns, ksmbd_kstat->kstat->gid), id_to_sid(from_kgid_munged(&init_user_ns, ksmbd_kstat->kstat->gid),
SIDNFS_GROUP, (struct smb_sid *)&posix_info->SidBuffer[20]); 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);
...@@ -3543,9 +3544,9 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv) ...@@ -3543,9 +3544,9 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
return -EINVAL; return -EINVAL;
lock_dir(priv->dir_fp); lock_dir(priv->dir_fp);
dent = lookup_one_len(priv->d_info->name, dent = lookup_one(user_ns, priv->d_info->name,
priv->dir_fp->filp->f_path.dentry, priv->dir_fp->filp->f_path.dentry,
priv->d_info->name_len); priv->d_info->name_len);
unlock_dir(priv->dir_fp); unlock_dir(priv->dir_fp);
if (IS_ERR(dent)) { if (IS_ERR(dent)) {
...@@ -3571,7 +3572,6 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv) ...@@ -3571,7 +3572,6 @@ static int process_query_dir_entries(struct smb2_query_dir_private *priv)
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,
user_ns,
&ksmbd_kstat); &ksmbd_kstat);
dput(dent); dput(dent);
if (rc) if (rc)
...@@ -5008,7 +5008,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work, ...@@ -5008,7 +5008,7 @@ static int smb2_get_info_sec(struct ksmbd_work *work,
user_ns = file_mnt_user_ns(fp->filp); user_ns = file_mnt_user_ns(fp->filp);
inode = file_inode(fp->filp); inode = file_inode(fp->filp);
ksmbd_acls_fattr(&fattr, inode); ksmbd_acls_fattr(&fattr, user_ns, inode);
if (test_share_config_flag(work->tcon->share_conf, if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_ACL_XATTR)) KSMBD_SHARE_FLAG_ACL_XATTR))
...@@ -5246,7 +5246,9 @@ int smb2_echo(struct ksmbd_work *work) ...@@ -5246,7 +5246,9 @@ int smb2_echo(struct ksmbd_work *work)
return 0; return 0;
} }
static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp, static int smb2_rename(struct ksmbd_work *work,
struct ksmbd_file *fp,
struct user_namespace *user_ns,
struct smb2_file_rename_info *file_info, struct smb2_file_rename_info *file_info,
struct nls_table *local_nls) struct nls_table *local_nls)
{ {
...@@ -5310,7 +5312,7 @@ static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -5310,7 +5312,7 @@ static int smb2_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
if (rc) if (rc)
goto out; goto out;
rc = ksmbd_vfs_setxattr(file_mnt_user_ns(fp->filp), rc = ksmbd_vfs_setxattr(user_ns,
fp->filp->f_path.dentry, fp->filp->f_path.dentry,
xattr_stream_name, xattr_stream_name,
NULL, 0, 0); NULL, 0, 0);
...@@ -5438,11 +5440,11 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, ...@@ -5438,11 +5440,11 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
{ {
struct smb2_file_all_info *file_info; struct smb2_file_all_info *file_info;
struct iattr attrs; struct iattr attrs;
struct iattr temp_attrs; struct timespec64 ctime;
struct file *filp; struct file *filp;
struct inode *inode; struct inode *inode;
struct user_namespace *user_ns; struct user_namespace *user_ns;
int rc; int rc = 0;
if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE)) if (!(fp->daccess & FILE_WRITE_ATTRIBUTES_LE))
return -EACCES; return -EACCES;
...@@ -5462,11 +5464,11 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, ...@@ -5462,11 +5464,11 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
} }
if (file_info->ChangeTime) { if (file_info->ChangeTime) {
temp_attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime); attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
attrs.ia_ctime = temp_attrs.ia_ctime; ctime = attrs.ia_ctime;
attrs.ia_valid |= ATTR_CTIME; attrs.ia_valid |= ATTR_CTIME;
} else { } else {
temp_attrs.ia_ctime = inode->i_ctime; ctime = inode->i_ctime;
} }
if (file_info->LastWriteTime) { if (file_info->LastWriteTime) {
...@@ -5505,13 +5507,6 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, ...@@ -5505,13 +5507,6 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf,
rc = 0; rc = 0;
} }
/*
* HACK : set ctime here to avoid ctime changed
* when file_info->ChangeTime is zero.
*/
attrs.ia_ctime = temp_attrs.ia_ctime;
attrs.ia_valid |= ATTR_CTIME;
if (attrs.ia_valid) { if (attrs.ia_valid) {
struct dentry *dentry = filp->f_path.dentry; struct dentry *dentry = filp->f_path.dentry;
struct inode *inode = d_inode(dentry); struct inode *inode = d_inode(dentry);
...@@ -5519,17 +5514,15 @@ static int set_file_basic_info(struct ksmbd_file *fp, char *buf, ...@@ -5519,17 +5514,15 @@ 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(user_ns, dentry, &attrs);
if (rc)
return -EINVAL;
inode_lock(inode); inode_lock(inode);
setattr_copy(user_ns, inode, &attrs);
attrs.ia_valid &= ~ATTR_CTIME;
rc = notify_change(user_ns, dentry, &attrs, NULL); rc = notify_change(user_ns, dentry, &attrs, NULL);
if (!rc) {
inode->i_ctime = ctime;
mark_inode_dirty(inode);
}
inode_unlock(inode); inode_unlock(inode);
} }
return 0; return rc;
} }
static int set_file_allocation_info(struct ksmbd_work *work, static int set_file_allocation_info(struct ksmbd_work *work,
...@@ -5624,6 +5617,7 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -5624,6 +5617,7 @@ static int set_end_of_file_info(struct ksmbd_work *work, struct ksmbd_file *fp,
static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
char *buf) char *buf)
{ {
struct user_namespace *user_ns;
struct ksmbd_file *parent_fp; struct ksmbd_file *parent_fp;
struct dentry *parent; struct dentry *parent;
struct dentry *dentry = fp->filp->f_path.dentry; struct dentry *dentry = fp->filp->f_path.dentry;
...@@ -5634,11 +5628,12 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -5634,11 +5628,12 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
return -EACCES; return -EACCES;
} }
user_ns = file_mnt_user_ns(fp->filp);
if (ksmbd_stream_fd(fp)) if (ksmbd_stream_fd(fp))
goto next; goto next;
parent = dget_parent(dentry); parent = dget_parent(dentry);
ret = ksmbd_vfs_lock_parent(parent, dentry); ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
if (ret) { if (ret) {
dput(parent); dput(parent);
return ret; return ret;
...@@ -5655,7 +5650,7 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -5655,7 +5650,7 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
} }
} }
next: next:
return smb2_rename(work, fp, return smb2_rename(work, fp, user_ns,
(struct smb2_file_rename_info *)buf, (struct smb2_file_rename_info *)buf,
work->sess->conn->local_nls); work->sess->conn->local_nls);
} }
...@@ -7116,8 +7111,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn, ...@@ -7116,8 +7111,8 @@ static int fsctl_query_iface_info_ioctl(struct ksmbd_conn *conn,
netdev->ethtool_ops->get_link_ksettings(netdev, &cmd); netdev->ethtool_ops->get_link_ksettings(netdev, &cmd);
speed = cmd.base.speed; speed = cmd.base.speed;
} else { } else {
pr_err("%s %s\n", netdev->name, ksmbd_debug(SMB, "%s %s\n", netdev->name,
"speed is unknown, defaulting to 1Gb/sec"); "speed is unknown, defaulting to 1Gb/sec");
speed = SPEED_1000; speed = SPEED_1000;
} }
......
...@@ -291,7 +291,6 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, ...@@ -291,7 +291,6 @@ 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;
...@@ -322,8 +321,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level, ...@@ -322,8 +321,7 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
user_ns, user_ns,
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, rc = fn(conn, info_level, d_info, &ksmbd_kstat);
user_ns, &ksmbd_kstat);
if (rc) if (rc)
break; break;
if (d_info->out_buf_len <= 0) if (d_info->out_buf_len <= 0)
......
...@@ -511,7 +511,6 @@ int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, ...@@ -511,7 +511,6 @@ 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,
......
...@@ -274,24 +274,34 @@ static int sid_to_id(struct user_namespace *user_ns, ...@@ -274,24 +274,34 @@ static int sid_to_id(struct user_namespace *user_ns,
uid_t id; uid_t id;
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) { /*
uid = make_kuid(user_ns, id); * Translate raw sid into kuid in the server's user
if (uid_valid(uid) && kuid_has_mapping(user_ns, uid)) { * namespace.
fattr->cf_uid = uid; */
rc = 0; uid = make_kuid(&init_user_ns, id);
}
/* If this is an idmapped mount, apply the idmapping. */
uid = kuid_from_mnt(user_ns, uid);
if (uid_valid(uid)) {
fattr->cf_uid = uid;
rc = 0;
} }
} else { } else {
kgid_t gid; kgid_t gid;
gid_t id; gid_t id;
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) { /*
gid = make_kgid(user_ns, id); * Translate raw sid into kgid in the server's user
if (gid_valid(gid) && kgid_has_mapping(user_ns, gid)) { * namespace.
fattr->cf_gid = gid; */
rc = 0; gid = make_kgid(&init_user_ns, id);
}
/* If this is an idmapped mount, apply the idmapping. */
gid = kgid_from_mnt(user_ns, gid);
if (gid_valid(gid)) {
fattr->cf_gid = gid;
rc = 0;
} }
} }
...@@ -587,14 +597,14 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns, ...@@ -587,14 +597,14 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
uid_t uid; uid_t uid;
unsigned int sid_type = SIDOWNER; unsigned int sid_type = SIDOWNER;
uid = from_kuid(user_ns, pace->e_uid); uid = posix_acl_uid_translate(user_ns, pace);
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(user_ns, pace->e_gid); gid = posix_acl_gid_translate(user_ns, pace);
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);
...@@ -653,12 +663,12 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns, ...@@ -653,12 +663,12 @@ static void set_posix_acl_entries_dacl(struct user_namespace *user_ns,
if (pace->e_tag == ACL_USER) { if (pace->e_tag == ACL_USER) {
uid_t uid; uid_t uid;
uid = from_kuid(user_ns, pace->e_uid); uid = posix_acl_uid_translate(user_ns, pace);
id_to_sid(uid, SIDCREATOR_OWNER, sid); 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(user_ns, pace->e_gid); gid = posix_acl_gid_translate(user_ns, pace);
id_to_sid(gid, SIDCREATOR_GROUP, sid); id_to_sid(gid, SIDCREATOR_GROUP, sid);
} else { } else {
kfree(sid); kfree(sid);
...@@ -723,7 +733,7 @@ static void set_mode_dacl(struct user_namespace *user_ns, ...@@ -723,7 +733,7 @@ static void set_mode_dacl(struct user_namespace *user_ns,
} }
/* owner RID */ /* owner RID */
uid = from_kuid(user_ns, fattr->cf_uid); uid = from_kuid(&init_user_ns, fattr->cf_uid);
if (uid) if (uid)
sid = &server_conf.domain_sid; sid = &server_conf.domain_sid;
else else
...@@ -739,7 +749,7 @@ static void set_mode_dacl(struct user_namespace *user_ns, ...@@ -739,7 +749,7 @@ static void set_mode_dacl(struct user_namespace *user_ns,
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(user_ns, fattr->cf_gid)); cpu_to_le32(from_kgid(&init_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);
...@@ -880,7 +890,7 @@ int build_sec_desc(struct user_namespace *user_ns, ...@@ -880,7 +890,7 @@ int build_sec_desc(struct user_namespace *user_ns,
if (!nowner_sid_ptr) if (!nowner_sid_ptr)
return -ENOMEM; return -ENOMEM;
uid = from_kuid(user_ns, fattr->cf_uid); uid = from_kuid(&init_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);
...@@ -891,7 +901,7 @@ int build_sec_desc(struct user_namespace *user_ns, ...@@ -891,7 +901,7 @@ int build_sec_desc(struct user_namespace *user_ns,
return -ENOMEM; return -ENOMEM;
} }
gid = from_kgid(user_ns, fattr->cf_gid); gid = from_kgid(&init_user_ns, fattr->cf_gid);
id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr); id_to_sid(gid, SIDUNIX_GROUP, ngroup_sid_ptr);
offset = sizeof(struct smb_ntsd); offset = sizeof(struct smb_ntsd);
...@@ -1234,11 +1244,9 @@ int smb_check_perm_dacl(struct ksmbd_conn *conn, struct path *path, ...@@ -1234,11 +1244,9 @@ 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(user_ns, id = posix_acl_uid_translate(user_ns, pa_entry);
pa_entry->e_uid);
else if (pa_entry->e_tag == ACL_GROUP) else if (pa_entry->e_tag == ACL_GROUP)
id = from_kgid(user_ns, id = posix_acl_gid_translate(user_ns, pa_entry);
pa_entry->e_gid);
else else
continue; continue;
...@@ -1322,22 +1330,31 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, ...@@ -1322,22 +1330,31 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
newattrs.ia_valid |= ATTR_MODE; newattrs.ia_valid |= ATTR_MODE;
newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777); newattrs.ia_mode = (inode->i_mode & ~0777) | (fattr.cf_mode & 0777);
inode_lock(inode);
rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
inode_unlock(inode);
if (rc)
goto out;
ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry); ksmbd_vfs_remove_acl_xattrs(user_ns, path->dentry);
/* Update posix acls */ /* Update posix acls */
if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) { if (IS_ENABLED(CONFIG_FS_POSIX_ACL) && fattr.cf_dacls) {
rc = set_posix_acl(user_ns, inode, rc = set_posix_acl(user_ns, inode,
ACL_TYPE_ACCESS, fattr.cf_acls); ACL_TYPE_ACCESS, fattr.cf_acls);
if (S_ISDIR(inode->i_mode) && fattr.cf_dacls) if (rc < 0)
ksmbd_debug(SMB,
"Set posix acl(ACL_TYPE_ACCESS) failed, rc : %d\n",
rc);
if (S_ISDIR(inode->i_mode) && fattr.cf_dacls) {
rc = set_posix_acl(user_ns, inode, rc = set_posix_acl(user_ns, inode,
ACL_TYPE_DEFAULT, fattr.cf_dacls); ACL_TYPE_DEFAULT, fattr.cf_dacls);
if (rc)
ksmbd_debug(SMB,
"Set posix acl(ACL_TYPE_DEFAULT) failed, rc : %d\n",
rc);
}
} }
inode_lock(inode);
rc = notify_change(user_ns, path->dentry, &newattrs, NULL);
inode_unlock(inode);
if (rc)
goto out;
/* Check it only calling from SD BUFFER context */ /* Check it only calling from SD BUFFER context */
if (type_check && !(le16_to_cpu(pntsd->type) & DACL_PRESENT)) if (type_check && !(le16_to_cpu(pntsd->type) & DACL_PRESENT))
goto out; goto out;
......
...@@ -209,4 +209,29 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon, ...@@ -209,4 +209,29 @@ int set_info_sec(struct ksmbd_conn *conn, struct ksmbd_tree_connect *tcon,
bool type_check); bool type_check);
void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid); void id_to_sid(unsigned int cid, uint sidtype, struct smb_sid *ssid);
void ksmbd_init_domain(u32 *sub_auth); void ksmbd_init_domain(u32 *sub_auth);
static inline uid_t posix_acl_uid_translate(struct user_namespace *mnt_userns,
struct posix_acl_entry *pace)
{
kuid_t kuid;
/* If this is an idmapped mount, apply the idmapping. */
kuid = kuid_into_mnt(mnt_userns, pace->e_uid);
/* Translate the kuid into a userspace id ksmbd would see. */
return from_kuid(&init_user_ns, kuid);
}
static inline gid_t posix_acl_gid_translate(struct user_namespace *mnt_userns,
struct posix_acl_entry *pace)
{
kgid_t kgid;
/* If this is an idmapped mount, apply the idmapping. */
kgid = kgid_into_mnt(mnt_userns, pace->e_gid);
/* Translate the kgid into a userspace id ksmbd would see. */
return from_kgid(&init_user_ns, kgid);
}
#endif /* _SMBACL_H */ #endif /* _SMBACL_H */
...@@ -1168,7 +1168,7 @@ static int smb_direct_post_send_data(struct smb_direct_transport *t, ...@@ -1168,7 +1168,7 @@ static int smb_direct_post_send_data(struct smb_direct_transport *t,
pr_err("failed to map buffer\n"); pr_err("failed to map buffer\n");
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
} else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES - 1) { } else if (sg_cnt + msg->num_sge > SMB_DIRECT_MAX_SEND_SGES) {
pr_err("buffer not fitted into sges\n"); pr_err("buffer not fitted into sges\n");
ret = -E2BIG; ret = -E2BIG;
ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt, ib_dma_unmap_sg(t->cm_id->device, sg, sg_cnt,
......
...@@ -69,14 +69,15 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work, ...@@ -69,14 +69,15 @@ static void ksmbd_vfs_inherit_owner(struct ksmbd_work *work,
* *
* the reference count of @parent isn't incremented. * the reference count of @parent isn't incremented.
*/ */
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child) int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
struct dentry *child)
{ {
struct dentry *dentry; struct dentry *dentry;
int ret = 0; int ret = 0;
inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); inode_lock_nested(d_inode(parent), I_MUTEX_PARENT);
dentry = lookup_one_len(child->d_name.name, parent, dentry = lookup_one(user_ns, child->d_name.name, parent,
child->d_name.len); child->d_name.len);
if (IS_ERR(dentry)) { if (IS_ERR(dentry)) {
ret = PTR_ERR(dentry); ret = PTR_ERR(dentry);
goto out_err; goto out_err;
...@@ -102,7 +103,7 @@ int ksmbd_vfs_may_delete(struct user_namespace *user_ns, ...@@ -102,7 +103,7 @@ int ksmbd_vfs_may_delete(struct user_namespace *user_ns,
int ret; int ret;
parent = dget_parent(dentry); parent = dget_parent(dentry);
ret = ksmbd_vfs_lock_parent(parent, dentry); ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
if (ret) { if (ret) {
dput(parent); dput(parent);
return ret; return ret;
...@@ -137,7 +138,7 @@ int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns, ...@@ -137,7 +138,7 @@ int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
*daccess |= FILE_EXECUTE_LE; *daccess |= FILE_EXECUTE_LE;
parent = dget_parent(dentry); parent = dget_parent(dentry);
ret = ksmbd_vfs_lock_parent(parent, dentry); ret = ksmbd_vfs_lock_parent(user_ns, parent, dentry);
if (ret) { if (ret) {
dput(parent); dput(parent);
return ret; return ret;
...@@ -197,6 +198,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode) ...@@ -197,6 +198,7 @@ int ksmbd_vfs_create(struct ksmbd_work *work, const char *name, umode_t mode)
*/ */
int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode) int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
{ {
struct user_namespace *user_ns;
struct path path; struct path path;
struct dentry *dentry; struct dentry *dentry;
int err; int err;
...@@ -210,16 +212,16 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode) ...@@ -210,16 +212,16 @@ int ksmbd_vfs_mkdir(struct ksmbd_work *work, const char *name, umode_t mode)
return err; return err;
} }
user_ns = mnt_user_ns(path.mnt);
mode |= S_IFDIR; mode |= S_IFDIR;
err = vfs_mkdir(mnt_user_ns(path.mnt), d_inode(path.dentry), err = vfs_mkdir(user_ns, d_inode(path.dentry), dentry, mode);
dentry, mode);
if (err) { if (err) {
goto out; goto out;
} else if (d_unhashed(dentry)) { } else if (d_unhashed(dentry)) {
struct dentry *d; struct dentry *d;
d = lookup_one_len(dentry->d_name.name, dentry->d_parent, d = lookup_one(user_ns, dentry->d_name.name, dentry->d_parent,
dentry->d_name.len); dentry->d_name.len);
if (IS_ERR(d)) { if (IS_ERR(d)) {
err = PTR_ERR(d); err = PTR_ERR(d);
goto out; goto out;
...@@ -582,6 +584,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id) ...@@ -582,6 +584,7 @@ int ksmbd_vfs_fsync(struct ksmbd_work *work, u64 fid, u64 p_id)
*/ */
int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name) int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
{ {
struct user_namespace *user_ns;
struct path path; struct path path;
struct dentry *parent; struct dentry *parent;
int err; int err;
...@@ -601,8 +604,9 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name) ...@@ -601,8 +604,9 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name)
return err; return err;
} }
user_ns = mnt_user_ns(path.mnt);
parent = dget_parent(path.dentry); parent = dget_parent(path.dentry);
err = ksmbd_vfs_lock_parent(parent, path.dentry); err = ksmbd_vfs_lock_parent(user_ns, parent, path.dentry);
if (err) { if (err) {
dput(parent); dput(parent);
path_put(&path); path_put(&path);
...@@ -616,14 +620,12 @@ int ksmbd_vfs_remove_file(struct ksmbd_work *work, char *name) ...@@ -616,14 +620,12 @@ 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(mnt_user_ns(path.mnt), d_inode(parent), err = vfs_rmdir(user_ns, d_inode(parent), path.dentry);
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(mnt_user_ns(path.mnt), d_inode(parent), err = vfs_unlink(user_ns, d_inode(parent), path.dentry, 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);
...@@ -748,7 +750,8 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work, ...@@ -748,7 +750,8 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
if (ksmbd_override_fsids(work)) if (ksmbd_override_fsids(work))
return -ENOMEM; return -ENOMEM;
dst_dent = lookup_one_len(dst_name, dst_dent_parent, strlen(dst_name)); dst_dent = lookup_one(dst_user_ns, dst_name, dst_dent_parent,
strlen(dst_name));
err = PTR_ERR(dst_dent); err = PTR_ERR(dst_dent);
if (IS_ERR(dst_dent)) { if (IS_ERR(dst_dent)) {
pr_err("lookup failed %s [%d]\n", dst_name, err); pr_err("lookup failed %s [%d]\n", dst_name, err);
...@@ -779,6 +782,7 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work, ...@@ -779,6 +782,7 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp, int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
char *newname) char *newname)
{ {
struct user_namespace *user_ns;
struct path dst_path; struct path dst_path;
struct dentry *src_dent_parent, *dst_dent_parent; struct dentry *src_dent_parent, *dst_dent_parent;
struct dentry *src_dent, *trap_dent, *src_child; struct dentry *src_dent, *trap_dent, *src_child;
...@@ -808,8 +812,9 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -808,8 +812,9 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp,
trap_dent = lock_rename(src_dent_parent, dst_dent_parent); trap_dent = lock_rename(src_dent_parent, dst_dent_parent);
dget(src_dent); dget(src_dent);
dget(dst_dent_parent); dget(dst_dent_parent);
src_child = lookup_one_len(src_dent->d_name.name, src_dent_parent, user_ns = file_mnt_user_ns(fp->filp);
src_dent->d_name.len); src_child = lookup_one(user_ns, src_dent->d_name.name, src_dent_parent,
src_dent->d_name.len);
if (IS_ERR(src_child)) { if (IS_ERR(src_child)) {
err = PTR_ERR(src_child); err = PTR_ERR(src_child);
goto out_lock; goto out_lock;
...@@ -823,7 +828,7 @@ int ksmbd_vfs_fp_rename(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -823,7 +828,7 @@ 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), user_ns,
src_dent_parent, src_dent_parent,
src_dent, src_dent,
mnt_user_ns(dst_path.mnt), mnt_user_ns(dst_path.mnt),
...@@ -1109,7 +1114,7 @@ int ksmbd_vfs_unlink(struct user_namespace *user_ns, ...@@ -1109,7 +1114,7 @@ int ksmbd_vfs_unlink(struct user_namespace *user_ns,
{ {
int err = 0; int err = 0;
err = ksmbd_vfs_lock_parent(dir, dentry); err = ksmbd_vfs_lock_parent(user_ns, dir, dentry);
if (err) if (err)
return err; return err;
dget(dentry); dget(dentry);
...@@ -1385,14 +1390,14 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac ...@@ -1385,14 +1390,14 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct user_namespac
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(user_ns, pa_entry->e_uid); xa_entry->uid = posix_acl_uid_translate(user_ns, pa_entry);
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(user_ns, pa_entry->e_gid); xa_entry->gid = posix_acl_gid_translate(user_ns, pa_entry);
break; break;
case ACL_GROUP_OBJ: case ACL_GROUP_OBJ:
xa_entry->type = SMB_ACL_GROUP_OBJ; xa_entry->type = SMB_ACL_GROUP_OBJ;
......
...@@ -107,7 +107,8 @@ struct ksmbd_kstat { ...@@ -107,7 +107,8 @@ struct ksmbd_kstat {
__le32 file_attributes; __le32 file_attributes;
}; };
int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child); int ksmbd_vfs_lock_parent(struct user_namespace *user_ns, struct dentry *parent,
struct dentry *child);
int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry); int ksmbd_vfs_may_delete(struct user_namespace *user_ns, struct dentry *dentry);
int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns, int ksmbd_vfs_query_maximal_access(struct user_namespace *user_ns,
struct dentry *dentry, __le32 *daccess); struct dentry *dentry, __le32 *daccess);
......
...@@ -666,22 +666,6 @@ void ksmbd_free_global_file_table(void) ...@@ -666,22 +666,6 @@ void ksmbd_free_global_file_table(void)
ksmbd_destroy_file_table(&global_ft); ksmbd_destroy_file_table(&global_ft);
} }
int ksmbd_file_table_flush(struct ksmbd_work *work)
{
struct ksmbd_file *fp = NULL;
unsigned int id;
int ret;
read_lock(&work->sess->file_table.lock);
idr_for_each_entry(work->sess->file_table.idr, fp, id) {
ret = ksmbd_vfs_fsync(work, fp->volatile_id, KSMBD_NO_FID);
if (ret)
break;
}
read_unlock(&work->sess->file_table.lock);
return ret;
}
int ksmbd_init_file_table(struct ksmbd_file_table *ft) int ksmbd_init_file_table(struct ksmbd_file_table *ft)
{ {
ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL); ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL);
......
...@@ -152,7 +152,6 @@ void ksmbd_close_session_fds(struct ksmbd_work *work); ...@@ -152,7 +152,6 @@ void ksmbd_close_session_fds(struct ksmbd_work *work);
int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode); int ksmbd_close_inode_fds(struct ksmbd_work *work, struct inode *inode);
int ksmbd_init_global_file_table(void); int ksmbd_init_global_file_table(void);
void ksmbd_free_global_file_table(void); void ksmbd_free_global_file_table(void);
int ksmbd_file_table_flush(struct ksmbd_work *work);
void ksmbd_set_fd_limit(unsigned long limit); void ksmbd_set_fd_limit(unsigned long limit);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment