~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/smb/server/smb2misc.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /fs/smb/server/smb2misc.c (Version linux-6.11-rc3) and /fs/smb/server/smb2misc.c (Version linux-4.13.16)


  1 // SPDX-License-Identifier: GPL-2.0-or-later        1 
  2 /*                                                
  3  *   Copyright (C) 2016 Namjae Jeon <linkinjeo    
  4  *   Copyright (C) 2018 Samsung Electronics Co    
  5  */                                               
  6                                                   
  7 #include "glob.h"                                 
  8 #include "nterr.h"                                
  9 #include "smb_common.h"                           
 10 #include "smbstatus.h"                            
 11 #include "mgmt/user_session.h"                    
 12 #include "connection.h"                           
 13                                                   
 14 static int check_smb2_hdr(struct smb2_hdr *hdr    
 15 {                                                 
 16         /*                                        
 17          * Make sure that this really is an SM    
 18          */                                       
 19         if (hdr->Flags & SMB2_FLAGS_SERVER_TO_    
 20                 return 1;                         
 21         return 0;                                 
 22 }                                                 
 23                                                   
 24 /*                                                
 25  *  The following table defines the expected "    
 26  *  in order by SMB2 command.  This is similar    
 27  *                                                
 28  *  Note that commands are defined in smb2pdu.    
 29  *  indexed by command in host byte order         
 30  */                                               
 31 static const __le16 smb2_req_struct_sizes[NUMB    
 32         /* SMB2_NEGOTIATE */ cpu_to_le16(36),     
 33         /* SMB2_SESSION_SETUP */ cpu_to_le16(2    
 34         /* SMB2_LOGOFF */ cpu_to_le16(4),         
 35         /* SMB2_TREE_CONNECT */ cpu_to_le16(9)    
 36         /* SMB2_TREE_DISCONNECT */ cpu_to_le16    
 37         /* SMB2_CREATE */ cpu_to_le16(57),        
 38         /* SMB2_CLOSE */ cpu_to_le16(24),         
 39         /* SMB2_FLUSH */ cpu_to_le16(24),         
 40         /* SMB2_READ */ cpu_to_le16(49),          
 41         /* SMB2_WRITE */ cpu_to_le16(49),         
 42         /* SMB2_LOCK */ cpu_to_le16(48),          
 43         /* SMB2_IOCTL */ cpu_to_le16(57),         
 44         /* SMB2_CANCEL */ cpu_to_le16(4),         
 45         /* SMB2_ECHO */ cpu_to_le16(4),           
 46         /* SMB2_QUERY_DIRECTORY */ cpu_to_le16    
 47         /* SMB2_CHANGE_NOTIFY */ cpu_to_le16(3    
 48         /* SMB2_QUERY_INFO */ cpu_to_le16(41),    
 49         /* SMB2_SET_INFO */ cpu_to_le16(33),      
 50         /* use 44 for lease break */              
 51         /* SMB2_OPLOCK_BREAK */ cpu_to_le16(36    
 52 };                                                
 53                                                   
 54 /*                                                
 55  * The size of the variable area depends on th    
 56  * located in different fields for various SMB    
 57  * with no variable length info, show an offse    
 58  */                                               
 59 static const bool has_smb2_data_area[NUMBER_OF    
 60         /* SMB2_NEGOTIATE */ true,                
 61         /* SMB2_SESSION_SETUP */ true,            
 62         /* SMB2_LOGOFF */ false,                  
 63         /* SMB2_TREE_CONNECT */ true,             
 64         /* SMB2_TREE_DISCONNECT */ false,         
 65         /* SMB2_CREATE */ true,                   
 66         /* SMB2_CLOSE */ false,                   
 67         /* SMB2_FLUSH */ false,                   
 68         /* SMB2_READ */ true,                     
 69         /* SMB2_WRITE */ true,                    
 70         /* SMB2_LOCK */ true,                     
 71         /* SMB2_IOCTL */ true,                    
 72         /* SMB2_CANCEL */ false, /* BB CHECK t    
 73         /* SMB2_ECHO */ false,                    
 74         /* SMB2_QUERY_DIRECTORY */ true,          
 75         /* SMB2_CHANGE_NOTIFY */ false,           
 76         /* SMB2_QUERY_INFO */ true,               
 77         /* SMB2_SET_INFO */ true,                 
 78         /* SMB2_OPLOCK_BREAK */ false             
 79 };                                                
 80                                                   
 81 /*                                                
 82  * Set length of the data area and the offset     
 83  * if they are invalid, return error.             
 84  */                                               
 85 static int smb2_get_data_area_len(unsigned int    
 86                                   struct smb2_    
 87 {                                                 
 88         int ret = 0;                              
 89                                                   
 90         *off = 0;                                 
 91         *len = 0;                                 
 92                                                   
 93         /*                                        
 94          * Following commands have data areas     
 95          * of the data buffer offset and data     
 96          * command.                               
 97          */                                       
 98         switch (hdr->Command) {                   
 99         case SMB2_SESSION_SETUP:                  
100                 *off = le16_to_cpu(((struct sm    
101                 *len = le16_to_cpu(((struct sm    
102                 break;                            
103         case SMB2_TREE_CONNECT:                   
104                 *off = max_t(unsigned short in    
105                              le16_to_cpu(((str    
106                              offsetof(struct s    
107                 *len = le16_to_cpu(((struct sm    
108                 break;                            
109         case SMB2_CREATE:                         
110         {                                         
111                 unsigned short int name_off =     
112                         max_t(unsigned short i    
113                               le16_to_cpu(((st    
114                               offsetof(struct     
115                 unsigned short int name_len =     
116                         le16_to_cpu(((struct s    
117                                                   
118                 if (((struct smb2_create_req *    
119                         *off = le32_to_cpu(((s    
120                                 hdr)->CreateCo    
121                         *len = le32_to_cpu(((s    
122                                 hdr)->CreateCo    
123                         if (!name_len)            
124                                 break;            
125                                                   
126                         if (name_off + name_le    
127                                 break;            
128                 }                                 
129                                                   
130                 *off = name_off;                  
131                 *len = name_len;                  
132                 break;                            
133         }                                         
134         case SMB2_QUERY_INFO:                     
135                 *off = max_t(unsigned int,        
136                              le16_to_cpu(((str    
137                              offsetof(struct s    
138                 *len = le32_to_cpu(((struct sm    
139                 break;                            
140         case SMB2_SET_INFO:                       
141                 *off = max_t(unsigned int,        
142                              le16_to_cpu(((str    
143                              offsetof(struct s    
144                 *len = le32_to_cpu(((struct sm    
145                 break;                            
146         case SMB2_READ:                           
147                 *off = le16_to_cpu(((struct sm    
148                 *len = le16_to_cpu(((struct sm    
149                 break;                            
150         case SMB2_WRITE:                          
151                 if (((struct smb2_write_req *)    
152                     ((struct smb2_write_req *)    
153                         *off = max_t(unsigned     
154                                      le16_to_c    
155                                      offsetof(    
156                         *len = le32_to_cpu(((s    
157                         break;                    
158                 }                                 
159                                                   
160                 *off = le16_to_cpu(((struct sm    
161                 *len = le16_to_cpu(((struct sm    
162                 break;                            
163         case SMB2_QUERY_DIRECTORY:                
164                 *off = max_t(unsigned short in    
165                              le16_to_cpu(((str    
166                              offsetof(struct s    
167                 *len = le16_to_cpu(((struct sm    
168                 break;                            
169         case SMB2_LOCK:                           
170         {                                         
171                 unsigned short lock_count;        
172                                                   
173                 lock_count = le16_to_cpu(((str    
174                 if (lock_count > 0) {             
175                         *off = offsetof(struct    
176                         *len = sizeof(struct s    
177                 }                                 
178                 break;                            
179         }                                         
180         case SMB2_IOCTL:                          
181                 *off = max_t(unsigned int,        
182                              le32_to_cpu(((str    
183                              offsetof(struct s    
184                 *len = le32_to_cpu(((struct sm    
185                 break;                            
186         default:                                  
187                 ksmbd_debug(SMB, "no length ch    
188                 break;                            
189         }                                         
190                                                   
191         if (*off > 4096) {                        
192                 ksmbd_debug(SMB, "offset %d to    
193                 ret = -EINVAL;                    
194         } else if ((u64)*off + *len > MAX_STRE    
195                 ksmbd_debug(SMB, "Request is l    
196                             MAX_STREAM_PROT_LE    
197                 ret = -EINVAL;                    
198         }                                         
199                                                   
200         return ret;                               
201 }                                                 
202                                                   
203 /*                                                
204  * Calculate the size of the SMB message based    
205  * portion, the number of word parameters and     
206  */                                               
207 static int smb2_calc_size(void *buf, unsigned     
208 {                                                 
209         struct smb2_pdu *pdu = (struct smb2_pd    
210         struct smb2_hdr *hdr = &pdu->hdr;         
211         unsigned int offset; /* the offset fro    
212         unsigned int data_length; /* the lengt    
213         int ret;                                  
214                                                   
215         /* Structure Size has already been che    
216         *len = le16_to_cpu(hdr->StructureSize)    
217                                                   
218         /*                                        
219          * StructureSize2, ie length of fixed     
220          * been checked to make sure it is the    
221          */                                       
222         *len += le16_to_cpu(pdu->StructureSize    
223         /*                                        
224          * StructureSize2 of smb2_lock pdu is     
225          * the size of smb2 lock request with     
226          * regardless of number of locks. Subt    
227          * smb2_lock_element for correct buffe    
228          */                                       
229         if (hdr->Command == SMB2_LOCK)            
230                 *len -= sizeof(struct smb2_loc    
231                                                   
232         if (has_smb2_data_area[le16_to_cpu(hdr    
233                 goto calc_size_exit;              
234                                                   
235         ret = smb2_get_data_area_len(&offset,     
236         if (ret)                                  
237                 return ret;                       
238         ksmbd_debug(SMB, "SMB2 data length %u     
239                     offset);                      
240                                                   
241         if (data_length > 0) {                    
242                 /*                                
243                  * Check to make sure that dat    
244                  * Note that last byte of the     
245                  * for some commands, typicall    
246                  * so we must add one to the c    
247                  */                               
248                 if (offset + 1 < *len) {          
249                         ksmbd_debug(SMB,          
250                                     "data area    
251                                     offset + 1    
252                         return -EINVAL;           
253                 }                                 
254                                                   
255                 *len = offset + data_length;      
256         }                                         
257                                                   
258 calc_size_exit:                                   
259         ksmbd_debug(SMB, "SMB2 len %u\n", *len    
260         return 0;                                 
261 }                                                 
262                                                   
263 static inline int smb2_query_info_req_len(stru    
264 {                                                 
265         return le32_to_cpu(h->InputBufferLengt    
266                 le32_to_cpu(h->OutputBufferLen    
267 }                                                 
268                                                   
269 static inline int smb2_set_info_req_len(struct    
270 {                                                 
271         return le32_to_cpu(h->BufferLength);      
272 }                                                 
273                                                   
274 static inline int smb2_read_req_len(struct smb    
275 {                                                 
276         return le32_to_cpu(h->Length);            
277 }                                                 
278                                                   
279 static inline int smb2_write_req_len(struct sm    
280 {                                                 
281         return le32_to_cpu(h->Length);            
282 }                                                 
283                                                   
284 static inline int smb2_query_dir_req_len(struc    
285 {                                                 
286         return le32_to_cpu(h->OutputBufferLeng    
287 }                                                 
288                                                   
289 static inline int smb2_ioctl_req_len(struct sm    
290 {                                                 
291         return le32_to_cpu(h->InputCount) +       
292                 le32_to_cpu(h->OutputCount);      
293 }                                                 
294                                                   
295 static inline int smb2_ioctl_resp_len(struct s    
296 {                                                 
297         return le32_to_cpu(h->MaxInputResponse    
298                 le32_to_cpu(h->MaxOutputRespon    
299 }                                                 
300                                                   
301 static int smb2_validate_credit_charge(struct     
302                                        struct     
303 {                                                 
304         unsigned int req_len = 0, expect_resp_    
305         unsigned short credit_charge = le16_to    
306         void *__hdr = hdr;                        
307         int ret = 0;                              
308                                                   
309         switch (hdr->Command) {                   
310         case SMB2_QUERY_INFO:                     
311                 req_len = smb2_query_info_req_    
312                 break;                            
313         case SMB2_SET_INFO:                       
314                 req_len = smb2_set_info_req_le    
315                 break;                            
316         case SMB2_READ:                           
317                 req_len = smb2_read_req_len(__    
318                 break;                            
319         case SMB2_WRITE:                          
320                 req_len = smb2_write_req_len(_    
321                 break;                            
322         case SMB2_QUERY_DIRECTORY:                
323                 req_len = smb2_query_dir_req_l    
324                 break;                            
325         case SMB2_IOCTL:                          
326                 req_len = smb2_ioctl_req_len(_    
327                 expect_resp_len = smb2_ioctl_r    
328                 break;                            
329         case SMB2_CANCEL:                         
330                 return 0;                         
331         default:                                  
332                 req_len = 1;                      
333                 break;                            
334         }                                         
335                                                   
336         credit_charge = max_t(unsigned short,     
337         max_len = max_t(unsigned int, req_len,    
338         calc_credit_num = DIV_ROUND_UP(max_len    
339                                                   
340         if (credit_charge < calc_credit_num) {    
341                 ksmbd_debug(SMB, "Insufficient    
342                             credit_charge, cal    
343                 return 1;                         
344         } else if (credit_charge > conn->vals-    
345                 ksmbd_debug(SMB, "Too large cr    
346                 return 1;                         
347         }                                         
348                                                   
349         spin_lock(&conn->credits_lock);           
350         if (credit_charge > conn->total_credit    
351                 ksmbd_debug(SMB, "Insufficient    
352                             credit_charge, con    
353                 ret = 1;                          
354         }                                         
355                                                   
356         if ((u64)conn->outstanding_credits + c    
357                 ksmbd_debug(SMB, "Limits excee    
358                             credit_charge, con    
359                 ret = 1;                          
360         } else                                    
361                 conn->outstanding_credits += c    
362                                                   
363         spin_unlock(&conn->credits_lock);         
364                                                   
365         return ret;                               
366 }                                                 
367                                                   
368 int ksmbd_smb2_check_message(struct ksmbd_work    
369 {                                                 
370         struct smb2_pdu *pdu = ksmbd_req_buf_n    
371         struct smb2_hdr *hdr = &pdu->hdr;         
372         int command;                              
373         __u32 clc_len;  /* calculated length *    
374         __u32 len = get_rfc1002_len(work->requ    
375         __u32 req_struct_size, next_cmd = le32    
376                                                   
377         if ((u64)work->next_smb2_rcv_hdr_off +    
378                 pr_err("next command(%u) offse    
379                                 next_cmd);        
380                 return 1;                         
381         }                                         
382                                                   
383         if (next_cmd > 0)                         
384                 len = next_cmd;                   
385         else if (work->next_smb2_rcv_hdr_off)     
386                 len -= work->next_smb2_rcv_hdr    
387                                                   
388         if (check_smb2_hdr(hdr))                  
389                 return 1;                         
390                                                   
391         if (hdr->StructureSize != SMB2_HEADER_    
392                 ksmbd_debug(SMB, "Illegal stru    
393                             le16_to_cpu(hdr->S    
394                 return 1;                         
395         }                                         
396                                                   
397         command = le16_to_cpu(hdr->Command);      
398         if (command >= NUMBER_OF_SMB2_COMMANDS    
399                 ksmbd_debug(SMB, "Illegal SMB2    
400                 return 1;                         
401         }                                         
402                                                   
403         if (smb2_req_struct_sizes[command] !=     
404                 if (!(command == SMB2_OPLOCK_B    
405                     (le16_to_cpu(pdu->Structur    
406                     le16_to_cpu(pdu->Structure    
407                         /* special case for SM    
408                         ksmbd_debug(SMB,          
409                                 "Illegal reque    
410                                 le16_to_cpu(pd    
411                         return 1;                 
412                 }                                 
413         }                                         
414                                                   
415         req_struct_size = le16_to_cpu(pdu->Str    
416                 __SMB2_HEADER_STRUCTURE_SIZE;     
417         if (command == SMB2_LOCK_HE)              
418                 req_struct_size -= sizeof(stru    
419                                                   
420         if (req_struct_size > len + 1)            
421                 return 1;                         
422                                                   
423         if (smb2_calc_size(hdr, &clc_len))        
424                 return 1;                         
425                                                   
426         if (len != clc_len) {                     
427                 /* client can return one byte     
428                 if (clc_len == len + 1)           
429                         goto validate_credit;     
430                                                   
431                 /*                                
432                  * Some windows servers (win20    
433                  * PDU in a compound to 8 byte    
434                  */                               
435                 if (ALIGN(clc_len, 8) == len)     
436                         goto validate_credit;     
437                                                   
438                 /*                                
439                  * SMB2 NEGOTIATE request will    
440                  * handling proceeds.             
441                  */                               
442                 if (command == SMB2_NEGOTIATE_    
443                         goto validate_credit;     
444                                                   
445                 /*                                
446                  * Allow a message that padded    
447                  * Linux 4.19.217 with smb 3.0    
448                  * sending messages where the     
449                  * 8 bytes less than len.         
450                  */                               
451                 if (clc_len < len && (len - cl    
452                         goto validate_credit;     
453                                                   
454                 pr_err_ratelimited(               
455                             "cli req too short    
456                             len, clc_len, comm    
457                             le64_to_cpu(hdr->M    
458                                                   
459                 return 1;                         
460         }                                         
461                                                   
462 validate_credit:                                  
463         if ((work->conn->vals->capabilities &     
464             smb2_validate_credit_charge(work->    
465                 return 1;                         
466                                                   
467         return 0;                                 
468 }                                                 
469                                                   
470 int smb2_negotiate_request(struct ksmbd_work *    
471 {                                                 
472         return ksmbd_smb_negotiate_common(work    
473 }                                                 
474                                                   

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php