mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	There is a regular need in the kernel to provide a way to declare having
a dynamically sized set of trailing elements in a structure. Kernel code
should always use “flexible array members”[1] for these cases. The older
style of one-element or zero-length arrays should no longer be used[2].
Use an anonymous union with a couple of anonymous structs in order to
keep userspace unchanged and refactor the related code accordingly:
$ pahole -C group_filter net/ipv4/ip_sockglue.o
struct group_filter {
	union {
		struct {
			__u32      gf_interface_aux;     /*     0     4 */
			/* XXX 4 bytes hole, try to pack */
			struct __kernel_sockaddr_storage gf_group_aux; /*     8   128 */
			/* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
			__u32      gf_fmode_aux;         /*   136     4 */
			__u32      gf_numsrc_aux;        /*   140     4 */
			struct __kernel_sockaddr_storage gf_slist[1]; /*   144   128 */
		};                                       /*     0   272 */
		struct {
			__u32      gf_interface;         /*     0     4 */
			/* XXX 4 bytes hole, try to pack */
			struct __kernel_sockaddr_storage gf_group; /*     8   128 */
			/* --- cacheline 2 boundary (128 bytes) was 8 bytes ago --- */
			__u32      gf_fmode;             /*   136     4 */
			__u32      gf_numsrc;            /*   140     4 */
			struct __kernel_sockaddr_storage gf_slist_flex[0]; /*   144     0 */
		};                                       /*     0   144 */
	};                                               /*     0   272 */
	/* size: 272, cachelines: 5, members: 1 */
	/* last cacheline: 16 bytes */
};
$ pahole -C compat_group_filter net/ipv4/ip_sockglue.o
struct compat_group_filter {
	union {
		struct {
			__u32      gf_interface_aux;     /*     0     4 */
			struct __kernel_sockaddr_storage gf_group_aux __attribute__((__aligned__(4))); /*     4   128 */
			/* --- cacheline 2 boundary (128 bytes) was 4 bytes ago --- */
			__u32      gf_fmode_aux;         /*   132     4 */
			__u32      gf_numsrc_aux;        /*   136     4 */
			struct __kernel_sockaddr_storage gf_slist[1] __attribute__((__aligned__(4))); /*   140   128 */
		} __attribute__((__packed__)) __attribute__((__aligned__(4)));                     /*     0   268 */
		struct {
			__u32      gf_interface;         /*     0     4 */
			struct __kernel_sockaddr_storage gf_group __attribute__((__aligned__(4))); /*     4   128 */
			/* --- cacheline 2 boundary (128 bytes) was 4 bytes ago --- */
			__u32      gf_fmode;             /*   132     4 */
			__u32      gf_numsrc;            /*   136     4 */
			struct __kernel_sockaddr_storage gf_slist_flex[0] __attribute__((__aligned__(4))); /*   140     0 */
		} __attribute__((__packed__)) __attribute__((__aligned__(4)));                     /*     0   140 */
	} __attribute__((__aligned__(1)));               /*     0   268 */
	/* size: 268, cachelines: 5, members: 1 */
	/* forced alignments: 1 */
	/* last cacheline: 12 bytes */
} __attribute__((__packed__));
This helps with the ongoing efforts to globally enable -Warray-bounds
and get us closer to being able to tighten the FORTIFY_SOURCE routines
on memcpy().
[1] https://en.wikipedia.org/wiki/Flexible_array_member
[2] https://www.kernel.org/doc/html/v5.10/process/deprecated.html#zero-length-and-one-element-arrays
Link: https://github.com/KSPP/linux/issues/79
Link: https://github.com/KSPP/linux/issues/109
Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
		
	
			
		
			
				
	
	
		
			96 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0 */
 | 
						|
#ifndef NET_COMPAT_H
 | 
						|
#define NET_COMPAT_H
 | 
						|
 | 
						|
 | 
						|
struct sock;
 | 
						|
 | 
						|
#include <linux/compat.h>
 | 
						|
 | 
						|
