History

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

Linus Torvalds committed 5 years ago

Commit 7c0ec892 parents 5ff2756 1bb56815 files · +150 −57Browse files

Unified · Split

5 files
  1. fs/cifs/cifs_ioctl.h +19 −6
  2. fs/cifs/cifspdu.h +2 −1
  3. fs/cifs/ioctl.c +105 −38
  4. fs/cifs/smb2pdu.c +7 −0
  5. fs/cifs/trace.h +17 −12
fs/cifs/cifs_ioctl.h+19−6
@@ -72,15 +72,28 @@ struct smb3_key_debug_info { · 71 unmodified lines
7272 } __packed;
7373
7474 /*
75− * Dump full key (32 byte encrypt/decrypt keys instead of 16 bytes)
76− * is needed if GCM256 (stronger encryption) negotiated
75+ * Dump variable-sized keys
7776 */
7877 struct smb3_full_key_debug_info {
79− __u64 Suid;
78+ /* INPUT: size of userspace buffer */
79+ __u32 in_size;
80+
81+ /*
82+ * INPUT: 0 for current user, otherwise session to dump
83+ * OUTPUT: session id that was dumped
84+ */
85+ __u64 session_id;
8086 __u16 cipher_type;
81− __u8 auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
82− __u8 smb3encryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
83− __u8 smb3decryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
87+ __u8 session_key_length;
88+ __u8 server_in_key_length;
89+ __u8 server_out_key_length;
90+ __u8 data[];
91+ /*
92+ * return this struct with the keys appended at the end:
93+ * __u8 session_key[session_key_length];
94+ * __u8 server_in_key[server_in_key_length];
95+ * __u8 server_out_key[server_out_key_length];
96+ */
8497 } __packed;
8598
8699 struct smb3_notify {
fs/cifs/cifspdu.h+2−1
@@ -148,7 +148,8 @@ · 147 unmodified lines
148148 #define SMB3_SIGN_KEY_SIZE (16)
149149
150150 /*
151− * Size of the smb3 encryption/decryption keys
151+ * Size of the smb3 encryption/decryption key storage.
152+ * This size is big enough to store any cipher key types.
152153 */
153154 #define SMB3_ENC_DEC_KEY_SIZE (32)
154155
fs/cifs/ioctl.c+105−38
@@ -33,6 +33,7 @@ · 32 unmodified lines
3333 #include "cifsfs.h"
3434 #include "cifs_ioctl.h"
3535 #include "smb2proto.h"
36+#include "smb2glob.h"
3637 #include <linux/btrfs.h>
3738
3839 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) · 175 unmodified lines
214215 return 0;
215216 }
216217
217−static int cifs_dump_full_key(struct cifs_tcon *tcon, unsigned long arg)
218+static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug_info __user *in)
218219 {
219− struct smb3_full_key_debug_info pfull_key_inf;
220− __u64 suid;
221− struct list_head *tmp;
220+ struct smb3_full_key_debug_info out;
222221 struct cifs_ses *ses;
222+ int rc = 0;
223223 bool found = false;
224+ u8 __user *end;
224225
225− if (!smb3_encryption_required(tcon))
226− return -EOPNOTSUPP;
226+ if (!smb3_encryption_required(tcon)) {
227+ rc = -EOPNOTSUPP;
228+ goto out;
229+ }
230+
231+ /* copy user input into our output buffer */
232+ if (copy_from_user(&out, in, sizeof(out))) {
233+ rc = -EINVAL;
234+ goto out;
235+ }
236+
237+ if (!out.session_id) {
238+ /* if ses id is 0, use current user session */
239+ ses = tcon->ses;
240+ } else {
241+ /* otherwise if a session id is given, look for it in all our sessions */
242+ struct cifs_ses *ses_it = NULL;
243+ struct TCP_Server_Info *server_it = NULL;
227244
228− ses = tcon->ses; /* default to user id for current user */
229− if (get_user(suid, (__u64 __user *)arg))
230− suid = 0;
231− if (suid) {
232− /* search to see if there is a session with a matching SMB UID */
233245 spin_lock(&cifs_tcp_ses_lock);
234− list_for_each(tmp, &tcon->ses->server->smb_ses_list) {
235− ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
236− if (ses->Suid == suid) {
237− found = true;
238− break;
246+ list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) {
247+ list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) {
248+ if (ses_it->Suid == out.session_id) {
249+ ses = ses_it;
250+ /*
251+ * since we are using the session outside the crit
252+ * section, we need to make sure it won't be released
253+ * so increment its refcount
254+ */
255+ ses->ses_count++;
256+ found = true;
257+ goto search_end;
258+ }
239259 }
240260 }
261+search_end:
241262 spin_unlock(&cifs_tcp_ses_lock);
242− if (found == false)
243− return -EINVAL;
244− } /* else uses default user's SMB UID (ie current user) */
245−
246− pfull_key_inf.cipher_type = le16_to_cpu(ses->server->cipher_type);
247− pfull_key_inf.Suid = ses->Suid;
248− memcpy(pfull_key_inf.auth_key, ses->auth_key.response,
249− 16 /* SMB2_NTLMV2_SESSKEY_SIZE */);
250− memcpy(pfull_key_inf.smb3decryptionkey, ses->smb3decryptionkey,
251− 32 /* SMB3_ENC_DEC_KEY_SIZE */);
252− memcpy(pfull_key_inf.smb3encryptionkey,
253− ses->smb3encryptionkey, 32 /* SMB3_ENC_DEC_KEY_SIZE */);
254− if (copy_to_user((void __user *)arg, &pfull_key_inf,
255− sizeof(struct smb3_full_key_debug_info)))
256− return -EFAULT;
263+ if (!found) {
264+ rc = -ENOENT;
265+ goto out;
266+ }
267+ }
257268
258− return 0;
269+ switch (ses->server->cipher_type) {
270+ case SMB2_ENCRYPTION_AES128_CCM:
271+ case SMB2_ENCRYPTION_AES128_GCM:
272+ out.session_key_length = CIFS_SESS_KEY_SIZE;
273+ out.server_in_key_length = out.server_out_key_length = SMB3_GCM128_CRYPTKEY_SIZE;
274+ break;
275+ case SMB2_ENCRYPTION_AES256_CCM:
276+ case SMB2_ENCRYPTION_AES256_GCM:
277+ out.session_key_length = CIFS_SESS_KEY_SIZE;
278+ out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE;
279+ break;
280+ default:
281+ rc = -EOPNOTSUPP;
282+ goto out;
283+ }
284+
285+ /* check if user buffer is big enough to store all the keys */
286+ if (out.in_size < sizeof(out) + out.session_key_length + out.server_in_key_length
287+ + out.server_out_key_length) {
288+ rc = -ENOBUFS;
289+ goto out;
290+ }
291+
292+ out.session_id = ses->Suid;
293+ out.cipher_type = le16_to_cpu(ses->server->cipher_type);
294+
295+ /* overwrite user input with our output */
296+ if (copy_to_user(in, &out, sizeof(out))) {
297+ rc = -EINVAL;
298+ goto out;
299+ }
300+
301+ /* append all the keys at the end of the user buffer */
302+ end = in->data;
303+ if (copy_to_user(end, ses->auth_key.response, out.session_key_length)) {
304+ rc = -EINVAL;
305+ goto out;
306+ }
307+ end += out.session_key_length;
308+
309+ if (copy_to_user(end, ses->smb3encryptionkey, out.server_in_key_length)) {
310+ rc = -EINVAL;
311+ goto out;
312+ }
313+ end += out.server_in_key_length;
314+
315+ if (copy_to_user(end, ses->smb3decryptionkey, out.server_out_key_length)) {
316+ rc = -EINVAL;
317+ goto out;
318+ }
319+
320+out:
321+ if (found)
322+ cifs_put_smb_ses(ses);
323+ return rc;
259324 }
260325
261326 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) · 109 unmodified lines
371436 rc = -EOPNOTSUPP;
372437 break;
373438 case CIFS_DUMP_KEY:
439+ /*
440+ * Dump encryption keys. This is an old ioctl that only
441+ * handles AES-128-{CCM,GCM}.
442+ */
374443 if (pSMBFile == NULL)
375444 break;
376445 if (!capable(CAP_SYS_ADMIN)) {
@@ -398,11 +467,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) · 21 unmodified lines
398467 else
399468 rc = 0;
400469 break;
401− /*
402− * Dump full key (32 bytes instead of 16 bytes) is
403− * needed if GCM256 (stronger encryption) negotiated
404− */
405470 case CIFS_DUMP_FULL_KEY:
471+ /*
472+ * Dump encryption keys (handles any key sizes)
473+ */
406474 if (pSMBFile == NULL)
407475 break;
408476 if (!capable(CAP_SYS_ADMIN)) {
@@ -410,8 +478,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg) · 1 unmodified line
410478 break;
411479 }
412480 tcon = tlink_tcon(pSMBFile->tlink);
413− rc = cifs_dump_full_key(tcon, arg);
414−
481+ rc = cifs_dump_full_key(tcon, (void __user *)arg);
415482 break;
416483 case CIFS_IOC_NOTIFY:
417484 if (!S_ISDIR(inode->i_mode)) {
fs/cifs/smb2pdu.c+7−0
@@ -958,6 +958,13 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses) · 957 unmodified lines
958958 /* Internal types */
959959 server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
960960
961+ /*
962+ * SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
963+ * Set the cipher type manually.
964+ */
965+ if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
966+ server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
967+
961968 security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
962969 (struct smb2_sync_hdr *)rsp);
963970 /*
fs/cifs/trace.h+17−12
@@ -12,6 +12,11 @@ · 11 unmodified lines
1212
1313 #include <linux/tracepoint.h>
1414
15+/*
16+ * Please use this 3-part article as a reference for writing new tracepoints:
17+ * https://lwn.net/Articles/379903/
18+ */
19+
1520 /* For logging errors in read or write */
1621 DECLARE_EVENT_CLASS(smb3_rw_err_class,
1722 TP_PROTO(unsigned int xid,
@@ -529,16 +534,16 @@ DECLARE_EVENT_CLASS(smb3_exit_err_class, · 511 unmodified lines
529534 TP_ARGS(xid, func_name, rc),
530535 TP_STRUCT__entry(
531536 __field(unsigned int, xid)
532− __field(const char *, func_name)
537+ __string(func_name, func_name)
533538 __field(int, rc)
534539 ),
535540 TP_fast_assign(
536541 __entry->xid = xid;
537− __entry->func_name = func_name;
542+ __assign_str(func_name, func_name);
538543 __entry->rc = rc;
539544 ),
540545 TP_printk("\t%s: xid=%u rc=%d",
541− __entry->func_name, __entry->xid, __entry->rc)
546+ __get_str(func_name), __entry->xid, __entry->rc)
542547 )
543548
544549 #define DEFINE_SMB3_EXIT_ERR_EVENT(name) \
@@ -583,14 +588,14 @@ DECLARE_EVENT_CLASS(smb3_enter_exit_class, · 38 unmodified lines
583588 TP_ARGS(xid, func_name),
584589 TP_STRUCT__entry(
585590 __field(unsigned int, xid)
586− __field(const char *, func_name)
591+ __string(func_name, func_name)
587592 ),
588593 TP_fast_assign(
589594 __entry->xid = xid;
590− __entry->func_name = func_name;
595+ __assign_str(func_name, func_name);
591596 ),
592597 TP_printk("\t%s: xid=%u",
593− __entry->func_name, __entry->xid)
598+ __get_str(func_name), __entry->xid)
594599 )
595600
596601 #define DEFINE_SMB3_ENTER_EXIT_EVENT(name) \
@@ -857,16 +862,16 @@ DECLARE_EVENT_CLASS(smb3_reconnect_class, · 260 unmodified lines
857862 TP_STRUCT__entry(
858863 __field(__u64, currmid)
859864 __field(__u64, conn_id)
860− __field(char *, hostname)
865+ __string(hostname, hostname)
861866 ),
862867 TP_fast_assign(
863868 __entry->currmid = currmid;
864869 __entry->conn_id = conn_id;
865− __entry->hostname = hostname;
870+ __assign_str(hostname, hostname);
866871 ),
867872 TP_printk("conn_id=0x%llx server=%s current_mid=%llu",
868873 __entry->conn_id,
869− __entry->hostname,
874+ __get_str(hostname),
870875 __entry->currmid)
871876 )
872877
@@ -891,7 +896,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class, · 18 unmodified lines
891896 TP_STRUCT__entry(
892897 __field(__u64, currmid)
893898 __field(__u64, conn_id)
894− __field(char *, hostname)
899+ __string(hostname, hostname)
895900 __field(int, credits)
896901 __field(int, credits_to_add)
897902 __field(int, in_flight)
@@ -899,7 +904,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class, · 1 unmodified line
899904 TP_fast_assign(
900905 __entry->currmid = currmid;
901906 __entry->conn_id = conn_id;
902− __entry->hostname = hostname;
907+ __assign_str(hostname, hostname);
903908 __entry->credits = credits;
904909 __entry->credits_to_add = credits_to_add;
905910 __entry->in_flight = in_flight;
@@ -907,7 +912,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class, · 1 unmodified line
907912 TP_printk("conn_id=0x%llx server=%s current_mid=%llu "
908913 "credits=%d credit_change=%d in_flight=%d",
909914 __entry->conn_id,
910− __entry->hostname,
915+ __get_str(hostname),
911916 __entry->currmid,
912917 __entry->credits,
913918 __entry->credits_to_add,

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t