diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 87 |
1 files changed, 76 insertions, 11 deletions
diff --git a/net/socket.c b/net/socket.c index 38a14311f3a6..d92c490e66fa 100644 --- a/net/socket.c +++ b/net/socket.c @@ -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,12 +347,19 @@ static struct file_system_type sock_fs_type = { * but we take care of internal coherence yet. */ -struct file *sock_alloc_file(struct socket *sock, int flags) +struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) { struct qstr name = { .name = "" }; struct path path; struct file *file; + 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)) return ERR_PTR(-ENOMEM); @@ -384,7 +392,7 @@ static int sock_map_fd(struct socket *sock, int flags) if (unlikely(fd < 0)) return fd; - newfile = sock_alloc_file(sock, flags); + newfile = sock_alloc_file(sock, flags, NULL); if (likely(!IS_ERR(newfile))) { fd_install(fd, newfile); return fd; @@ -451,6 +459,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 * @@ -475,6 +545,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; @@ -1402,7 +1473,7 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, goto out_release_both; } - newfile1 = sock_alloc_file(sock1, flags); + newfile1 = sock_alloc_file(sock1, flags, NULL); if (unlikely(IS_ERR(newfile1))) { err = PTR_ERR(newfile1); put_unused_fd(fd1); @@ -1410,7 +1481,7 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, goto out_release_both; } - newfile2 = sock_alloc_file(sock2, flags); + newfile2 = sock_alloc_file(sock2, flags, NULL); if (IS_ERR(newfile2)) { err = PTR_ERR(newfile2); fput(newfile1); @@ -1553,7 +1624,7 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, sock_release(newsock); goto out_put; } - newfile = sock_alloc_file(newsock, flags); + newfile = sock_alloc_file(newsock, flags, sock->sk->sk_prot_creator->name); if (unlikely(IS_ERR(newfile))) { err = PTR_ERR(newfile); put_unused_fd(newfd); @@ -2546,12 +2617,6 @@ static int __init sock_init(void) goto out; /* - * Initialize sock SLAB cache. - */ - - sk_init(); - - /* * Initialize skbuff SLAB cache */ skb_init(); |