diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index cef79873b09d..928691c43408 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -85,7 +85,7 @@ | |||
85 | #include <linux/module.h> | 85 | #include <linux/module.h> |
86 | #include <linux/kernel.h> | 86 | #include <linux/kernel.h> |
87 | #include <linux/signal.h> | 87 | #include <linux/signal.h> |
88 | #include <linux/sched.h> | 88 | #include <linux/sched/signal.h> |
89 | #include <linux/errno.h> | 89 | #include <linux/errno.h> |
90 | #include <linux/string.h> | 90 | #include <linux/string.h> |
91 | #include <linux/stat.h> | 91 | #include <linux/stat.h> |
@@ -117,6 +117,7 @@ | |||
117 | #include <net/checksum.h> | 117 | #include <net/checksum.h> |
118 | #include <linux/security.h> | 118 | #include <linux/security.h> |
119 | #include <linux/freezer.h> | 119 | #include <linux/freezer.h> |
120 | #include <linux/file.h> | ||
120 | 121 | ||
121 | struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; | 122 | struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; |
122 | EXPORT_SYMBOL_GPL(unix_socket_table); | 123 | EXPORT_SYMBOL_GPL(unix_socket_table); |
@@ -635,7 +636,7 @@ static int unix_bind(struct socket *, struct sockaddr *, int); | |||
635 | static int unix_stream_connect(struct socket *, struct sockaddr *, | 636 | static int unix_stream_connect(struct socket *, struct sockaddr *, |
636 | int addr_len, int flags); | 637 | int addr_len, int flags); |
637 | static int unix_socketpair(struct socket *, struct socket *); | 638 | static int unix_socketpair(struct socket *, struct socket *); |
638 | static int unix_accept(struct socket *, struct socket *, int); | 639 | static int unix_accept(struct socket *, struct socket *, int, bool); |
639 | static int unix_getname(struct socket *, struct sockaddr *, int *, int); | 640 | static int unix_getname(struct socket *, struct sockaddr *, int *, int); |
640 | static unsigned int unix_poll(struct file *, struct socket *, poll_table *); | 641 | static unsigned int unix_poll(struct file *, struct socket *, poll_table *); |
641 | static unsigned int unix_dgram_poll(struct file *, struct socket *, | 642 | static unsigned int unix_dgram_poll(struct file *, struct socket *, |
@@ -1401,7 +1402,8 @@ static void unix_sock_inherit_flags(const struct socket *old, | |||
1401 | set_bit(SOCK_PASSSEC, &new->flags); | 1402 | set_bit(SOCK_PASSSEC, &new->flags); |
1402 | } | 1403 | } |
1403 | 1404 | ||
1404 | static int unix_accept(struct socket *sock, struct socket *newsock, int flags) | 1405 | static int unix_accept(struct socket *sock, struct socket *newsock, int flags, |
1406 | bool kern) | ||
1405 | { | 1407 | { |
1406 | struct sock *sk = sock->sk; | 1408 | struct sock *sk = sock->sk; |
1407 | struct sock *tsk; | 1409 | struct sock *tsk; |
@@ -2592,6 +2594,43 @@ long unix_outq_len(struct sock *sk) | |||
2592 | } | 2594 | } |
2593 | EXPORT_SYMBOL_GPL(unix_outq_len); | 2595 | EXPORT_SYMBOL_GPL(unix_outq_len); |
2594 | 2596 | ||
2597 | static int unix_open_file(struct sock *sk) | ||
2598 | { | ||
2599 | struct path path; | ||
2600 | struct file *f; | ||
2601 | int fd; | ||
2602 | |||
2603 | if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) | ||
2604 | return -EPERM; | ||
2605 | |||
2606 | unix_state_lock(sk); | ||
2607 | path = unix_sk(sk)->path; | ||
2608 | if (!path.dentry) { | ||
2609 | unix_state_unlock(sk); | ||
2610 | return -ENOENT; | ||
2611 | } | ||
2612 | |||
2613 | path_get(&path); | ||
2614 | unix_state_unlock(sk); | ||
2615 | |||
2616 | fd = get_unused_fd_flags(O_CLOEXEC); | ||
2617 | if (fd < 0) | ||
2618 | goto out; | ||
2619 | |||
2620 | f = dentry_open(&path, O_PATH, current_cred()); | ||
2621 | if (IS_ERR(f)) { | ||
2622 | put_unused_fd(fd); | ||
2623 | fd = PTR_ERR(f); | ||
2624 | goto out; | ||
2625 | } | ||
2626 | |||
2627 | fd_install(fd, f); | ||
2628 | out: | ||
2629 | path_put(&path); | ||
2630 | |||
2631 | return fd; | ||
2632 | } | ||
2633 | |||
2595 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 2634 | static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
2596 | { | 2635 | { |
2597 | struct sock *sk = sock->sk; | 2636 | struct sock *sk = sock->sk; |
@@ -2610,6 +2649,9 @@ static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
2610 | else | 2649 | else |
2611 | err = put_user(amount, (int __user *)arg); | 2650 | err = put_user(amount, (int __user *)arg); |
2612 | break; | 2651 | break; |
2652 | case SIOCUNIXFILE: | ||
2653 | err = unix_open_file(sk); | ||
2654 | break; | ||
2613 | default: | 2655 | default: |
2614 | err = -ENOIOCTLCMD; | 2656 | err = -ENOIOCTLCMD; |
2615 | break; | 2657 | break; |