Patch "net: dev: Convert sa_data to flexible array in struct sockaddr" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    net: dev: Convert sa_data to flexible array in struct sockaddr

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     net-dev-convert-sa_data-to-flexible-array-in-struct-.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit b612f045d7213f210e1bfc3ce9ba04fb7a0812b1
Author: Kees Cook <keescook@xxxxxxxxxxxx>
Date:   Tue Oct 18 02:56:03 2022 -0700

    net: dev: Convert sa_data to flexible array in struct sockaddr
    
    [ Upstream commit b5f0de6df6dce8d641ef58ef7012f3304dffb9a1 ]
    
    One of the worst offenders of "fake flexible arrays" is struct sockaddr,
    as it is the classic example of why GCC and Clang have been traditionally
    forced to treat all trailing arrays as fake flexible arrays: in the
    distant misty past, sa_data became too small, and code started just
    treating it as a flexible array, even though it was fixed-size. The
    special case by the compiler is specifically that sizeof(sa->sa_data)
    and FORTIFY_SOURCE (which uses __builtin_object_size(sa->sa_data, 1))
    do not agree (14 and -1 respectively), which makes FORTIFY_SOURCE treat
    it as a flexible array.
    
    However, the coming -fstrict-flex-arrays compiler flag will remove
    these special cases so that FORTIFY_SOURCE can gain coverage over all
    the trailing arrays in the kernel that are _not_ supposed to be treated
    as a flexible array. To deal with this change, convert sa_data to a true
    flexible array. To keep the structure size the same, move sa_data into
    a union with a newly introduced sa_data_min with the original size. The
    result is that FORTIFY_SOURCE can continue to have no idea how large
    sa_data may actually be, but anything using sizeof(sa->sa_data) must
    switch to sizeof(sa->sa_data_min).
    
    Cc: Jens Axboe <axboe@xxxxxxxxx>
    Cc: Pavel Begunkov <asml.silence@xxxxxxxxx>
    Cc: David Ahern <dsahern@xxxxxxxxxx>
    Cc: Dylan Yudaken <dylany@xxxxxx>
    Cc: Yajun Deng <yajun.deng@xxxxxxxxx>
    Cc: Petr Machata <petrm@xxxxxxxxxx>
    Cc: Hangbin Liu <liuhangbin@xxxxxxxxx>
    Cc: Leon Romanovsky <leon@xxxxxxxxxx>
    Cc: syzbot <syzkaller@xxxxxxxxxxxxxxxx>
    Cc: Willem de Bruijn <willemb@xxxxxxxxxx>
    Cc: Pablo Neira Ayuso <pablo@xxxxxxxxxxxxx>
    Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20221018095503.never.671-kees@xxxxxxxxxx
    Signed-off-by: Jakub Kicinski <kuba@xxxxxxxxxx>
    Stable-dep-of: a7d6027790ac ("arp: Prevent overflow in arp_req_get().")
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/include/linux/socket.h b/include/linux/socket.h
index b3c58042bd254..d79efd0268809 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -33,7 +33,10 @@ typedef __kernel_sa_family_t	sa_family_t;
 
 struct sockaddr {
 	sa_family_t	sa_family;	/* address family, AF_xxx	*/
-	char		sa_data[14];	/* 14 bytes of protocol address	*/
+	union {
+		char sa_data_min[14];		/* Minimum 14 bytes of protocol address	*/
+		DECLARE_FLEX_ARRAY(char, sa_data);
+	};
 };
 
 struct linger {
diff --git a/net/core/dev.c b/net/core/dev.c
index 1ba3662faf0aa..60619fe8af5fc 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -8861,7 +8861,7 @@ EXPORT_SYMBOL(dev_set_mac_address_user);
 
 int dev_get_mac_address(struct sockaddr *sa, struct net *net, char *dev_name)
 {
-	size_t size = sizeof(sa->sa_data);
+	size_t size = sizeof(sa->sa_data_min);
 	struct net_device *dev;
 	int ret = 0;
 
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 7674bb9f3076c..5cdbfbf9a7dcf 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -342,7 +342,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, void __user *data,
 		if (ifr->ifr_hwaddr.sa_family != dev->type)
 			return -EINVAL;
 		memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
-		       min(sizeof(ifr->ifr_hwaddr.sa_data),
+		       min(sizeof(ifr->ifr_hwaddr.sa_data_min),
 			   (size_t)dev->addr_len));
 		call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
 		return 0;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 51882f07ef70c..c3117350f5fbb 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3284,7 +3284,7 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
 			    int addr_len)
 {
 	struct sock *sk = sock->sk;
-	char name[sizeof(uaddr->sa_data) + 1];
+	char name[sizeof(uaddr->sa_data_min) + 1];
 
 	/*
 	 *	Check legality
@@ -3295,8 +3295,8 @@ static int packet_bind_spkt(struct socket *sock, struct sockaddr *uaddr,
 	/* uaddr->sa_data comes from the userspace, it's not guaranteed to be
 	 * zero-terminated.
 	 */
-	memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data));
-	name[sizeof(uaddr->sa_data)] = 0;
+	memcpy(name, uaddr->sa_data, sizeof(uaddr->sa_data_min));
+	name[sizeof(uaddr->sa_data_min)] = 0;
 
 	return packet_do_bind(sk, name, 0, 0);
 }
@@ -3566,11 +3566,11 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
 		return -EOPNOTSUPP;
 
 	uaddr->sa_family = AF_PACKET;
-	memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data));
+	memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data_min));
 	rcu_read_lock();
 	dev = dev_get_by_index_rcu(sock_net(sk), READ_ONCE(pkt_sk(sk)->ifindex));
 	if (dev)
-		strscpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
+		strscpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data_min));
 	rcu_read_unlock();
 
 	return sizeof(*uaddr);




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux