netfilter: conntrack: include kmemleak.h for kmemleak_not_leak()
[linux-2.6-microblaze.git] / net / socket.c
index a05289b..54dcb43 100644 (file)
 #include <linux/ipv6_route.h>
 #include <linux/route.h>
 #include <linux/sockios.h>
-#include <linux/atalk.h>
 #include <net/busy_poll.h>
 #include <linux/errqueue.h>
 
@@ -234,7 +233,7 @@ static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen,
        return __put_user(klen, ulen);
 }
 
-static struct kmem_cache *sock_inode_cachep __read_mostly;
+static struct kmem_cache *sock_inode_cachep __ro_after_init;
 
 static struct inode *sock_alloc_inode(struct super_block *sb)
 {
@@ -991,10 +990,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
  *     what to do with it - that's up to the protocol still.
  */
 
-static struct ns_common *get_net_ns(struct ns_common *ns)
+struct ns_common *get_net_ns(struct ns_common *ns)
 {
        return &get_net(container_of(ns, struct net, ns))->ns;
 }
+EXPORT_SYMBOL_GPL(get_net_ns);
 
 static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
@@ -1593,8 +1593,9 @@ int __sys_accept4(int fd, struct sockaddr __user *upeer_sockaddr,
                goto out_fd;
 
        if (upeer_sockaddr) {
-               if (newsock->ops->getname(newsock, (struct sockaddr *)&address,
-                                         &len, 2) < 0) {
+               len = newsock->ops->getname(newsock,
+                                       (struct sockaddr *)&address, 2);
+               if (len < 0) {
                        err = -ECONNABORTED;
                        goto out_fd;
                }
@@ -1685,7 +1686,7 @@ int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
 {
        struct socket *sock;
        struct sockaddr_storage address;
-       int len, err, fput_needed;
+       int err, fput_needed;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
@@ -1695,10 +1696,11 @@ int __sys_getsockname(int fd, struct sockaddr __user *usockaddr,
        if (err)
                goto out_put;
 
-       err = sock->ops->getname(sock, (struct sockaddr *)&address, &len, 0);
-       if (err)
+       err = sock->ops->getname(sock, (struct sockaddr *)&address, 0);
+       if (err < 0)
                goto out_put;
-       err = move_addr_to_user(&address, len, usockaddr, usockaddr_len);
+        /* "err" is actually length in this case */
+       err = move_addr_to_user(&address, err, usockaddr, usockaddr_len);
 
 out_put:
        fput_light(sock->file, fput_needed);
@@ -1722,7 +1724,7 @@ int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
 {
        struct socket *sock;
        struct sockaddr_storage address;
-       int len, err, fput_needed;
+       int err, fput_needed;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock != NULL) {
@@ -1732,11 +1734,10 @@ int __sys_getpeername(int fd, struct sockaddr __user *usockaddr,
                        return err;
                }
 
-               err =
-                   sock->ops->getname(sock, (struct sockaddr *)&address, &len,
-                                      1);
-               if (!err)
-                       err = move_addr_to_user(&address, len, usockaddr,
+               err = sock->ops->getname(sock, (struct sockaddr *)&address, 1);
+               if (err >= 0)
+                       /* "err" is actually length in this case */
+                       err = move_addr_to_user(&address, err, usockaddr,
                                                usockaddr_len);
                fput_light(sock->file, fput_needed);
        }
@@ -2137,12 +2138,16 @@ out_freeiov:
  *     BSD sendmsg interface
  */
 
-long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
+long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
+                  bool forbid_cmsg_compat)
 {
        int fput_needed, err;
        struct msghdr msg_sys;
        struct socket *sock;
 
+       if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
+               return -EINVAL;
+
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
@@ -2156,9 +2161,7 @@ out:
 
 SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int, flags)
 {
-       if (flags & MSG_CMSG_COMPAT)
-               return -EINVAL;
-       return __sys_sendmsg(fd, msg, flags);
+       return __sys_sendmsg(fd, msg, flags, true);
 }
 
 /*
@@ -2166,7 +2169,7 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct user_msghdr __user *, msg, unsigned int
  */
 
 int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
-                  unsigned int flags)
+                  unsigned int flags, bool forbid_cmsg_compat)
 {
        int fput_needed, err, datagrams;
        struct socket *sock;
@@ -2176,6 +2179,9 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
        struct used_address used_address;
        unsigned int oflags = flags;
 
+       if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
+               return -EINVAL;
+
        if (vlen > UIO_MAXIOV)
                vlen = UIO_MAXIOV;
 
@@ -2232,9 +2238,7 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
                unsigned int, vlen, unsigned int, flags)
 {
-       if (flags & MSG_CMSG_COMPAT)
-               return -EINVAL;
-       return __sys_sendmmsg(fd, mmsg, vlen, flags);
+       return __sys_sendmmsg(fd, mmsg, vlen, flags, true);
 }
 
 static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
@@ -2307,12 +2311,16 @@ out_freeiov:
  *     BSD recvmsg interface
  */
 
-long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned flags)
+long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
+                  bool forbid_cmsg_compat)
 {
        int fput_needed, err;
        struct msghdr msg_sys;
        struct socket *sock;
 
+       if (forbid_cmsg_compat && (flags & MSG_CMSG_COMPAT))
+               return -EINVAL;
+
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
                goto out;
@@ -2327,9 +2335,7 @@ out:
 SYSCALL_DEFINE3(recvmsg, int, fd, struct user_msghdr __user *, msg,
                unsigned int, flags)
 {
-       if (flags & MSG_CMSG_COMPAT)
-               return -EINVAL;
-       return __sys_recvmsg(fd, msg, flags);
+       return __sys_recvmsg(fd, msg, flags, true);
 }
 
 /*
@@ -2358,10 +2364,12 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
        if (!sock)
                return err;
 
-       err = sock_error(sock->sk);
-       if (err) {
-               datagrams = err;
-               goto out_put;
+       if (likely(!(flags & MSG_ERRQUEUE))) {
+               err = sock_error(sock->sk);
+               if (err) {
+                       datagrams = err;
+                       goto out_put;
+               }
        }
 
        entry = mmsg;
@@ -2445,9 +2453,9 @@ out_put:
        return datagrams;
 }
 
-SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
-               unsigned int, vlen, unsigned int, flags,
-               struct timespec __user *, timeout)
+static int do_sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
+                          unsigned int vlen, unsigned int flags,
+                          struct timespec __user *timeout)
 {
        int datagrams;
        struct timespec timeout_sys;
@@ -2470,6 +2478,13 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
        return datagrams;
 }
 
+SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
+               unsigned int, vlen, unsigned int, flags,
+               struct timespec __user *, timeout)
+{
+       return do_sys_recvmmsg(fd, mmsg, vlen, flags, timeout);
+}
+
 #ifdef __ARCH_WANT_SYS_SOCKETCALL
 /* Argument list sizes for sys_socketcall */
 #define AL(x) ((x) * sizeof(unsigned long))
@@ -2546,14 +2561,16 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
                err = __sys_socketpair(a0, a1, a[2], (int __user *)a[3]);
                break;
        case SYS_SEND:
-               err = sys_send(a0, (void __user *)a1, a[2], a[3]);
+               err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
+                                  NULL, 0);
                break;
        case SYS_SENDTO:
                err = __sys_sendto(a0, (void __user *)a1, a[2], a[3],
                                   (struct sockaddr __user *)a[4], a[5]);
                break;
        case SYS_RECV:
-               err = sys_recv(a0, (void __user *)a1, a[2], a[3]);
+               err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
+                                    NULL, NULL);
                break;
        case SYS_RECVFROM:
                err = __sys_recvfrom(a0, (void __user *)a1, a[2], a[3],
@@ -2573,17 +2590,20 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
                                     (int __user *)a[4]);
                break;
        case SYS_SENDMSG:
-               err = sys_sendmsg(a0, (struct user_msghdr __user *)a1, a[2]);
+               err = __sys_sendmsg(a0, (struct user_msghdr __user *)a1,
+                                   a[2], true);
                break;
        case SYS_SENDMMSG:
-               err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
+               err = __sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2],
+                                    a[3], true);
                break;
        case SYS_RECVMSG:
