Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/perex/alsa
[sfrench/cifs-2.6.git] / net / socket.c
index b09eb9036a17a3563e9ad5ca08a1734b86aa0df5..7651de0085028dc4d02b15e5844e239dd938d01e 100644 (file)
@@ -84,6 +84,7 @@
 #include <linux/kmod.h>
 #include <linux/audit.h>
 #include <linux/wireless.h>
+#include <linux/nsproxy.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -111,6 +112,9 @@ static long compat_sock_ioctl(struct file *file,
 static int sock_fasync(int fd, struct file *filp, int on);
 static ssize_t sock_sendpage(struct file *file, struct page *page,
                             int offset, size_t size, loff_t *ppos, int more);
+static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
+                               struct pipe_inode_info *pipe, size_t len,
+                               unsigned int flags);
 
 /*
  *     Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
@@ -133,6 +137,7 @@ static const struct file_operations socket_file_ops = {
        .fasync =       sock_fasync,
        .sendpage =     sock_sendpage,
        .splice_write = generic_splice_sendpage,
+       .splice_read =  sock_splice_read,
 };
 
 /*
@@ -257,7 +262,7 @@ static void sock_destroy_inode(struct inode *inode)
                        container_of(inode, struct socket_alloc, vfs_inode));
 }
 
-static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags)
+static void init_once(struct kmem_cache *cachep, void *foo)
 {
        struct socket_alloc *ei = (struct socket_alloc *)foo;
 
@@ -363,26 +368,26 @@ static int sock_alloc_fd(struct file **filep)
 
 static int sock_attach_fd(struct socket *sock, struct file *file)
 {
+       struct dentry *dentry;
        struct qstr name = { .name = "" };
 
-       file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
-       if (unlikely(!file->f_path.dentry))
+       dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name);
+       if (unlikely(!dentry))
                return -ENOMEM;
 
-       file->f_path.dentry->d_op = &sockfs_dentry_operations;
+       dentry->d_op = &sockfs_dentry_operations;
        /*
         * We dont want to push this dentry into global dentry hash table.
         * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
         * This permits a working /proc/$pid/fd/XXX on sockets
         */
-       file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
-       d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
-       file->f_path.mnt = mntget(sock_mnt);
-       file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
+       dentry->d_flags &= ~DCACHE_UNHASHED;
+       d_instantiate(dentry, SOCK_INODE(sock));
 
        sock->file = file;
-       file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
-       file->f_mode = FMODE_READ | FMODE_WRITE;
+       init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
+                 &socket_file_ops);
+       SOCK_INODE(sock)->i_fop = &socket_file_ops;
        file->f_flags = O_RDWR;
        file->f_pos = 0;
        file->private_data = sock;
@@ -690,6 +695,15 @@ static ssize_t sock_sendpage(struct file *file, struct page *page,
        return sock->ops->sendpage(sock, page, offset, size, flags);
 }
 
