3 SMB3 fixes, two for stable, and the other fixes a problem pointed out with a recently added ioctl
-----BEGIN PGP SIGNATURE----- iQGzBAABCgAdFiEE6fsu8pdIjtWE/DpLiiy9cAdyT1EFAmCxbv4ACgkQiiy9cAdy T1GkPwwAqq0tvNDZnQ6aAur1jwHMiOIAydvpgNKXlKkiXYu+qQbMRgOdUsOtjM00 Idi8PHKkID2X63HeiwLwoQTfTXGcs6I4UM1iOslEs2ZaX+Fkgo5PG25lIFRTAsqR tqYGqGi6yL6TWE7PlVJxr3QuwGeMr7B8X9A0lTZ7YJwslhByK8ymasPdF+jSgPQI zDOuAeXiYvlph8sCftWX7gF34aBfKgiH8LhA6M2SY5S16g7LwtXUJjq1PJactoD3 +nEPyCtRoN6ohScKNVnM8JDpOKIrM+mJ42RG28ZLo6//8so0SFcUdC8VhECBxOWL 9WkoL2GxRV0LoRnzCZS30EpAi/eQU+QlTrPueGp+n8GjauJMDPoxJ2l6UXox6CLm 8CqwxKATG6WbrdcGhaVbIxVbAWC7Ze271C/7L61R5K+RmDTXc6jI4vAIw1Pib4o+ CG6XtxHya5PM0zvyLgU28M6aY+WExbwnkSQKvI2FJZkOVG0xdFCy2O1QLLRBChmn a6hsA05a =8nZ2 -----END PGP SIGNATURE----- Merge tag '5.13-rc4-smb3' of git://git.samba.org/sfrench/cifs-2.6 Pull cifs fixes from Steve French: "Three SMB3 fixes. Two for stable, and the other fixes a problem pointed out with a recently added ioctl" * tag '5.13-rc4-smb3' of git://git.samba.org/sfrench/cifs-2.6: cifs: change format of CIFS_FULL_KEY_DUMP ioctl cifs: fix string declarations and assignments in tracepoints cifs: set server->cipher_type to AES-128-CCM for SMB3.0
This commit is contained in:
commit
7c0ec89d31
|
@ -72,15 +72,28 @@ struct smb3_key_debug_info {
|
|||
} __packed;
|
||||
|
||||
/*
|
||||
* Dump full key (32 byte encrypt/decrypt keys instead of 16 bytes)
|
||||
* is needed if GCM256 (stronger encryption) negotiated
|
||||
* Dump variable-sized keys
|
||||
*/
|
||||
struct smb3_full_key_debug_info {
|
||||
__u64 Suid;
|
||||
/* INPUT: size of userspace buffer */
|
||||
__u32 in_size;
|
||||
|
||||
/*
|
||||
* INPUT: 0 for current user, otherwise session to dump
|
||||
* OUTPUT: session id that was dumped
|
||||
*/
|
||||
__u64 session_id;
|
||||
__u16 cipher_type;
|
||||
__u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
|
||||
__u8 smb3encryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
|
||||
__u8 smb3decryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
|
||||
__u8 session_key_length;
|
||||
__u8 server_in_key_length;
|
||||
__u8 server_out_key_length;
|
||||
__u8 data[];
|
||||
/*
|
||||
* return this struct with the keys appended at the end:
|
||||
* __u8 session_key[session_key_length];
|
||||
* __u8 server_in_key[server_in_key_length];
|
||||
* __u8 server_out_key[server_out_key_length];
|
||||
*/
|
||||
} __packed;
|
||||
|
||||
struct smb3_notify {
|
||||
|
|
|
@ -148,7 +148,8 @@
|
|||
#define SMB3_SIGN_KEY_SIZE (16)
|
||||
|
||||
/*
|
||||
* Size of the smb3 encryption/decryption keys
|
||||
* Size of the smb3 encryption/decryption key storage.
|
||||
* This size is big enough to store any cipher key types.
|
||||
*/
|
||||
#define SMB3_ENC_DEC_KEY_SIZE (32)
|
||||
|
||||
|
|
141
fs/cifs/ioctl.c
141
fs/cifs/ioctl.c
|
@ -33,6 +33,7 @@
|
|||
#include "cifsfs.h"
|
||||
#include "cifs_ioctl.h"
|
||||
#include "smb2proto.h"
|
||||
#include "smb2glob.h"
|
||||
#include <linux/btrfs.h>
|
||||
|
||||
static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
|
||||
|
@ -214,48 +215,112 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cifs_dump_full_key(struct cifs_tcon *tcon, unsigned long arg)
|
||||
static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug_info __user *in)
|
||||
{
|
||||
struct smb3_full_key_debug_info pfull_key_inf;
|
||||
__u64 suid;
|
||||
struct list_head *tmp;
|
||||
struct smb3_full_key_debug_info out;
|
||||
struct cifs_ses *ses;
|
||||
int rc = 0;
|
||||
bool found = false;
|
||||
u8 __user *end;
|
||||
|
||||
if (!smb3_encryption_required(tcon))
|
||||
return -EOPNOTSUPP;
|
||||
if (!smb3_encryption_required(tcon)) {
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* copy user input into our output buffer */
|
||||
if (copy_from_user(&out, in, sizeof(out))) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!out.session_id) {
|
||||
/* if ses id is 0, use current user session */
|
||||
ses = tcon->ses;
|
||||
} else {
|
||||
/* otherwise if a session id is given, look for it in all our sessions */
|
||||
struct cifs_ses *ses_it = NULL;
|
||||
struct TCP_Server_Info *server_it = NULL;
|
||||
|
||||
ses = tcon->ses; /* default to user id for current user */
|
||||
if (get_user(suid, (__u64 __user *)arg))
|
||||
suid = 0;
|
||||
if (suid) {
|
||||
/* search to see if there is a session with a matching SMB UID */
|
||||
spin_lock(&cifs_tcp_ses_lock);
|
||||
list_for_each(tmp, &tcon->ses->server->smb_ses_list) {
|
||||
ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
|
||||
if (ses->Suid == suid) {
|
||||
found = true;
|
||||
break;
|
||||
list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) {
|
||||
list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) {
|
||||
if (ses_it->Suid == out.session_id) {
|
||||
ses = ses_it;
|
||||
/*
|
||||
* since we are using the session outside the crit
|
||||
* section, we need to make sure it won't be released
|
||||
* so increment its refcount
|
||||
*/
|
||||
ses->ses_count++;
|
||||
found = true;
|
||||
goto search_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
search_end:
|
||||
spin_unlock(&cifs_tcp_ses_lock);
|
||||
if (found == false)
|
||||
return -EINVAL;
|
||||
} /* else uses default user's SMB UID (ie current user) */
|
||||
if (!found) {
|
||||
rc = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
pfull_key_inf.cipher_type = le16_to_cpu(ses->server->cipher_type);
|
||||
pfull_key_inf.Suid = ses->Suid;
|
||||
memcpy(pfull_key_inf.auth_key, ses->auth_key.response,
|
||||
16 /* SMB2_NTLMV2_SESSKEY_SIZE */);
|
||||
memcpy(pfull_key_inf.smb3decryptionkey, ses->smb3decryptionkey,
|
||||
32 /* SMB3_ENC_DEC_KEY_SIZE */);
|
||||
memcpy(pfull_key_inf.smb3encryptionkey,
|
||||
ses->smb3encryptionkey, 32 /* SMB3_ENC_DEC_KEY_SIZE */);
|
||||
if (copy_to_user((void __user *)arg, &pfull_key_inf,
|
||||
sizeof(struct smb3_full_key_debug_info)))
|
||||
return -EFAULT;
|
||||
switch (ses->server->cipher_type) {
|
||||
case SMB2_ENCRYPTION_AES128_CCM:
|
||||
case SMB2_ENCRYPTION_AES128_GCM:
|
||||
out.session_key_length = CIFS_SESS_KEY_SIZE;
|
||||
out.server_in_key_length = out.server_out_key_length = SMB3_GCM128_CRYPTKEY_SIZE;
|
||||
break;
|
||||
case SMB2_ENCRYPTION_AES256_CCM:
|
||||
case SMB2_ENCRYPTION_AES256_GCM:
|
||||
out.session_key_length = CIFS_SESS_KEY_SIZE;
|
||||
out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE;
|
||||
break;
|
||||
default:
|
||||
rc = -EOPNOTSUPP;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
/* check if user buffer is big enough to store all the keys */
|
||||
if (out.in_size < sizeof(out) + out.session_key_length + out.server_in_key_length
|
||||
+ out.server_out_key_length) {
|
||||
rc = -ENOBUFS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out.session_id = ses->Suid;
|
||||
out.cipher_type = le16_to_cpu(ses->server->cipher_type);
|
||||
|
||||
/* overwrite user input with our output */
|
||||
if (copy_to_user(in, &out, sizeof(out))) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* append all the keys at the end of the user buffer */
|
||||
end = in->data;
|
||||
if (copy_to_user(end, ses->auth_key.response, out.session_key_length)) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
end += out.session_key_length;
|
||||
|
||||
if (copy_to_user(end, ses->smb3encryptionkey, out.server_in_key_length)) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
end += out.server_in_key_length;
|
||||
|
||||
if (copy_to_user(end, ses->smb3decryptionkey, out.server_out_key_length)) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
if (found)
|
||||
cifs_put_smb_ses(ses);
|
||||
return rc;
|
||||
}
|
||||
|
||||
long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
||||
|
@ -371,6 +436,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
|||
rc = -EOPNOTSUPP;
|
||||
break;
|
||||
case CIFS_DUMP_KEY:
|
||||
/*
|
||||
* Dump encryption keys. This is an old ioctl that only
|
||||
* handles AES-128-{CCM,GCM}.
|
||||
*/
|
||||
if (pSMBFile == NULL)
|
||||
break;
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
|
@ -398,11 +467,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
|||
else
|
||||
rc = 0;
|
||||
break;
|
||||
/*
|
||||
* Dump full key (32 bytes instead of 16 bytes) is
|
||||
* needed if GCM256 (stronger encryption) negotiated
|
||||
*/
|
||||
case CIFS_DUMP_FULL_KEY:
|
||||
/*
|
||||
* Dump encryption keys (handles any key sizes)
|
||||
*/
|
||||
if (pSMBFile == NULL)
|
||||
break;
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
|
@ -410,8 +478,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
tcon = tlink_tcon(pSMBFile->tlink);
|
||||
rc = cifs_dump_full_key(tcon, arg);
|
||||
|
||||
rc = cifs_dump_full_key(tcon, (void __user *)arg);
|
||||
break;
|
||||
case CIFS_IOC_NOTIFY:
|
||||
if (!S_ISDIR(inode->i_mode)) {
|
||||
|
|
|
@ -958,6 +958,13 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
|
|||
/* Internal types */
|
||||
server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
|
||||
|
||||
/*
|
||||
* SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
|
||||
* Set the cipher type manually.
|
||||
*/
|
||||
if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
|
||||
server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
|
||||
|
||||
security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
|
||||
(struct smb2_sync_hdr *)rsp);
|
||||
/*
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
/*
|
||||
* Please use this 3-part article as a reference for writing new tracepoints:
|
||||
* https://lwn.net/Articles/379903/
|
||||
*/
|
||||
|
||||
/* For logging errors in read or write */
|
||||
DECLARE_EVENT_CLASS(smb3_rw_err_class,
|
||||
TP_PROTO(unsigned int xid,
|
||||
|
@ -529,16 +534,16 @@ DECLARE_EVENT_CLASS(smb3_exit_err_class,
|
|||
TP_ARGS(xid, func_name, rc),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, xid)
|
||||
__field(const char *, func_name)
|
||||
__string(func_name, func_name)
|
||||
__field(int, rc)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->xid = xid;
|
||||
__entry->func_name = func_name;
|
||||
__assign_str(func_name, func_name);
|
||||
__entry->rc = rc;
|
||||
),
|
||||
TP_printk("\t%s: xid=%u rc=%d",
|
||||
__entry->func_name, __entry->xid, __entry->rc)
|
||||
__get_str(func_name), __entry->xid, __entry->rc)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_EXIT_ERR_EVENT(name) \
|
||||
|
@ -583,14 +588,14 @@ DECLARE_EVENT_CLASS(smb3_enter_exit_class,
|
|||
TP_ARGS(xid, func_name),
|
||||
TP_STRUCT__entry(
|
||||
__field(unsigned int, xid)
|
||||
__field(const char *, func_name)
|
||||
__string(func_name, func_name)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->xid = xid;
|
||||
__entry->func_name = func_name;
|
||||
__assign_str(func_name, func_name);
|
||||
),
|
||||
TP_printk("\t%s: xid=%u",
|
||||
__entry->func_name, __entry->xid)
|
||||
__get_str(func_name), __entry->xid)
|
||||
)
|
||||
|
||||
#define DEFINE_SMB3_ENTER_EXIT_EVENT(name) \
|
||||
|
@ -857,16 +862,16 @@ DECLARE_EVENT_CLASS(smb3_reconnect_class,
|
|||
TP_STRUCT__entry(
|
||||
__field(__u64, currmid)
|
||||
__field(__u64, conn_id)
|
||||
__field(char *, hostname)
|
||||
__string(hostname, hostname)
|
||||
),
|
||||
TP_fast_assign(
|
||||
__entry->currmid = currmid;
|
||||
__entry->conn_id = conn_id;
|
||||
__entry->hostname = hostname;
|
||||
__assign_str(hostname, hostname);
|
||||
),
|
||||
TP_printk("conn_id=0x%llx server=%s current_mid=%llu",
|
||||
__entry->conn_id,
|
||||
__entry->hostname,
|
||||
__get_str(hostname),
|
||||
__entry->currmid)
|
||||
)
|
||||
|
||||
|
@ -891,7 +896,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class,
|
|||
TP_STRUCT__entry(
|
||||
__field(__u64, currmid)
|
||||
__field(__u64, conn_id)
|
||||
__field(char *, hostname)
|
||||
__string(hostname, hostname)
|
||||
__field(int, credits)
|
||||
__field(int, credits_to_add)
|
||||
__field(int, in_flight)
|
||||
|
@ -899,7 +904,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class,
|
|||
TP_fast_assign(
|
||||
__entry->currmid = currmid;
|
||||
__entry->conn_id = conn_id;
|
||||
__entry->hostname = hostname;
|
||||
__assign_str(hostname, hostname);
|
||||
__entry->credits = credits;
|
||||
__entry->credits_to_add = credits_to_add;
|
||||
__entry->in_flight = in_flight;
|
||||
|
@ -907,7 +912,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class,
|
|||
TP_printk("conn_id=0x%llx server=%s current_mid=%llu "
|
||||
"credits=%d credit_change=%d in_flight=%d",
|
||||
__entry->conn_id,
|
||||
__entry->hostname,
|
||||
__get_str(hostname),
|
||||
__entry->currmid,
|
||||
__entry->credits,
|
||||
__entry->credits_to_add,
|
||||
|
|
Loading…
Reference in New Issue