net: Convert to use the fallthrough macro
[platform/kernel/linux-rpi.git] / net / socket.c
index 49a6daf..f4d5998 100644 (file)
@@ -500,7 +500,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
        if (f.file) {
                sock = sock_from_file(f.file, err);
                if (likely(sock)) {
-                       *fput_needed = f.flags;
+                       *fput_needed = f.flags & FDPUT_FPUT;
                        return sock;
                }
                fdput(f);
@@ -1325,7 +1325,7 @@ int sock_wake_async(struct socket_wq *wq, int how, int band)
        case SOCK_WAKE_SPACE:
                if (!test_and_clear_bit(SOCKWQ_ASYNC_NOSPACE, &wq->flags))
                        break;
-               /* fall through */
+               fallthrough;
        case SOCK_WAKE_IO:
 call_kill:
                kill_fasync(&wq->fasync_list, SIGIO, band);
@@ -1804,8 +1804,7 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
                ret = __sys_accept4_file(f.file, 0, upeer_sockaddr,
                                                upeer_addrlen, flags,
                                                rlimit(RLIMIT_NOFILE));
-               if (f.flags)
-                       fput(f.file);
+               fdput(f);
        }
 
        return ret;
@@ -1868,8 +1867,7 @@ int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
                ret = move_addr_to_kernel(uservaddr, addrlen, &address);
                if (!ret)
                        ret = __sys_connect_file(f.file, &address, addrlen, 0);
-               if (f.flags)
-                       fput(f.file);
+               fdput(f);
        }
 
        return ret;
@@ -2094,11 +2092,10 @@ static bool sock_use_custom_sol_socket(const struct socket *sock)
  *     Set a socket option. Because we don't know the option lengths we have
  *     to pass the user mode parameter for the protocols to sort out.
  */
-
-static int __sys_setsockopt(int fd, int level, int optname,
-                           char __user *optval, int optlen)
+int __sys_setsockopt(int fd, int level, int optname, char __user *user_optval,
+               int optlen)
 {
-       mm_segment_t oldfs = get_fs();
+       sockptr_t optval;
        char *kernel_optval = NULL;
        int err, fput_needed;
        struct socket *sock;
@@ -2106,6 +2103,10 @@ static int __sys_setsockopt(int fd, int level, int optname,
        if (optlen < 0)
                return -EINVAL;
 
+       err = init_user_sockptr(&optval, user_optval, optlen);
+       if (err)
+               return err;
+
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                return err;
@@ -2114,8 +2115,10 @@ static int __sys_setsockopt(int fd, int level, int optname,
        if (err)
                goto out_put;
 
-       err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
-                                            optval, &optlen, &kernel_optval);
+       if (!in_compat_syscall())
+               err = BPF_CGROUP_RUN_PROG_SETSOCKOPT(sock->sk, &level, &optname,
+                                                    user_optval, &optlen,
+                                                    &kernel_optval);
        if (err < 0)
                goto out_put;
        if (err > 0) {
@@ -2123,22 +2126,16 @@ static int __sys_setsockopt(int fd, int level, int optname,
                goto out_put;
        }
 
-       if (kernel_optval) {
-               set_fs(KERNEL_DS);
-               optval = (char __user __force *)kernel_optval;
-       }
-
+       if (kernel_optval)
+               optval = KERNEL_SOCKPTR(kernel_optval);
        if (level == SOL_SOCKET && !sock_use_custom_sol_socket(sock))
                err = sock_setsockopt(sock, level, optname, optval, optlen);
+       else if (unlikely(!sock->ops->setsockopt))
+               err = -EOPNOTSUPP;
        else
                err = sock->ops->setsockopt(sock, level, optname, optval,
                                            optlen);
-
-       if (kernel_optval) {
-               set_fs(oldfs);
-               kfree(kernel_optval);
-       }
-
+       kfree(kernel_optval);
 out_put:
        fput_light(sock->file, fput_needed);
        return err;
@@ -2154,37 +2151,38 @@ SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
  *     Get a socket option. Because we don't know the option lengths we have
  *     to pass a user mode parameter for the protocols to sort out.
  */
-
-static int __sys_getsockopt(int fd, int level, int optname,
-                           char __user *optval, int __user *optlen)
+int __sys_getsockopt(int fd, int level, int optname, char __user *optval,
+               int __user *optlen)
 {
        int err, fput_needed;
        struct socket *sock;
        int max_optlen;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
-       if (sock != NULL) {
-               err = security_socket_getsockopt(sock, level, optname);
-               if (err)
-                       goto out_put;
+       if (!sock)
+               return err;
+
+       err = security_socket_getsockopt(sock, level, optname);
+       if (err)
+               goto out_put;
 
+       if (!in_compat_syscall())
                max_optlen = BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN(optlen);
 
-               if (level == SOL_SOCKET)
-                       err =
-                           sock_getsockopt(sock, level, optname, optval,
+       if (level == SOL_SOCKET)
+               err = sock_getsockopt(sock, level, optname, optval, optlen);
+       else if (unlikely(!sock->ops->getsockopt))
+               err = -EOPNOTSUPP;
+       else
+               err = sock->ops->getsockopt(sock, level, optname, optval,
                                            optlen);
-               else
-                       err =
-                           sock->ops->getsockopt(sock, level, optname, optval,
-                                                 optlen);
 
+       if (!in_compat_syscall())
                err = BPF_CGROUP_RUN_PROG_GETSOCKOPT(sock->sk, level, optname,
-                                                    optval, optlen,
-                                                    max_optlen, err);
+                                                    optval, optlen, max_optlen,
+                                                    err);
 out_put:
-               fput_light(sock->file, fput_needed);
-       }
+       fput_light(sock->file, fput_needed);
        return err;
 }
 
@@ -3065,7 +3063,7 @@ static int __init sock_init(void)
 
        err = register_filesystem(&sock_fs_type);
        if (err)
-               goto out_fs;
+               goto out;
        sock_mnt = kern_mount(&sock_fs_type);
        if (IS_ERR(sock_mnt)) {
                err = PTR_ERR(sock_mnt);
@@ -3088,7 +3086,6 @@ out:
 
 out_mount:
        unregister_filesystem(&sock_fs_type);
-out_fs:
        goto out;
 }
 
@@ -3161,13 +3158,13 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32)
                if (rule_cnt > KMALLOC_MAX_SIZE / sizeof(u32))
                        return -ENOMEM;
                buf_size += rule_cnt * sizeof(u32);
-               /* fall through */
+               fallthrough;
        case ETHTOOL_GRXRINGS:
        case ETHTOOL_GRXCLSRLCNT:
        case ETHTOOL_GRXCLSRULE:
        case ETHTOOL_SRXCLSRLINS:
                convert_out = true;
-               /* fall through */
+               fallthrough;
        case ETHTOOL_SRXCLSRLDEL:
                buf_size += sizeof(struct ethtool_rxnfc);
                convert_in = true;