struct compat_msghdr {
 | 
						|
	compat_uptr_t	msg_name;	/* void * */
 | 
						|
	compat_int_t	msg_namelen;
 | 
						|
	compat_uptr_t	msg_iov;	/* struct compat_iovec * */
 | 
						|
	compat_size_t	msg_iovlen;
 | 
						|
	compat_uptr_t	msg_control;	/* void * */
 | 
						|
	compat_size_t	msg_controllen;
 | 
						|
	compat_uint_t	msg_flags;
 | 
						|
};
 | 
						|
 | 
						|
struct compat_mmsghdr {
 | 
						|
	struct compat_msghdr msg_hdr;
 | 
						|
	compat_uint_t        msg_len;
 | 
						|
};
 | 
						|
 | 
						|
struct compat_cmsghdr {
 | 
						|
	compat_size_t	cmsg_len;
 | 
						|
	compat_int_t	cmsg_level;
 | 
						|
	compat_int_t	cmsg_type;
 | 
						|
};
 | 
						|
 | 
						|
struct compat_rtentry {
 | 
						|
	u32		rt_pad1;
 | 
						|
	struct sockaddr rt_dst;         /* target address               */
 | 
						|
	struct sockaddr rt_gateway;     /* gateway addr (RTF_GATEWAY)   */
 | 
						|
	struct sockaddr rt_genmask;     /* target network mask (IP)     */
 | 
						|
	unsigned short	rt_flags;
 | 
						|
	short		rt_pad2;
 | 
						|
	u32		rt_pad3;
 | 
						|
	unsigned char	rt_tos;
 | 
						|
	unsigned char	rt_class;
 | 
						|
	short		rt_pad4;
 | 
						|
	short		rt_metric;      /* +1 for binary compatibility! */
 | 
						|
	compat_uptr_t	rt_dev;         /* forcing the device at add    */
 | 
						|
	u32		rt_mtu;         /* per route MTU/Window         */
 | 
						|
	u32		rt_window;      /* Window clamping              */
 | 
						|
	unsigned short  rt_irtt;        /* Initial RTT                  */
 | 
						|
};
 | 
						|
 | 
						|
int __get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg,
 | 
						|
			struct sockaddr __user **save_addr, compat_uptr_t *ptr,
 | 
						|
			compat_size_t *len);
 | 
						|
int get_compat_msghdr(struct msghdr *, struct compat_msghdr __user *,
 | 
						|
		      struct sockaddr __user **, struct iovec **);
 | 
						|
int put_cmsg_compat(struct msghdr*, int, int, int, void *);
 | 
						|
 | 
						|
int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *,
 | 
						|
				     unsigned char *, int);
 | 
						|
 | 
						|
struct compat_group_req {
 | 
						|
	__u32				 gr_interface;
 | 
						|
	struct __kernel_sockaddr_storage gr_group
 | 
						|
		__aligned(4);
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct compat_group_source_req {
 | 
						|
	__u32				 gsr_interface;
 | 
						|
	struct __kernel_sockaddr_storage gsr_group
 | 
						|
		__aligned(4);
 | 
						|
	struct __kernel_sockaddr_storage gsr_source
 | 
						|
		__aligned(4);
 | 
						|
} __packed;
 | 
						|
 | 
						|
struct compat_group_filter {
 | 
						|
	union {
 | 
						|
		struct {
 | 
						|
			__u32				 gf_interface_aux;
 | 
						|
			struct __kernel_sockaddr_storage gf_group_aux
 | 
						|
				__aligned(4);
 | 
						|
			__u32				 gf_fmode_aux;
 | 
						|
			__u32				 gf_numsrc_aux;
 | 
						|
			struct __kernel_sockaddr_storage gf_slist[1]
 | 
						|
				__aligned(4);
 | 
						|
		} __packed;
 | 
						|
		struct {
 | 
						|
			__u32				 gf_interface;
 | 
						|
			struct __kernel_sockaddr_storage gf_group
 | 
						|
				__aligned(4);
 | 
						|
			__u32				 gf_fmode;
 | 
						|
			__u32				 gf_numsrc;
 | 
						|
			struct __kernel_sockaddr_storage gf_slist_flex[]
 | 
						|
				__aligned(4);
 | 
						|
		} __packed;
 | 
						|
	};
 | 
						|
} __packed;
 | 
						|
 | 
						|
#endif /* NET_COMPAT_H */
 |