]> Pileus Git - ~andy/linux/blobdiff - net/socket.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[~andy/linux] / net / socket.c
index a5471f804d994ece8c31df6be0e04d5076b6dfd0..80dc7e84b046358581f454ec87993d4195e6edc3 100644 (file)
@@ -88,6 +88,7 @@
 #include <linux/nsproxy.h>
 #include <linux/magic.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -346,7 +347,8 @@ static struct file_system_type sock_fs_type = {
  *     but we take care of internal coherence yet.
  */
 
-static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
+static int sock_alloc_file(struct socket *sock, struct file **f, int flags,
+                          const char *dname)
 {
        struct qstr name = { .name = "" };
        struct path path;
@@ -357,6 +359,13 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
        if (unlikely(fd < 0))
                return fd;
 
+       if (dname) {
+               name.name = dname;
+               name.len = strlen(name.name);
+       } else if (sock->sk) {
+               name.name = sock->sk->sk_prot_creator->name;
+               name.len = strlen(name.name);
+       }
        path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
        if (unlikely(!path.dentry)) {
                put_unused_fd(fd);
@@ -389,7 +398,7 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
 int sock_map_fd(struct socket *sock, int flags)
 {
        struct file *newfile;
-       int fd = sock_alloc_file(sock, &newfile, flags);
+       int fd = sock_alloc_file(sock, &newfile, flags, NULL);
 
        if (likely(fd >= 0))
                fd_install(fd, newfile);
@@ -455,6 +464,68 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
        return NULL;
 }
 
+#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
+#define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
+#define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
+static ssize_t sockfs_getxattr(struct dentry *dentry,
+                              const char *name, void *value, size_t size)
+{
+       const char *proto_name;
+       size_t proto_size;
+       int error;
+
+       error = -ENODATA;
+       if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
+               proto_name = dentry->d_name.name;
+               proto_size = strlen(proto_name);
+
+               if (value) {
+                       error = -ERANGE;
+                       if (proto_size + 1 > size)
+                               goto out;
+
+                       strncpy(value, proto_name, proto_size + 1);
+               }
+               error = proto_size + 1;
+       }
+
+out:
+       return error;
+}
+
+static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
+                               size_t size)
+{
+       ssize_t len;
+       ssize_t used = 0;
+
+       len = security_inode_listsecurity(dentry->d_inode, buffer, size);
+       if (len < 0)
+               return len;
+       used += len;
+       if (buffer) {
+               if (size < used)
+                       return -ERANGE;
+               buffer += len;
+       }
+
+       len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
+       used += len;
+       if (buffer) {
+               if (size < used)
+                       return -ERANGE;
+               memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
+               buffer += len;
+       }
+
+       return used;
+}
+
+static const struct inode_operations sockfs_inode_ops = {
+       .getxattr = sockfs_getxattr,
+       .listxattr = sockfs_listxattr,
+};
+
 /**
  *     sock_alloc      -       allocate a socket
  *
@@ -479,6 +550,7 @@ static struct socket *sock_alloc(void)
        inode->i_mode = S_IFSOCK | S_IRWXUGO;
        inode->i_uid = current_fsuid();
        inode->i_gid = current_fsgid();
+       inode->i_op = &sockfs_inode_ops;
 
        this_cpu_add(sockets_in_use, 1);
        return sock;
@@ -1394,13 +1466,13 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
        if (err < 0)
                goto out_release_both;
 
-       fd1 = sock_alloc_file(sock1, &newfile1, flags);
+       fd1 = sock_alloc_file(sock1, &newfile1, flags, NULL);
        if (unlikely(fd1 < 0)) {
                err = fd1;
                goto out_release_both;
        }
 
-       fd2 = sock_alloc_file(sock2, &newfile2, flags);
+       fd2 = sock_alloc_file(sock2, &newfile2, flags, NULL);
        if (unlikely(fd2 < 0)) {
                err = fd2;
                fput(newfile1);
@@ -1536,7 +1608,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
         */
        __module_get(newsock->ops->owner);
 
-       newfd = sock_alloc_file(newsock, &newfile, flags);
+       newfd = sock_alloc_file(newsock, &newfile, flags,
+                               sock->sk->sk_prot_creator->name);
        if (unlikely(newfd < 0)) {
                err = newfd;
                sock_release(newsock);
@@ -2527,12 +2600,6 @@ static int __init sock_init(void)
        if (err)
                goto out;
 
-       /*
-        *      Initialize sock SLAB cache.
-        */
-
-       sk_init();
-
        /*
         *      Initialize skbuff SLAB cache
         */
@@ -2604,7 +2671,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
        set_fs(old_fs);
        if (!err)
-               err = compat_put_timeval(up, &ktv);
+               err = compat_put_timeval(&ktv, up);
 
        return err;
 }
@@ -2620,7 +2687,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
        set_fs(old_fs);
        if (!err)
-               err = compat_put_timespec(up, &kts);
+               err = compat_put_timespec(&kts, up);
 
        return err;
 }