Skip to content

Commit

Permalink
Merge tag '5.8-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/ci…
Browse files Browse the repository at this point in the history
…fs-2.6

Pull more cifs updates from Steve French:
 "12 cifs/smb3 fixes, 2 for stable.

   - add support for idsfromsid on create and chgrp/chown allowing
     ability to save owner information more naturally for some workloads

   - improve query info (getattr) when SMB3.1.1 posix extensions are
     negotiated by using new query info level"

* tag '5.8-rc-smb3-fixes-part2' of git://git.samba.org/sfrench/cifs-2.6:
  smb3: Add debug message for new file creation with idsfromsid mount option
  cifs: fix chown and chgrp when idsfromsid mount option enabled
  smb3: allow uid and gid owners to be set on create with idsfromsid mount option
  smb311: Add tracepoints for new compound posix query info
  smb311: add support for using info level for posix extensions query
  smb311: Add support for lookup with posix extensions query info
  smb311: Add support for SMB311 query info (non-compounded)
  SMB311: Add support for query info using posix extensions (level 100)
  smb3: add indatalen that can be a non-zero value to calculation of credit charge in smb2 ioctl
  smb3: fix typo in mount options displayed in /proc/mounts
  cifs: Add get_security_type_str function to return sec type.
  smb3: extend fscache mount volume coherency check
  • Loading branch information
torvalds committed Jun 13, 2020
2 parents 4f9b3a3 + a7a519a commit f82e7b5
Show file tree
Hide file tree
Showing 19 changed files with 571 additions and 57 deletions.
9 changes: 2 additions & 7 deletions fs/cifs/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,13 +53,6 @@ const struct fscache_cookie_def cifs_fscache_server_index_def = {
.type = FSCACHE_COOKIE_TYPE_INDEX,
};

/*
* Auxiliary data attached to CIFS superblock within the cache
*/
struct cifs_fscache_super_auxdata {
u64 resource_id; /* unique server resource id */
};

char *extract_sharename(const char *treename)
{
const char *src;
Expand Down Expand Up @@ -98,6 +91,8 @@ fscache_checkaux cifs_fscache_super_check_aux(void *cookie_netfs_data,

memset(&auxdata, 0, sizeof(auxdata));
auxdata.resource_id = tcon->resource_id;
auxdata.vol_create_time = tcon->vol_create_time;
auxdata.vol_serial_number = tcon->vol_serial_number;

if (memcmp(data, &auxdata, datalen) != 0)
return FSCACHE_CHECKAUX_OBSOLETE;
Expand Down
4 changes: 1 addition & 3 deletions fs/cifs/cifs_debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,6 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
struct cifs_ses *ses;
struct cifs_tcon *tcon;
int i, j;
const char *security_types[] = {"Unspecified", "LANMAN", "NTLM",
"NTLMv2", "RawNTLMSSP", "Kerberos"};

seq_puts(m,
"Display Internal CIFS Data Structures for Debugging\n"
Expand Down Expand Up @@ -379,7 +377,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
}

seq_printf(m,"Security type: %s\n",
security_types[server->ops->select_sectype(server, ses->sectype)]);
get_security_type_str(server->ops->select_sectype(server, ses->sectype)));

if (server->rdma)
seq_printf(m, "RDMA\n\t");
Expand Down
79 changes: 64 additions & 15 deletions fs/cifs/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,28 @@ unsigned int setup_special_mode_ACE(struct cifs_ace *pntace, __u64 nmode)
return ace_size;
}

unsigned int setup_special_user_owner_ACE(struct cifs_ace *pntace)
{
int i;
unsigned int ace_size = 28;

pntace->type = ACCESS_ALLOWED_ACE_TYPE;
pntace->flags = 0x0;
pntace->access_req = cpu_to_le32(GENERIC_ALL);
pntace->sid.num_subauth = 3;
pntace->sid.revision = 1;
for (i = 0; i < NUM_AUTHS; i++)
pntace->sid.authority[i] = sid_unix_NFS_users.authority[i];

pntace->sid.sub_auth[0] = sid_unix_NFS_users.sub_auth[0];
pntace->sid.sub_auth[1] = sid_unix_NFS_users.sub_auth[1];
pntace->sid.sub_auth[2] = cpu_to_le32(current_fsgid().val);

/* size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth*4) */
pntace->size = cpu_to_le16(ace_size);
return ace_size;
}

