diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/net/socket.c b/net/socket.c index 2270b941bcc7..3ca2fd9e3720 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -209,8 +209,8 @@ int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr *kaddr) | |||
209 | * specified. Zero is returned for a success. | 209 | * specified. Zero is returned for a success. |
210 | */ | 210 | */ |
211 | 211 | ||
212 | int move_addr_to_user(struct sockaddr *kaddr, int klen, void __user *uaddr, | 212 | static int move_addr_to_user(struct sockaddr *kaddr, int klen, |
213 | int __user *ulen) | 213 | void __user *uaddr, int __user *ulen) |
214 | { | 214 | { |
215 | int err; | 215 | int err; |
216 | int len; | 216 | int len; |
@@ -305,19 +305,17 @@ static const struct super_operations sockfs_ops = { | |||
305 | .statfs = simple_statfs, | 305 | .statfs = simple_statfs, |
306 | }; | 306 | }; |
307 | 307 | ||
308 | static int sockfs_get_sb(struct file_system_type *fs_type, | 308 | static struct dentry *sockfs_mount(struct file_system_type *fs_type, |
309 | int flags, const char *dev_name, void *data, | 309 | int flags, const char *dev_name, void *data) |
310 | struct vfsmount *mnt) | ||
311 | { | 310 | { |
312 | return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC, | 311 | return mount_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC); |
313 | mnt); | ||
314 | } | 312 | } |
315 | 313 | ||
316 | static struct vfsmount *sock_mnt __read_mostly; | 314 | static struct vfsmount *sock_mnt __read_mostly; |
317 | 315 | ||
318 | static struct file_system_type sock_fs_type = { | 316 | static struct file_system_type sock_fs_type = { |
319 | .name = "sockfs", | 317 | .name = "sockfs", |
320 | .get_sb = sockfs_get_sb, | 318 | .mount = sockfs_mount, |
321 | .kill_sb = kill_anon_super, | 319 | .kill_sb = kill_anon_super, |
322 | }; | 320 | }; |
323 | 321 | ||
@@ -377,7 +375,7 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | |||
377 | &socket_file_ops); | 375 | &socket_file_ops); |
378 | if (unlikely(!file)) { | 376 | if (unlikely(!file)) { |
379 | /* drop dentry, keep inode */ | 377 | /* drop dentry, keep inode */ |
380 | atomic_inc(&path.dentry->d_inode->i_count); | 378 | ihold(path.dentry->d_inode); |
381 | path_put(&path); | 379 | path_put(&path); |
382 | put_unused_fd(fd); | 380 | put_unused_fd(fd); |
383 | return -ENFILE; | 381 | return -ENFILE; |
@@ -480,6 +478,7 @@ static struct socket *sock_alloc(void) | |||
480 | sock = SOCKET_I(inode); | 478 | sock = SOCKET_I(inode); |
481 | 479 | ||
482 | kmemcheck_annotate_bitfield(sock, type); | 480 | kmemcheck_annotate_bitfield(sock, type); |
481 | inode->i_ino = get_next_ino(); | ||
483 | inode->i_mode = S_IFSOCK | S_IRWXUGO; | 482 | inode->i_mode = S_IFSOCK | S_IRWXUGO; |
484 | inode->i_uid = current_fsuid(); | 483 | inode->i_uid = current_fsuid(); |
485 | inode->i_gid = current_fsgid(); | 484 | inode->i_gid = current_fsgid(); |
@@ -502,6 +501,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) | |||
502 | const struct file_operations bad_sock_fops = { | 501 | const struct file_operations bad_sock_fops = { |
503 | .owner = THIS_MODULE, | 502 | .owner = THIS_MODULE, |
504 | .open = sock_no_open, | 503 | .open = sock_no_open, |
504 | .llseek = noop_llseek, | ||
505 | }; | 505 | }; |
506 | 506 | ||
507 | /** | 507 | /** |
@@ -535,14 +535,13 @@ void sock_release(struct socket *sock) | |||
535 | } | 535 | } |
536 | EXPORT_SYMBOL(sock_release); | 536 | EXPORT_SYMBOL(sock_release); |
537 | 537 | ||
538 | int sock_tx_timestamp(struct msghdr *msg, struct sock *sk, | 538 | int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) |
539 | union skb_shared_tx *shtx) | ||
540 | { | 539 | { |
541 | shtx->flags = 0; | 540 | *tx_flags = 0; |
542 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | 541 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) |
543 | shtx->hardware = 1; | 542 | *tx_flags |= SKBTX_HW_TSTAMP; |
544 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | 543 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) |
545 | shtx->software = 1; | 544 | *tx_flags |= SKBTX_SW_TSTAMP; |
546 | return 0; | 545 | return 0; |
547 | } | 546 | } |
548 | EXPORT_SYMBOL(sock_tx_timestamp); | 547 | EXPORT_SYMBOL(sock_tx_timestamp); |
@@ -662,7 +661,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
662 | } | 661 | } |
663 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 662 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
664 | 663 | ||
665 | inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) | 664 | static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, |
665 | struct sk_buff *skb) | ||
666 | { | 666 | { |
667 | if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount) | 667 | if (sock_flag(sk, SOCK_RXQ_OVFL) && skb && skb->dropcount) |
668 | put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, | 668 | put_cmsg(msg, SOL_SOCKET, SO_RXQ_OVFL, |
@@ -1144,7 +1144,7 @@ call_kill: | |||
1144 | } | 1144 | } |
1145 | EXPORT_SYMBOL(sock_wake_async); | 1145 | EXPORT_SYMBOL(sock_wake_async); |
1146 | 1146 | ||
1147 | static int __sock_create(struct net *net, int family, int type, int protocol, | 1147 | int __sock_create(struct net *net, int family, int type, int protocol, |
1148 | struct socket **res, int kern) | 1148 | struct socket **res, int kern) |
1149 | { | 1149 | { |
1150 | int err; | 1150 | int err; |
@@ -1256,6 +1256,7 @@ out_release: | |||
1256 | rcu_read_unlock(); | 1256 | rcu_read_unlock(); |
1257 | goto out_sock_release; | 1257 | goto out_sock_release; |
1258 | } | 1258 | } |
1259 | EXPORT_SYMBOL(__sock_create); | ||
1259 | 1260 | ||
1260 | int sock_create(int family, int type, int protocol, struct socket **res) | 1261 | int sock_create(int family, int type, int protocol, struct socket **res) |
1261 | { | 1262 | { |
@@ -1651,6 +1652,8 @@ SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len, | |||
1651 | struct iovec iov; | 1652 | struct iovec iov; |
1652 | int fput_needed; | 1653 | int fput_needed; |
1653 | 1654 | ||
1655 | if (len > INT_MAX) | ||
1656 | len = INT_MAX; | ||
1654 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1657 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1655 | if (!sock) | 1658 | if (!sock) |
1656 | goto out; | 1659 | goto out; |
@@ -1708,6 +1711,8 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, | |||
1708 | int err, err2; | 1711 | int err, err2; |
1709 | int fput_needed; | 1712 | int fput_needed; |
1710 | 1713 | ||
1714 | if (size > INT_MAX) | ||
1715 | size = INT_MAX; | ||
1711 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | 1716 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1712 | if (!sock) | 1717 | if (!sock) |
1713 | goto out; | 1718 | goto out; |
@@ -1919,7 +1924,8 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) | |||
1919 | * Afterwards, it will be a kernel pointer. Thus the compiler-assisted | 1924 | * Afterwards, it will be a kernel pointer. Thus the compiler-assisted |
1920 | * checking falls down on this. | 1925 | * checking falls down on this. |
1921 | */ | 1926 | */ |
1922 | if (copy_from_user(ctl_buf, (void __user *)msg_sys.msg_control, | 1927 | if (copy_from_user(ctl_buf, |
1928 | (void __user __force *)msg_sys.msg_control, | ||
1923 | ctl_len)) | 1929 | ctl_len)) |
1924 | goto out_freectl; | 1930 | goto out_freectl; |
1925 | msg_sys.msg_control = ctl_buf; | 1931 | msg_sys.msg_control = ctl_buf; |
@@ -3054,14 +3060,19 @@ int kernel_getsockopt(struct socket *sock, int level, int optname, | |||
3054 | char *optval, int *optlen) | 3060 | char *optval, int *optlen) |
3055 | { | 3061 | { |
3056 | mm_segment_t oldfs = get_fs(); | 3062 | mm_segment_t oldfs = get_fs(); |
3063 | char __user *uoptval; | ||
3064 | int __user *uoptlen; | ||
3057 | int err; | 3065 | int err; |
3058 | 3066 | ||
3067 | uoptval = (char __user __force *) optval; | ||
3068 | uoptlen = (int __user __force *) optlen; | ||
3069 | |||
3059 | set_fs(KERNEL_DS); | 3070 | set_fs(KERNEL_DS); |
3060 | if (level == SOL_SOCKET) | 3071 | if (level == SOL_SOCKET) |
3061 | err = sock_getsockopt(sock, level, optname, optval, optlen); | 3072 | err = sock_getsockopt(sock, level, optname, uoptval, uoptlen); |
3062 | else | 3073 | else |
3063 | err = sock->ops->getsockopt(sock, level, optname, optval, | 3074 | err = sock->ops->getsockopt(sock, level, optname, uoptval, |
3064 | optlen); | 3075 | uoptlen); |
3065 | set_fs(oldfs); | 3076 | set_fs(oldfs); |
3066 | return err; | 3077 | return err; |
3067 | } | 3078 | } |
@@ -3071,13 +3082,16 @@ int kernel_setsockopt(struct socket *sock, int level, int optname, | |||
3071 | char *optval, unsigned int optlen) | 3082 | char *optval, unsigned int optlen) |
3072 | { | 3083 | { |
3073 | mm_segment_t oldfs = get_fs(); | 3084 | mm_segment_t oldfs = get_fs(); |
3085 | char __user *uoptval; | ||
3074 | int err; | 3086 | int err; |
3075 | 3087 | ||
3088 | uoptval = (char __user __force *) optval; | ||
3089 | |||
3076 | set_fs(KERNEL_DS); | 3090 | set_fs(KERNEL_DS); |
3077 | if (level == SOL_SOCKET) | 3091 | if (level == SOL_SOCKET) |
3078 | err = sock_setsockopt(sock, level, optname, optval, optlen); | 3092 | err = sock_setsockopt(sock, level, optname, uoptval, optlen); |
3079 | else | 3093 | else |
3080 | err = sock->ops->setsockopt(sock, level, optname, optval, | 3094 | err = sock->ops->setsockopt(sock, level, optname, uoptval, |
3081 | optlen); | 3095 | optlen); |
3082 | set_fs(oldfs); | 3096 | set_fs(oldfs); |
3083 | return err; | 3097 | return err; |