]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selinux: do not report error on connect(AF_UNSPEC)
authorPaolo Abeni <pabeni@redhat.com>
Fri, 10 May 2019 17:12:33 +0000 (19:12 +0200)
committerPaul Moore <paul@paul-moore.com>
Tue, 21 May 2019 01:46:02 +0000 (21:46 -0400)
calling connect(AF_UNSPEC) on an already connected TCP socket is an
established way to disconnect() such socket. After commit 68741a8adab9
("selinux: Fix ltp test connect-syscall failure") it no longer works
and, in the above scenario connect() fails with EAFNOSUPPORT.

Fix the above explicitly early checking for AF_UNSPEC family, and
returning success in that case.

Reported-by: Tom Deseyn <tdeseyn@redhat.com>
Cc: stable@vger.kernel.org
Fixes: 68741a8adab9 ("selinux: Fix ltp test connect-syscall failure")
Suggested-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
security/selinux/hooks.c

index c61787b15f27b2b0bd0ed7d448fd6ba2d73ca07a..3ec702cf46ca6d04492e0b05ddb84cbad17542e7 100644 (file)
@@ -4637,6 +4637,14 @@ static int selinux_socket_connect_helper(struct socket *sock,
        err = sock_has_perm(sk, SOCKET__CONNECT);
        if (err)
                return err;
+       if (addrlen < offsetofend(struct sockaddr, sa_family))
+               return -EINVAL;
+
+       /* connect(AF_UNSPEC) has special handling, as it is a documented
+        * way to disconnect the socket
+        */
+       if (address->sa_family == AF_UNSPEC)
+               return 0;
 
        /*
         * If a TCP, DCCP or SCTP socket, check name_connect permission
@@ -4657,8 +4665,6 @@ static int selinux_socket_connect_helper(struct socket *sock,
                 * need to check address->sa_family as it is possible to have
                 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
                 */
-               if (addrlen < offsetofend(struct sockaddr, sa_family))
-                       return -EINVAL;
                switch (address->sa_family) {
                case AF_INET:
                        addr4 = (struct sockaddr_in *)address;