static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
struct cifs_sid *pgrpsid, __u64 nmode, bool modefromsid)
{
Expand Down Expand Up @@ -978,7 +1000,7 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
/* Convert permission bits from mode to equivalent CIFS ACL */
static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
__u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid,
bool mode_from_sid, int *aclflag)
bool mode_from_sid, bool id_from_sid, int *aclflag)
{
int rc = 0;
__u32 dacloffset;
Expand Down Expand Up @@ -1019,12 +1041,23 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
if (!nowner_sid_ptr)
return -ENOMEM;
id = from_kuid(&init_user_ns, uid);
rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
if (rc) {
cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
__func__, rc, id);
kfree(nowner_sid_ptr);
return rc;
if (id_from_sid) {
struct owner_sid *osid = (struct owner_sid *)nowner_sid_ptr;
/* Populate the user ownership fields S-1-5-88-1 */
osid->Revision = 1;
osid->NumAuth = 3;
osid->Authority[5] = 5;
osid->SubAuthorities[0] = cpu_to_le32(88);
osid->SubAuthorities[1] = cpu_to_le32(1);
osid->SubAuthorities[2] = cpu_to_le32(id);
} else { /* lookup sid with upcall */
rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
if (rc) {
cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
__func__, rc, id);
kfree(nowner_sid_ptr);
return rc;
}
}
cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
kfree(nowner_sid_ptr);
Expand All @@ -1039,12 +1072,23 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
if (!ngroup_sid_ptr)
return -ENOMEM;
id = from_kgid(&init_user_ns, gid);
rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
if (rc) {
cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
__func__, rc, id);
kfree(ngroup_sid_ptr);
return rc;
if (id_from_sid) {
struct owner_sid *gsid = (struct owner_sid *)ngroup_sid_ptr;
/* Populate the group ownership fields S-1-5-88-2 */
gsid->Revision = 1;
gsid->NumAuth = 3;
gsid->Authority[5] = 5;
gsid->SubAuthorities[0] = cpu_to_le32(88);
gsid->SubAuthorities[1] = cpu_to_le32(2);
gsid->SubAuthorities[2] = cpu_to_le32(id);
} else { /* lookup sid with upcall */
rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
if (rc) {
cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
__func__, rc, id);
kfree(ngroup_sid_ptr);
return rc;
}
}
cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
kfree(ngroup_sid_ptr);
Expand Down Expand Up @@ -1247,7 +1291,7 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
struct smb_version_operations *ops;
bool mode_from_sid;
bool mode_from_sid, id_from_sid;

if (IS_ERR(tlink))
return PTR_ERR(tlink);
Expand Down Expand Up @@ -1290,8 +1334,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
else
mode_from_sid = false;

if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UID_FROM_ACL)
id_from_sid = true;
else
id_from_sid = false;

rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
mode_from_sid, &aclflag);
mode_from_sid, id_from_sid, &aclflag);

cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);

Expand Down
15 changes: 15 additions & 0 deletions fs/cifs/cifsacl.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,21 @@ struct smb3_acl {
__le16 Sbz2; /* MBZ */
} __packed;

/*
* Used to store the special 'NFS SIDs' used to persist the POSIX uid and gid
* See See http://technet.microsoft.com/en-us/library/hh509017(v=ws.10).aspx
*/
struct owner_sid {
u8 Revision;
u8 NumAuth;
u8 Authority[6];
__le32 SubAuthorities[3];
} __packed;

struct owner_group_sids {
struct owner_sid owner;
struct owner_sid group;
} __packed;

