smb: client, common: fix fortify warnings

When compiling with gcc version 14.0.0 20231126 (experimental)
and CONFIG_FORTIFY_SOURCE=y, I've noticed the following:

In file included from ./include/linux/string.h:295,
from ./include/linux/bitmap.h:12,
from ./include/linux/cpumask.h:12,
from ./arch/x86/include/asm/paravirt.h:17,
from ./arch/x86/include/asm/cpuid.h:62,
from ./arch/x86/include/asm/processor.h:19,
from ./arch/x86/include/asm/cpufeature.h:5,
from ./arch/x86/include/asm/thread_info.h:53,
from ./include/linux/thread_info.h:60,
from ./arch/x86/include/asm/preempt.h:9,
from ./include/linux/preempt.h:79,
from ./include/linux/spinlock.h:56,
from ./include/linux/wait.h:9,
from ./include/linux/wait_bit.h:8,
from ./include/linux/fs.h:6,
from fs/smb/client/smb2pdu.c:18:
In function 'fortify_memcpy_chk',
inlined from '__SMB2_close' at fs/smb/client/smb2pdu.c:3480:4:
./include/linux/fortify-string.h:588:25: warning: call to '__read_overflow2_field'
declared with attribute warning: detected read beyond size of field (2nd parameter);
maybe use struct_group()? [-Wattribute-warning]
588 | __read_overflow2_field(q_size_field, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

and:

In file included from ./include/linux/string.h:295,
from ./include/linux/bitmap.h:12,
from ./include/linux/cpumask.h:12,
from ./arch/x86/include/asm/paravirt.h:17,
from ./arch/x86/include/asm/cpuid.h:62,
from ./arch/x86/include/asm/processor.h:19,
from ./arch/x86/include/asm/cpufeature.h:5,
from ./arch/x86/include/asm/thread_info.h:53,
from ./include/linux/thread_info.h:60,
from ./arch/x86/include/asm/preempt.h:9,
from ./include/linux/preempt.h:79,
from ./include/linux/spinlock.h:56,
from ./include/linux/wait.h:9,
from ./include/linux/wait_bit.h:8,
from ./include/linux/fs.h:6,
from fs/smb/client/cifssmb.c:17:
In function 'fortify_memcpy_chk',
inlined from 'CIFS_open' at fs/smb/client/cifssmb.c:1248:3:
./include/linux/fortify-string.h:588:25: warning: call to '__read_overflow2_field'
declared with attribute warning: detected read beyond size of field (2nd parameter);
maybe use struct_group()? [-Wattribute-warning]
588 | __read_overflow2_field(q_size_field, size);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

In both cases, the fortification logic inteprets calls to 'memcpy()' as an
attempts to copy an amount of data which exceeds the size of the specified
field (i.e. more than 8 bytes from __le64 value) and thus issues an overread
warning. Both of these warnings may be silenced by using the convenient
'struct_group()' quirk.

Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>

authored by Dmitry Antipov and committed by Steve French 0015eb6e 88010155

Changed files
+40 -31
fs
+14 -10
fs/smb/client/cifspdu.h
··· 882 882 __u8 OplockLevel; 883 883 __u16 Fid; 884 884 __le32 CreateAction; 885 - __le64 CreationTime; 886 - __le64 LastAccessTime; 887 - __le64 LastWriteTime; 888 - __le64 ChangeTime; 889 - __le32 FileAttributes; 885 + struct_group(common_attributes, 886 + __le64 CreationTime; 887 + __le64 LastAccessTime; 888 + __le64 LastWriteTime; 889 + __le64 ChangeTime; 890 + __le32 FileAttributes; 891 + ); 890 892 __le64 AllocationSize; 891 893 __le64 EndOfFile; 892 894 __le16 FileType; ··· 2266 2264 /* QueryFileInfo/QueryPathinfo (also for SetPath/SetFile) data buffer formats */ 2267 2265 /******************************************************************************/ 2268 2266 typedef struct { /* data block encoding of response to level 263 QPathInfo */ 2269 - __le64 CreationTime; 2270 - __le64 LastAccessTime; 2271 - __le64 LastWriteTime; 2272 - __le64 ChangeTime; 2273 - __le32 Attributes; 2267 + struct_group(common_attributes, 2268 + __le64 CreationTime; 2269 + __le64 LastAccessTime; 2270 + __le64 LastWriteTime; 2271 + __le64 ChangeTime; 2272 + __le32 Attributes; 2273 + ); 2274 2274 __u32 Pad1; 2275 2275 __le64 AllocationSize; 2276 2276 __le64 EndOfFile; /* size ie offset to first free byte in file */
+4 -2
fs/smb/client/cifssmb.c
··· 1244 1244 *oplock |= CIFS_CREATE_ACTION; 1245 1245 1246 1246 if (buf) { 1247 - /* copy from CreationTime to Attributes */ 1248 - memcpy((char *)buf, (char *)&rsp->CreationTime, 36); 1247 + /* copy commonly used attributes */ 1248 + memcpy(&buf->common_attributes, 1249 + &rsp->common_attributes, 1250 + sizeof(buf->common_attributes)); 1249 1251 /* the file_info buf is endian converted by caller */ 1250 1252 buf->AllocationSize = rsp->AllocationSize; 1251 1253 buf->EndOfFile = rsp->EndOfFile;
+3 -5
fs/smb/client/smb2pdu.c
··· 3472 3472 } else { 3473 3473 trace_smb3_close_done(xid, persistent_fid, tcon->tid, 3474 3474 ses->Suid); 3475 - /* 3476 - * Note that have to subtract 4 since struct network_open_info 3477 - * has a final 4 byte pad that close response does not have 3478 - */ 3479 3475 if (pbuf) 3480 - memcpy(pbuf, (char *)&rsp->CreationTime, sizeof(*pbuf) - 4); 3476 + memcpy(&pbuf->network_open_info, 3477 + &rsp->network_open_info, 3478 + sizeof(pbuf->network_open_info)); 3481 3479 } 3482 3480 3483 3481 atomic_dec(&tcon->num_remote_opens);
+9 -7
fs/smb/client/smb2pdu.h
··· 319 319 } __packed; 320 320 321 321 struct smb2_file_network_open_info { 322 - __le64 CreationTime; 323 - __le64 LastAccessTime; 324 - __le64 LastWriteTime; 325 - __le64 ChangeTime; 326 - __le64 AllocationSize; 327 - __le64 EndOfFile; 328 - __le32 Attributes; 322 + struct_group(network_open_info, 323 + __le64 CreationTime; 324 + __le64 LastAccessTime; 325 + __le64 LastWriteTime; 326 + __le64 ChangeTime; 327 + __le64 AllocationSize; 328 + __le64 EndOfFile; 329 + __le32 Attributes; 330 + ); 329 331 __le32 Reserved; 330 332 } __packed; /* level 34 Query also similar returned in close rsp and open rsp */ 331 333
+10 -7
fs/smb/common/smb2pdu.h
··· 702 702 __le16 StructureSize; /* 60 */ 703 703 __le16 Flags; 704 704 __le32 Reserved; 705 - __le64 CreationTime; 706 - __le64 LastAccessTime; 707 - __le64 LastWriteTime; 708 - __le64 ChangeTime; 709 - __le64 AllocationSize; /* Beginning of FILE_STANDARD_INFO equivalent */ 710 - __le64 EndOfFile; 711 - __le32 Attributes; 705 + struct_group(network_open_info, 706 + __le64 CreationTime; 707 + __le64 LastAccessTime; 708 + __le64 LastWriteTime; 709 + __le64 ChangeTime; 710 + /* Beginning of FILE_STANDARD_INFO equivalent */ 711 + __le64 AllocationSize; 712 + __le64 EndOfFile; 713 + __le32 Attributes; 714 + ); 712 715 } __packed; 713 716 714 717