Skip to content

Commit

Permalink
Merge tag '5.4-rc-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6
Browse files Browse the repository at this point in the history
Pull more cifs updates from Steve French:
 "Fixes from the recent SMB3 Test events and Storage Developer
  Conference (held the last two weeks).

  Here are nine smb3 patches including an important patch for debugging
  traces with wireshark, with three patches marked for stable.

  Additional fixes from last week to better handle some newly discovered
  reparse points, and a fix the create/mkdir path for setting the mode
  more atomically (in SMB3 Create security descriptor context), and one
  for path name processing are still being tested so are not included
  here"

* tag '5.4-rc-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6:
  CIFS: Fix oplock handling for SMB 2.1+ protocols
  smb3: missing ACL related flags
  smb3: pass mode bits into create calls
  smb3: Add missing reparse tags
  CIFS: fix max ea value size
  fs/cifs/sess.c: Remove set but not used variable 'capabilities'
  fs/cifs/smb2pdu.c: Make SMB2_notify_init static
  smb3: fix leak in "open on server" perf counter
  smb3: allow decryption keys to be dumped by admin for debugging
  • Loading branch information
torvalds committed Sep 30, 2019
2 parents 3f2dc27 + a016e27 commit 7edee52
Show file tree
Hide file tree
Showing 14 changed files with 194 additions and 26 deletions.
9 changes: 9 additions & 0 deletions fs/cifs/cifs_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,18 @@ struct smb_query_info {
/* char buffer[]; */
} __packed;

struct smb3_key_debug_info {
__u64 Suid;
__u16 cipher_type;
__u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
__u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
__u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
} __packed;

#define CIFS_IOCTL_MAGIC 0xCF
#define CIFS_IOC_COPYCHUNK_FILE _IOW(CIFS_IOCTL_MAGIC, 3, int)
#define CIFS_IOC_SET_INTEGRITY _IO(CIFS_IOCTL_MAGIC, 4)
#define CIFS_IOC_GET_MNT_INFO _IOR(CIFS_IOCTL_MAGIC, 5, struct smb_mnt_fs_info)
#define CIFS_ENUMERATE_SNAPSHOTS _IOR(CIFS_IOCTL_MAGIC, 6, struct smb_snapshot_array)
#define CIFS_QUERY_INFO _IOWR(CIFS_IOCTL_MAGIC, 7, struct smb_query_info)
#define CIFS_DUMP_KEY _IOWR(CIFS_IOCTL_MAGIC, 8, struct smb3_key_debug_info)
81 changes: 80 additions & 1 deletion fs/cifs/cifsacl.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,93 @@ struct cifs_acl {
__le32 num_aces;
} __attribute__((packed));

/* ACE types - see MS-DTYP 2.4.4.1 */
#define ACCESS_ALLOWED_ACE_TYPE 0x00
#define ACCESS_DENIED_ACE_TYPE 0x01
#define SYSTEM_AUDIT_ACE_TYPE 0x02
#define SYSTEM_ALARM_ACE_TYPE 0x03
#define ACCESS_ALLOWED_COMPOUND_ACE_TYPE 0x04
#define ACCESS_ALLOWED_OBJECT_ACE_TYPE 0x05
#define ACCESS_DENIED_OBJECT_ACE_TYPE 0x06
#define SYSTEM_AUDIT_OBJECT_ACE_TYPE 0x07
#define SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08
#define ACCESS_ALLOWED_CALLBACK_ACE_TYPE 0x09
#define ACCESS_DENIED_CALLBACK_ACE_TYPE 0x0A
#define ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE 0x0B
#define ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE 0x0C
#define SYSTEM_AUDIT_CALLBACK_ACE_TYPE 0x0D
#define SYSTEM_ALARM_CALLBACK_ACE_TYPE 0x0E /* Reserved */
#define SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE 0x0F
#define SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE 0x10 /* reserved */
#define SYSTEM_MANDATORY_LABEL_ACE_TYPE 0x11
#define SYSTEM_RESOURCE_ATTRIBUTE_ACE_TYPE 0x12
#define SYSTEM_SCOPED_POLICY_ID_ACE_TYPE 0x13

