Skip to content

Commit 87fbfff

Browse files
committed
broken ping to ipv6 linklocal addresses on debian buster
I am seeing ping failures to IPv6 linklocal addresses with Debian buster. Easiest example to reproduce is: $ ping -c1 -w1 ff02::1%eth1 connect: Invalid argument $ ping -c1 -w1 ff02::1%eth1 PING ff02::01%eth1(ff02::1%eth1) 56 data bytes 64 bytes from fe80::e0:f9ff:fe0c:37%eth1: icmp_seq=1 ttl=64 time=0.059 ms git bisect traced the failure to commit b9ef551 ("smack: Check address length before reading address family") Arguably ping is being stupid since the buster version is not setting the address family properly (ping on stretch for example does): $ strace -e connect ping6 -c1 -w1 ff02::1%eth1 connect(5, {sa_family=AF_UNSPEC, sa_data="\4\1\0\0\0\0\377\2\0\0\0\0\0\0\0\0\0\0\0\0\0\1\3\0\0\0"}, 28) = -1 EINVAL (Invalid argument) but the command works fine on kernels prior to this commit, so this is breakage which goes against the Linux paradigm of "don't break userspace" Cc: [email protected] Reported-by: David Ahern <[email protected]> Suggested-by: Tetsuo Handa <[email protected]> Signed-off-by: Casey Schaufler <[email protected]>  security/smack/smack_lsm.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-)
1 parent d5226fa commit 87fbfff

File tree

1 file changed

+19
-22
lines changed

1 file changed

+19
-22
lines changed

security/smack/smack_lsm.c

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2831,42 +2831,39 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
28312831
int addrlen)
28322832
{
28332833
int rc = 0;
2834-
#if IS_ENABLED(CONFIG_IPV6)
2835-
struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;
2836-
#endif
2837-
#ifdef SMACK_IPV6_SECMARK_LABELING
2838-
struct smack_known *rsp;
2839-
struct socket_smack *ssp;
2840-
#endif
28412834

28422835
if (sock->sk == NULL)
28432836
return 0;
2844-
2837+
if (sock->sk->sk_family != PF_INET &&
2838+
(!IS_ENABLED(CONFIG_IPV6) || sock->sk->sk_family != PF_INET6))
2839+
return 0;
2840+
if (addrlen < offsetofend(struct sockaddr, sa_family))
2841+
return 0;
2842+
if (IS_ENABLED(CONFIG_IPV6) && sap->sa_family == AF_INET6) {
2843+
struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap;
28452844
#ifdef SMACK_IPV6_SECMARK_LABELING
2846-
ssp = sock->sk->sk_security;
2845+
struct smack_known *rsp;
28472846
#endif
28482847

2849-
switch (sock->sk->sk_family) {
2850-
case PF_INET:
2851-
if (addrlen < sizeof(struct sockaddr_in) ||
2852-
sap->sa_family != AF_INET)
2853-
return -EINVAL;
2854-
rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
2855-
break;
2856-
case PF_INET6:
2857-
if (addrlen < SIN6_LEN_RFC2133 || sap->sa_family != AF_INET6)
2858-
return -EINVAL;
2848+
if (addrlen < SIN6_LEN_RFC2133)
2849+
return 0;
28592850
#ifdef SMACK_IPV6_SECMARK_LABELING
28602851
rsp = smack_ipv6host_label(sip);
2861-
if (rsp != NULL)
2852+
if (rsp != NULL) {
2853+
struct socket_smack *ssp = sock->sk->sk_security;
2854+
28622855
rc = smk_ipv6_check(ssp->smk_out, rsp, sip,
2863-
SMK_CONNECTING);
2856+
SMK_CONNECTING);
2857+
}
28642858
#endif
28652859
#ifdef SMACK_IPV6_PORT_LABELING
28662860
rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING);
28672861
#endif
2868-
break;
2862+
return rc;
28692863
}
2864+
if (sap->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in))
2865+
return 0;
2866+
rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
28702867
return rc;
28712868
}
28722869

0 commit comments

Comments
 (0)