aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/socket.c83
1 files changed, 78 insertions, 5 deletions
diff --git a/net/socket.c b/net/socket.c
index a5471f804d99..977c0f48c8d6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -88,6 +88,7 @@
88#include <linux/nsproxy.h> 88#include <linux/nsproxy.h>
89#include <linux/magic.h> 89#include <linux/magic.h>
90#include <linux/slab.h> 90#include <linux/slab.h>
91#include <linux/xattr.h>
91 92
92#include <asm/uaccess.h> 93#include <asm/uaccess.h>
93#include <asm/unistd.h> 94#include <asm/unistd.h>
@@ -346,7 +347,8 @@ static struct file_system_type sock_fs_type = {
346 * but we take care of internal coherence yet. 347 * but we take care of internal coherence yet.
347 */ 348 */
348 349
349static int sock_alloc_file(struct socket *sock, struct file **f, int flags) 350static int sock_alloc_file(struct socket *sock, struct file **f, int flags,
351 const char *dname)
350{ 352{
351 struct qstr name = { .name = "" }; 353 struct qstr name = { .name = "" };
352 struct path path; 354 struct path path;
@@ -357,6 +359,13 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
357 if (unlikely(fd < 0)) 359 if (unlikely(fd < 0))
358 return fd; 360 return fd;
359 361
362 if (dname) {
363 name.name = dname;
364 name.len = strlen(name.name);
365 } else if (sock->sk) {
366 name.name = sock->sk->sk_prot_creator->name;
367 name.len = strlen(name.name);
368 }
360 path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); 369 path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name);
361 if (unlikely(!path.dentry)) { 370 if (unlikely(!path.dentry)) {
362 put_unused_fd(fd); 371 put_unused_fd(fd);
@@ -389,7 +398,7 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags)
389int sock_map_fd(struct socket *sock, int flags) 398int sock_map_fd(struct socket *sock, int flags)
390{ 399{
391 struct file *newfile; 400 struct file *newfile;
392 int fd = sock_alloc_file(sock, &newfile, flags); 401 int fd = sock_alloc_file(sock, &newfile, flags, NULL);
393 402
394 if (likely(fd >= 0)) 403 if (likely(fd >= 0))
395 fd_install(fd, newfile); 404 fd_install(fd, newfile);
@@ -455,6 +464,68 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
455 return NULL; 464 return NULL;
456} 465}
457 466
467#define XATTR_SOCKPROTONAME_SUFFIX "sockprotoname"
468#define XATTR_NAME_SOCKPROTONAME (XATTR_SYSTEM_PREFIX XATTR_SOCKPROTONAME_SUFFIX)
469#define XATTR_NAME_SOCKPROTONAME_LEN (sizeof(XATTR_NAME_SOCKPROTONAME)-1)
470static ssize_t sockfs_getxattr(struct dentry *dentry,
471 const char *name, void *value, size_t size)
472{
473 const char *proto_name;
474 size_t proto_size;
475 int error;
476
477 error = -ENODATA;
478 if (!strncmp(name, XATTR_NAME_SOCKPROTONAME, XATTR_NAME_SOCKPROTONAME_LEN)) {
479 proto_name = dentry->d_name.name;
480 proto_size = strlen(proto_name);
481
482 if (value) {
483 error = -ERANGE;
484 if (proto_size + 1 > size)
485 goto out;
486
487 strncpy(value, proto_name, proto_size + 1);
488 }
489 error = proto_size + 1;
490 }
491
492out:
493 return error;
494}
495
496static ssize_t sockfs_listxattr(struct dentry *dentry, char *buffer,
497 size_t size)
498{
499 ssize_t len;
500 ssize_t used = 0;
501
502 len = security_inode_listsecurity(dentry->d_inode, buffer, size);
503 if (len < 0)
504 return len;
505 used += len;
506 if (buffer) {
507 if (size < used)
508 return -ERANGE;
509 buffer += len;
510 }
511
512 len = (XATTR_NAME_SOCKPROTONAME_LEN + 1);
513 used += len;
514 if (buffer) {
515 if (size < used)
516 return -ERANGE;
517 memcpy(buffer, XATTR_NAME_SOCKPROTONAME, len);
518 buffer += len;
519 }
520
521 return used;
522}
523
524static const struct inode_operations sockfs_inode_ops = {
525 .getxattr = sockfs_getxattr,
526 .listxattr = sockfs_listxattr,
527};
528
458/** 529/**
459 * sock_alloc - allocate a socket 530 * sock_alloc - allocate a socket
460 * 531 *
@@ -479,6 +550,7 @@ static struct socket *sock_alloc(void)
479 inode->i_mode = S_IFSOCK | S_IRWXUGO; 550 inode->i_mode = S_IFSOCK | S_IRWXUGO;
480 inode->i_uid = current_fsuid(); 551 inode->i_uid = current_fsuid();
481 inode->i_gid = current_fsgid(); 552 inode->i_gid = current_fsgid();
553 inode->i_op = &sockfs_inode_ops;
482 554
483 this_cpu_add(sockets_in_use, 1); 555 this_cpu_add(sockets_in_use, 1);
484 return sock; 556 return sock;
@@ -1394,13 +1466,13 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
1394 if (err < 0) 1466 if (err < 0)
1395 goto out_release_both; 1467 goto out_release_both;
1396 1468
1397 fd1 = sock_alloc_file(sock1, &newfile1, flags); 1469 fd1 = sock_alloc_file(sock1, &newfile1, flags, NULL);
1398 if (unlikely(fd1 < 0)) { 1470 if (unlikely(fd1 < 0)) {
1399 err = fd1; 1471 err = fd1;
1400 goto out_release_both; 1472 goto out_release_both;
1401 } 1473 }
1402 1474
1403 fd2 = sock_alloc_file(sock2, &newfile2, flags); 1475 fd2 = sock_alloc_file(sock2, &newfile2, flags, NULL);
1404 if (unlikely(fd2 < 0)) { 1476 if (unlikely(fd2 < 0)) {
1405 err = fd2; 1477 err = fd2;
1406 fput(newfile1); 1478 fput(newfile1);
@@ -1536,7 +1608,8 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr,
1536 */ 1608 */
1537 __module_get(newsock->ops->owner); 1609 __module_get(newsock->ops->owner);
1538 1610
1539 newfd = sock_alloc_file(newsock, &newfile, flags); 1611 newfd = sock_alloc_file(newsock, &newfile, flags,
1612 sock->sk->sk_prot_creator->name);
1540 if (unlikely(newfd < 0)) { 1613 if (unlikely(newfd < 0)) {
1541 err = newfd; 1614 err = newfd;
1542 sock_release(newsock); 1615 sock_release(newsock);