/* ACE flags */
#define OBJECT_INHERIT_ACE 0x01
#define CONTAINER_INHERIT_ACE 0x02
#define NO_PROPAGATE_INHERIT_ACE 0x04
#define INHERIT_ONLY_ACE 0x08
#define INHERITED_ACE 0x10
#define SUCCESSFUL_ACCESS_ACE_FLAG 0x40
#define FAILED_ACCESS_ACE_FLAG 0x80

struct cifs_ace {
__u8 type;
__u8 type; /* see above and MS-DTYP 2.4.4.1 */
__u8 flags;
__le16 size;
__le32 access_req;
struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
} __attribute__((packed));

/*
* The current SMB3 form of security descriptor is similar to what was used for
* cifs (see above) but some fields are split, and fields in the struct below
* matches names of fields to the the spec, MS-DTYP (see sections 2.4.5 and
* 2.4.6). Note that "CamelCase" fields are used in this struct in order to
* match the MS-DTYP and MS-SMB2 specs which define the wire format.
*/
struct smb3_sd {
__u8 Revision; /* revision level, MUST be one */
__u8 Sbz1; /* only meaningful if 'RM' flag set below */
__le16 Control;
__le32 OffsetOwner;
__le32 OffsetGroup;
__le32 OffsetSacl;
__le32 OffsetDacl;
} __packed;

/* Meaning of 'Control' field flags */
#define ACL_CONTROL_SR 0x0001 /* Self relative */
#define ACL_CONTROL_RM 0x0002 /* Resource manager control bits */
#define ACL_CONTROL_PS 0x0004 /* SACL protected from inherits */
#define ACL_CONTROL_PD 0x0008 /* DACL protected from inherits */
#define ACL_CONTROL_SI 0x0010 /* SACL Auto-Inherited */
#define ACL_CONTROL_DI 0x0020 /* DACL Auto-Inherited */
#define ACL_CONTROL_SC 0x0040 /* SACL computed through inheritance */
#define ACL_CONTROL_DC 0x0080 /* DACL computed through inheritence */
#define ACL_CONTROL_SS 0x0100 /* Create server ACL */
#define ACL_CONTROL_DT 0x0200 /* DACL provided by trusteed source */
#define ACL_CONTROL_SD 0x0400 /* SACL defaulted */
#define ACL_CONTROL_SP 0x0800 /* SACL is present on object */
#define ACL_CONTROL_DD 0x1000 /* DACL defaulted */
#define ACL_CONTROL_DP 0x2000 /* DACL is present on object */
#define ACL_CONTROL_GD 0x4000 /* Group was defaulted */
#define ACL_CONTROL_OD 0x8000 /* User was defaulted */

/* Meaning of AclRevision flags */
#define ACL_REVISION 0x02 /* See section 2.4.4.1 of MS-DTYP */
#define ACL_REVISION_DS 0x04 /* Additional AceTypes allowed */

struct smb3_acl {
u8 AclRevision; /* revision level */
u8 Sbz1; /* MBZ */
__le16 AclSize;
__le16 AceCount;
__le16 Sbz2; /* MBZ */
} __packed;