+static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
+                               struct pipe_inode_info *pipe, size_t len,
+                               unsigned int flags)
+{
+       struct socket *sock = file->private_data;
+
+       return sock->ops->splice_read(sock, ppos, pipe, len, flags);
+}
+
 static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
                                         struct sock_iocb *siocb)
 {
@@ -790,9 +804,9 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
  */
 
 static DEFINE_MUTEX(br_ioctl_mutex);
-static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL;
+static int (*br_ioctl_hook) (struct net *, unsigned int cmd, void __user *arg) = NULL;
 
-void brioctl_set(int (*hook) (unsigned int, void __user *))
+void brioctl_set(int (*hook) (struct net *, unsigned int, void __user *))
 {
        mutex_lock(&br_ioctl_mutex);
        br_ioctl_hook = hook;
@@ -802,9 +816,9 @@ void brioctl_set(int (*hook) (unsigned int, void __user *))
 EXPORT_SYMBOL(brioctl_set);
 
 static DEFINE_MUTEX(vlan_ioctl_mutex);
-static int (*vlan_ioctl_hook) (void __user *arg);
+static int (*vlan_ioctl_hook) (struct net *, void __user *arg);
 
-void vlan_ioctl_set(int (*hook) (void __user *))
+void vlan_ioctl_set(int (*hook) (struct net *, void __user *))
 {
        mutex_lock(&vlan_ioctl_mutex);
        vlan_ioctl_hook = hook;
@@ -833,16 +847,20 @@ EXPORT_SYMBOL(dlci_ioctl_set);
 static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 {
        struct socket *sock;
+       struct sock *sk;
        void __user *argp = (void __user *)arg;
        int pid, err;
+       struct net *net;
 
        sock = file->private_data;
+       sk = sock->sk;
+       net = sk->sk_net;
        if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
-               err = dev_ioctl(cmd, argp);
+               err = dev_ioctl(net, cmd, argp);
        } else
 #ifdef CONFIG_WIRELESS_EXT
        if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
-               err = dev_ioctl(cmd, argp);
+               err = dev_ioctl(net, cmd, argp);
        } else
 #endif                         /* CONFIG_WIRELESS_EXT */
                switch (cmd) {
@@ -868,7 +886,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 
                        mutex_lock(&br_ioctl_mutex);
                        if (br_ioctl_hook)
-                               err = br_ioctl_hook(cmd, argp);
+                               err = br_ioctl_hook(net, cmd, argp);
                        mutex_unlock(&br_ioctl_mutex);
                        break;
                case SIOCGIFVLAN:
@@ -879,7 +897,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
 
                        mutex_lock(&vlan_ioctl_mutex);
                        if (vlan_ioctl_hook)
-                               err = vlan_ioctl_hook(argp);
+                               err = vlan_ioctl_hook(net, argp);
                        mutex_unlock(&vlan_ioctl_mutex);
                        break;
                case SIOCADDDLCI:
@@ -902,7 +920,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                         * to the NIC driver.
                         */
                        if (err == -ENOIOCTLCMD)
-                               err = dev_ioctl(cmd, argp);
+                               err = dev_ioctl(net, cmd, argp);
                        break;
                }
        return err;
@@ -1052,26 +1070,25 @@ int sock_wake_async(struct socket *sock, int how, int band)
        if (!sock || !sock->fasync_list)
                return -1;
        switch (how) {
-       case 1:
-
+       case SOCK_WAKE_WAITD:
                if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
                        break;
                goto call_kill;
-       case 2:
+       case SOCK_WAKE_SPACE:
                if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
                        break;
                /* fall through */
-       case 0:
+       case SOCK_WAKE_IO:
 call_kill:
                __kill_fasync(sock->fasync_list, SIGIO, band);
                break;
-       case 3:
+       case SOCK_WAKE_URG:
                __kill_fasync(sock->fasync_list, SIGURG, band);
        }
        return 0;
 }
 
-static int __sock_create(int family, int type, int protocol,
+static int __sock_create(struct net *net, int family, int type, int protocol,
                         struct socket **res, int kern)
 {
        int err;
@@ -1147,7 +1164,7 @@ static int __sock_create(int family, int type, int protocol,
        /* Now protected by module ref count */
        rcu_read_unlock();
 
-       err = pf->create(sock, protocol);
+       err = pf->create(net, sock, protocol);
        if (err < 0)
                goto out_module_put;
 
@@ -1186,12 +1203,12 @@ out_release:
 
 int sock_create(int family, int type, int protocol, struct socket **res)
 {
-       return __sock_create(family, type, protocol, res, 0);
+       return __sock_create(current->nsproxy->net_ns, family, type, protocol, res, 0);
 }
 
 int sock_create_kern(int family, int type, int protocol, struct socket **res)
 {
-       return __sock_create(family, type, protocol, res, 1);
+       return __sock_create(&init_net, family, type, protocol, res, 1);
 }
 
 asmlinkage long sys_socket(int family, int type, int protocol)
@@ -1245,11 +1262,14 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
                goto out_release_both;
 
        fd1 = sock_alloc_fd(&newfile1);
-       if (unlikely(fd1 < 0))
+       if (unlikely(fd1 < 0)) {
+               err = fd1;
                goto out_release_both;
+       }
 
        fd2 = sock_alloc_fd(&newfile2);
        if (unlikely(fd2 < 0)) {
+               err = fd2;
                put_filp(newfile1);
                put_unused_fd(fd1);
                goto out_release_both;
@@ -1345,17 +1365,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
  *     ready for listening.
  */
 
-int sysctl_somaxconn __read_mostly = SOMAXCONN;
-
 asmlinkage long sys_listen(int fd, int backlog)
 {
        struct socket *sock;
        int err, fput_needed;
+       int somaxconn;
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock) {
-               if ((unsigned)backlog > sysctl_somaxconn)
-                       backlog = sysctl_somaxconn;
+               somaxconn = sock->sk->sk_net->sysctl_somaxconn;
+               if ((unsigned)backlog > somaxconn)
+                       backlog = somaxconn;
 
                err = security_socket_listen(sock, backlog);
                if (!err)
@@ -1573,16 +1593,11 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
        struct msghdr msg;
        struct iovec iov;
        int fput_needed;
-       struct file *sock_file;
 
-       sock_file = fget_light(fd, &fput_needed);
-       err = -EBADF;
-       if (!sock_file)
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
+       if (!sock)
                goto out;
 
-       sock = sock_from_file(sock_file, &err);
-       if (!sock)
-               goto out_put;
        iov.iov_base = buff;
        iov.iov_len = len;
        msg.msg_name = NULL;
@@ -1604,7 +1619,7 @@ asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
        err = sock_sendmsg(sock, &msg, len);
 
 out_put:
-       fput_light(sock_file, fput_needed);
+       fput_light(sock->file, fput_needed);
 out:
        return err;
 }
@@ -1633,17 +1648,11 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
        struct msghdr msg;
        char address[MAX_SOCK_ADDR];
        int err, err2;
-       struct file *sock_file;
        int fput_needed;
 
-       sock_file = fget_light(fd, &fput_needed);
-       err = -EBADF;
-       if (!sock_file)
-               goto out;
-
-       sock = sock_from_file(sock_file, &err);
+       sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (!sock)
-               goto out_put;
+               goto out;
 
        msg.msg_control = NULL;
        msg.msg_controllen = 0;
@@ -1662,8 +1671,8 @@ asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
                if (err2 < 0)
                        err = err2;
        }
-out_put:
-       fput_light(sock_file, fput_needed);
+
+       fput_light(sock->file, fput_needed);
 out:
        return err;
 }
@@ -1924,7 +1933,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
         *      kernel msghdr to use the kernel address space)
         */
 
-       uaddr = (void __user *)msg_sys.msg_name;
+       uaddr = (__force void __user *)msg_sys.msg_name;
        uaddr_len = COMPAT_NAMELEN(msg);
        if (MSG_CMSG_COMPAT & flags) {
                err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
@@ -2230,6 +2239,7 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
        err = sock->ops->accept(sock, *newsock, flags);
        if (err < 0) {
                sock_release(*newsock);
+               *newsock = NULL;
                goto done;
        }
 
@@ -2310,6 +2320,11 @@ int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
        return err;
 }
 
+int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
+{
+       return sock->ops->shutdown(sock, how);
+}
+
 /* ABI emulation layers need these two */
 EXPORT_SYMBOL(move_addr_to_kernel);
 EXPORT_SYMBOL(move_addr_to_user);
@@ -2336,3 +2351,4 @@ EXPORT_SYMBOL(kernel_getsockopt);
 EXPORT_SYMBOL(kernel_setsockopt);
 EXPORT_SYMBOL(kernel_sendpage);
 EXPORT_SYMBOL(kernel_sock_ioctl);
+EXPORT_SYMBOL(kernel_sock_shutdown);