/*
* Minimum security identifier can be one for system defined Users
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root)
seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ);

if (tcon->ses->chan_max > 1)
seq_printf(s, ",multichannel,max_channel=%zu",
seq_printf(s, ",multichannel,max_channels=%zu",
tcon->ses->chan_max);

return 0;
Expand Down
18 changes: 18 additions & 0 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -2008,6 +2008,24 @@ extern struct smb_version_values smb302_values;
extern struct smb_version_operations smb311_operations;
extern struct smb_version_values smb311_values;

static inline char *get_security_type_str(enum securityEnum sectype)
{
switch (sectype) {
case RawNTLMSSP:
return "RawNTLMSSP";
case Kerberos:
return "Kerberos";
case NTLMv2:
return "NTLMv2";
case NTLM:
return "NTLM";
case LANMAN:
return "LANMAN";
default:
return "Unknown";
}
}

static inline bool is_smb1_server(struct TCP_Server_Info *server)
{
return strcmp(server->vals->version_string, SMB1_VERSION_STRING) == 0;
Expand Down
3 changes: 3 additions & 0 deletions fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,8 @@ extern struct inode *cifs_iget(struct super_block *sb,
extern int cifs_get_inode_info(struct inode **inode, const char *full_path,
FILE_ALL_INFO *data, struct super_block *sb,
int xid, const struct cifs_fid *fid);
extern int smb311_posix_get_inode_info(struct inode **pinode, const char *search_path,
struct super_block *sb, unsigned int xid);
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb, unsigned int xid);
Expand All @@ -220,6 +222,7 @@ extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *,
const char *, int);
extern unsigned int setup_authusers_ACE(struct cifs_ace *pace);
extern unsigned int setup_special_mode_ACE(struct cifs_ace *pace, __u64 nmode);
extern unsigned int setup_special_user_owner_ACE(struct cifs_ace *pace);

extern void dequeue_mid(struct mid_q_entry *mid, bool malformed);
extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf,
Expand Down
5 changes: 4 additions & 1 deletion fs/cifs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ cifs_do_create(struct inode *inode, struct dentry *direntry, unsigned int xid,
rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb,
xid);
else {
/* TODO: Add support for calling POSIX query info here, but passing in fid */
rc = cifs_get_inode_info(&newinode, full_path, buf, inode->i_sb,
xid, fid);
if (newinode) {
Expand Down Expand Up @@ -700,7 +701,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
cifs_dbg(FYI, "Full path: %s inode = 0x%p\n",
full_path, d_inode(direntry));

if (pTcon->unix_ext) {
if (pTcon->posix_extensions)
rc = smb311_posix_get_inode_info(&newInode, full_path, parent_dir_inode->i_sb, xid);
else if (pTcon->unix_ext) {
rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb, xid);
} else {
Expand Down
5 changes: 4 additions & 1 deletion fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb,
if (rc)
goto out;

/* TODO: Add support for calling posix query info but with passing in fid */
if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path, inode->i_sb,
xid);
Expand Down Expand Up @@ -800,7 +801,9 @@ cifs_reopen_file(struct cifsFileInfo *cfile, bool can_flush)
if (!is_interrupt_error(rc))
mapping_set_error(inode->i_mapping, rc);

if (tcon->unix_ext)
if (tcon->posix_extensions)
rc = smb311_posix_get_inode_info(&inode, full_path, inode->i_sb, xid);
else if (tcon->unix_ext)
rc = cifs_get_inode_info_unix(&inode, full_path,
inode->i_sb, xid);
else
Expand Down
17 changes: 15 additions & 2 deletions fs/cifs/fscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
{
struct TCP_Server_Info *server = tcon->ses->server;
char *sharename;
struct cifs_fscache_super_auxdata auxdata;

sharename = extract_sharename(tcon->treeName);
if (IS_ERR(sharename)) {
Expand All @@ -104,11 +105,16 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)
return;
}

memset(&auxdata, 0, sizeof(auxdata));
auxdata.resource_id = tcon->resource_id;
auxdata.vol_create_time = tcon->vol_create_time;
auxdata.vol_serial_number = tcon->vol_serial_number;

tcon->fscache =
fscache_acquire_cookie(server->fscache,
&cifs_fscache_super_index_def,
sharename, strlen(sharename),
&tcon->resource_id, sizeof(tcon->resource_id),
&auxdata, sizeof(auxdata),
tcon, 0, true);
kfree(sharename);
cifs_dbg(FYI, "%s: (0x%p/0x%p)\n",
Expand All @@ -117,8 +123,15 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon)

void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon)
{
struct cifs_fscache_super_auxdata auxdata;

memset(&auxdata, 0, sizeof(auxdata));
auxdata.resource_id = tcon->resource_id;
auxdata.vol_create_time = tcon->vol_create_time;
auxdata.vol_serial_number = tcon->vol_serial_number;

cifs_dbg(FYI, "%s: (0x%p)\n", __func__, tcon->fscache);
fscache_relinquish_cookie(tcon->fscache, &tcon->resource_id, false);
fscache_relinquish_cookie(tcon->fscache, &auxdata, false);
tcon->fscache = NULL;
}

Expand Down
9 changes: 9 additions & 0 deletions fs/cifs/fscache.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@

#ifdef CONFIG_CIFS_FSCACHE

/*
* Auxiliary data attached to CIFS superblock within the cache
*/
struct cifs_fscache_super_auxdata {
u64 resource_id; /* unique server resource id */
__le64 vol_create_time;
u32 vol_serial_number;
} __packed;

/*
* Auxiliary data attached to CIFS inode within the cache
*/
Expand Down
Loading

0 comments on commit f82e7b5

Please sign in to comment.