/*
* Minimum security identifier can be one for system defined Users
* and Groups such as NULL SID and World or Built-in accounts such
Expand Down
6 changes: 4 additions & 2 deletions fs/cifs/cifsglob.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,8 +331,9 @@ struct smb_version_operations {
umode_t mode, struct cifs_tcon *tcon,
const char *full_path,
struct cifs_sb_info *cifs_sb);
int (*mkdir)(const unsigned int, struct cifs_tcon *, const char *,
struct cifs_sb_info *);
int (*mkdir)(const unsigned int xid, struct inode *inode, umode_t mode,
struct cifs_tcon *tcon, const char *name,
struct cifs_sb_info *sb);
/* set info on created directory */
void (*mkdir_setinfo)(struct inode *, const char *,
struct cifs_sb_info *, struct cifs_tcon *,
Expand Down Expand Up @@ -1209,6 +1210,7 @@ struct cifs_search_info {
bool smallBuf:1; /* so we know which buf_release function to call */
};

#define ACL_NO_MODE -1
struct cifs_open_parms {
struct cifs_tcon *tcon;
struct cifs_sb_info *cifs_sb;
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ extern int CIFSSMBUnixSetPathInfo(const unsigned int xid,
const struct nls_table *nls_codepage,
int remap);

extern int CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon,
extern int CIFSSMBMkDir(const unsigned int xid, struct inode *inode,
umode_t mode, struct cifs_tcon *tcon,
const char *name, struct cifs_sb_info *cifs_sb);
extern int CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon,
const char *name, struct cifs_sb_info *cifs_sb);
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1078,7 +1078,8 @@ CIFSSMBRmDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
}

int
CIFSSMBMkDir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
CIFSSMBMkDir(const unsigned int xid, struct inode *inode, umode_t mode,
struct cifs_tcon *tcon, const char *name,
struct cifs_sb_info *cifs_sb)
{
int rc = 0;
Expand Down
3 changes: 2 additions & 1 deletion fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1622,13 +1622,14 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode)
}

/* BB add setting the equivalent of mode via CreateX w/ACLs */
rc = server->ops->mkdir(xid, tcon, full_path, cifs_sb);
rc = server->ops->mkdir(xid, inode, mode, tcon, full_path, cifs_sb);
if (rc) {
cifs_dbg(FYI, "cifs_mkdir returned 0x%x\n", rc);
d_drop(direntry);
goto mkdir_out;
}