-               err = sys_recvmsg(a0, (struct user_msghdr __user *)a1, a[2]);
+               err = __sys_recvmsg(a0, (struct user_msghdr __user *)a1,
+                                   a[2], true);
                break;
        case SYS_RECVMMSG:
-               err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
-                                  (struct timespec __user *)a[4]);
+               err = do_sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2],
+                                     a[3], (struct timespec __user *)a[4]);
                break;
        case SYS_ACCEPT4:
                err = __sys_accept4(a0, (struct sockaddr __user *)a1,
@@ -2658,6 +2678,11 @@ void sock_unregister(int family)
 }
 EXPORT_SYMBOL(sock_unregister);
 
+bool sock_is_registered(int family)
+{
+       return family < NPROTO && rcu_access_pointer(net_families[family]);
+}
+
 static int __init sock_init(void)
 {
        int err;
@@ -3237,17 +3262,15 @@ int kernel_connect(struct socket *sock, struct sockaddr *addr, int addrlen,
 }
 EXPORT_SYMBOL(kernel_connect);
 
-int kernel_getsockname(struct socket *sock, struct sockaddr *addr,
-                        int *addrlen)
+int kernel_getsockname(struct socket *sock, struct sockaddr *addr)
 {
-       return sock->ops->getname(sock, addr, addrlen, 0);
+       return sock->ops->getname(sock, addr, 0);
 }
 EXPORT_SYMBOL(kernel_getsockname);
 
-int kernel_getpeername(struct socket *sock, struct sockaddr *addr,
-                        int *addrlen)
+int kernel_getpeername(struct socket *sock, struct sockaddr *addr)
 {
-       return sock->ops->getname(sock, addr, addrlen, 1);
+       return sock->ops->getname(sock, addr, 1);
 }
 EXPORT_SYMBOL(kernel_getpeername);