/* TODO: skip this for smb2/smb3 */
rc = cifs_mkdir_qinfo(inode, direntry, mode, full_path, cifs_sb, tcon,
xid);
mkdir_out:
Expand Down
29 changes: 29 additions & 0 deletions fs/cifs/ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ static long smb_mnt_get_fsinfo(unsigned int xid, struct cifs_tcon *tcon,
long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
{
struct inode *inode = file_inode(filep);
struct smb3_key_debug_info pkey_inf;
int rc = -ENOTTY; /* strange error - but the precedent */
unsigned int xid;
struct cifsFileInfo *pSMBFile = filep->private_data;
Expand Down Expand Up @@ -270,6 +271,34 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
else
rc = -EOPNOTSUPP;
break;
case CIFS_DUMP_KEY:
if (pSMBFile == NULL)
break;
if (!capable(CAP_SYS_ADMIN)) {
rc = -EACCES;
break;
}

tcon = tlink_tcon(pSMBFile->tlink);
if (!smb3_encryption_required(tcon)) {
rc = -EOPNOTSUPP;
break;
}
pkey_inf.cipher_type =
le16_to_cpu(tcon->ses->server->cipher_type);
pkey_inf.Suid = tcon->ses->Suid;
memcpy(pkey_inf.auth_key, tcon->ses->auth_key.response,
16 /* SMB2_NTLMV2_SESSKEY_SIZE */);
memcpy(pkey_inf.smb3decryptionkey,
tcon->ses->smb3decryptionkey, SMB3_SIGN_KEY_SIZE);
memcpy(pkey_inf.smb3encryptionkey,
tcon->ses->smb3encryptionkey, SMB3_SIGN_KEY_SIZE);
if (copy_to_user((void __user *)arg, &pkey_inf,
sizeof(struct smb3_key_debug_info)))
rc = -EFAULT;
else
rc = 0;
break;
default:
cifs_dbg(FYI, "unsupported ioctl\n");
break;
Expand Down
3 changes: 1 addition & 2 deletions fs/cifs/sess.c
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,6 @@ sess_auth_lanman(struct sess_data *sess_data)
char *bcc_ptr;
struct cifs_ses *ses = sess_data->ses;
char lnm_session_key[CIFS_AUTH_RESP_SIZE];
__u32 capabilities;
__u16 bytes_remaining;

/* lanman 2 style sessionsetup */
Expand All @@ -709,7 +708,7 @@ sess_auth_lanman(struct sess_data *sess_data)

pSMB = (SESSION_SETUP_ANDX *)sess_data->iov[0].iov_base;
bcc_ptr = sess_data->iov[2].iov_base;
capabilities = cifs_ssetup_hdr(ses, pSMB);
(void)cifs_ssetup_hdr(ses, pSMB);

pSMB->req.hdr.Flags2 &= ~SMBFLG2_UNICODE;

Expand Down
34 changes: 19 additions & 15 deletions fs/cifs/smb2inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static int
smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb, const char *full_path,
__u32 desired_access, __u32 create_disposition,
__u32 create_options, void *ptr, int command,
__u32 create_options, umode_t mode, void *ptr, int command,
struct cifsFileInfo *cfile)
{
int rc;
Expand Down Expand Up @@ -103,6 +103,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
oparms.create_options |= CREATE_OPEN_BACKUP_INTENT;
oparms.fid = &fid;
oparms.reconnect = false;
oparms.mode = mode;

memset(&open_iov, 0, sizeof(open_iov));
rqst[num_rqst].rq_iov = open_iov;
Expand Down Expand Up @@ -478,16 +479,16 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
cifs_get_readable_path(tcon, full_path, &cfile);
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
smb2_data, SMB2_OP_QUERY_INFO, cfile);
ACL_NO_MODE, smb2_data, SMB2_OP_QUERY_INFO, cfile);
if (rc == -EOPNOTSUPP) {
*symlink = true;
create_options |= OPEN_REPARSE_POINT;

/* Failed on a symbolic link - query a reparse point info */
rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
FILE_READ_ATTRIBUTES, FILE_OPEN,
create_options, smb2_data,
SMB2_OP_QUERY_INFO, NULL);
create_options, ACL_NO_MODE,
smb2_data, SMB2_OP_QUERY_INFO, NULL);
}
if (rc)
goto out;
Expand All @@ -499,12 +500,14 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
}

int
smb2_mkdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
smb2_mkdir(const unsigned int xid, struct inode *parent_inode, umode_t mode,
struct cifs_tcon *tcon, const char *name,
struct cifs_sb_info *cifs_sb)
{
return smb2_compound_op(xid, tcon, cifs_sb, name,
FILE_WRITE_ATTRIBUTES, FILE_CREATE,
CREATE_NOT_FILE, NULL, SMB2_OP_MKDIR, NULL);
CREATE_NOT_FILE, mode, NULL, SMB2_OP_MKDIR,
NULL);
}

void
Expand All @@ -525,8 +528,8 @@ smb2_mkdir_setinfo(struct inode *inode, const char *name,
cifs_get_writable_path(tcon, name, &cfile);
tmprc = smb2_compound_op(xid, tcon, cifs_sb, name,
FILE_WRITE_ATTRIBUTES, FILE_CREATE,
CREATE_NOT_FILE, &data, SMB2_OP_SET_INFO,
cfile);
CREATE_NOT_FILE, ACL_NO_MODE,
&data, SMB2_OP_SET_INFO, cfile);
if (tmprc == 0)
cifs_i->cifsAttrs = dosattrs;
}
Expand All @@ -536,7 +539,7 @@ smb2_rmdir(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
struct cifs_sb_info *cifs_sb)
{
return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
CREATE_NOT_FILE,
CREATE_NOT_FILE, ACL_NO_MODE,
NULL, SMB2_OP_RMDIR, NULL);
}

Expand All @@ -546,7 +549,7 @@ smb2_unlink(const unsigned int xid, struct cifs_tcon *tcon, const char *name,
{
return smb2_compound_op(xid, tcon, cifs_sb, name, DELETE, FILE_OPEN,
CREATE_DELETE_ON_CLOSE | OPEN_REPARSE_POINT,
NULL, SMB2_OP_DELETE, NULL);
ACL_NO_MODE, NULL, SMB2_OP_DELETE, NULL);
}

static int
Expand All @@ -564,7 +567,8 @@ smb2_set_path_attr(const unsigned int xid, struct cifs_tcon *tcon,
goto smb2_rename_path;
}
rc = smb2_compound_op(xid, tcon, cifs_sb, from_name, access,
FILE_OPEN, 0, smb2_to_name, command, cfile);
FILE_OPEN, 0, ACL_NO_MODE, smb2_to_name,
command, cfile);
smb2_rename_path:
kfree(smb2_to_name);
return rc;
Expand Down Expand Up @@ -601,8 +605,8 @@ smb2_set_path_size(const unsigned int xid, struct cifs_tcon *tcon,
__le64 eof = cpu_to_le64(size);

return smb2_compound_op(xid, tcon, cifs_sb, full_path,
FILE_WRITE_DATA, FILE_OPEN, 0, &eof,
SMB2_OP_SET_EOF, NULL);
FILE_WRITE_DATA, FILE_OPEN, 0, ACL_NO_MODE,
&eof, SMB2_OP_SET_EOF, NULL);
}

int
Expand All @@ -623,8 +627,8 @@ smb2_set_file_info(struct inode *inode, const char *full_path,
return PTR_ERR(tlink);

rc = smb2_compound_op(xid, tlink_tcon(tlink), cifs_sb, full_path,
FILE_WRITE_ATTRIBUTES, FILE_OPEN, 0, buf,
SMB2_OP_SET_INFO, NULL);
FILE_WRITE_ATTRIBUTES, FILE_OPEN,
0, ACL_NO_MODE, buf, SMB2_OP_SET_INFO, NULL);
cifs_put_tlink(tlink);
return rc;
}
10 changes: 10 additions & 0 deletions fs/cifs/smb2ops.c
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,8 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
goto oshr_exit;
}

atomic_inc(&tcon->num_remote_opens);

o_rsp = (struct smb2_create_rsp *)rsp_iov[0].iov_base;
oparms.fid->persistent_fid = o_rsp->PersistentFileId;
oparms.fid->volatile_fid = o_rsp->VolatileFileId;
Expand Down Expand Up @@ -1176,6 +1178,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,

rc = compound_send_recv(xid, ses, flags, 3, rqst,
resp_buftype, rsp_iov);
/* no need to bump num_remote_opens because handle immediately closed */

sea_exit:
kfree(ea);
Expand Down Expand Up @@ -1518,6 +1521,8 @@ smb2_ioctl_query_info(const unsigned int xid,
resp_buftype, rsp_iov);
if (rc)
goto iqinf_exit;

/* No need to bump num_remote_opens since handle immediately closed */
if (qi.flags & PASSTHRU_FSCTL) {
pqi = (struct smb_query_info __user *)arg;
io_rsp = (struct smb2_ioctl_rsp *)rsp_iov[1].iov_base;
Expand Down Expand Up @@ -3328,6 +3333,11 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
return;

/* Check if the server granted an oplock rather than a lease */
if (oplock & SMB2_OPLOCK_LEVEL_EXCLUSIVE)
return smb2_set_oplock_level(cinode, oplock, epoch,
purge_cache);

if (oplock & SMB2_LEASE_READ_CACHING_HE) {
new_oplock |= CIFS_CACHE_READ_FLG;
strcat(message, "R");
Expand Down
Loading

0 comments on commit 7edee52

Please sign in to comment.