aboutsummaryrefslogtreecommitdiffstats
path: root/net/socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/socket.c')
-rw-r--r--net/socket.c123
1 files changed, 51 insertions, 72 deletions
diff --git a/net/socket.c b/net/socket.c
index e83c416708af..a19ae1968d37 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -450,16 +450,17 @@ EXPORT_SYMBOL(sockfd_lookup);
450 450
451static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) 451static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed)
452{ 452{
453 struct file *file; 453 struct fd f = fdget(fd);
454 struct socket *sock; 454 struct socket *sock;
455 455
456 *err = -EBADF; 456 *err = -EBADF;
457 file = fget_light(fd, fput_needed); 457 if (f.file) {
458 if (file) { 458 sock = sock_from_file(f.file, err);
459 sock = sock_from_file(file, err); 459 if (likely(sock)) {
460 if (sock) 460 *fput_needed = f.flags;
461 return sock; 461 return sock;
462 fput_light(file, *fput_needed); 462 }
463 fdput(f);
463 } 464 }
464 return NULL; 465 return NULL;
465} 466}
@@ -1445,48 +1446,61 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
1445 err = fd1; 1446 err = fd1;
1446 goto out_release_both; 1447 goto out_release_both;
1447 } 1448 }
1449
1448 fd2 = get_unused_fd_flags(flags); 1450 fd2 = get_unused_fd_flags(flags);
1449 if (unlikely(fd2 < 0)) { 1451 if (unlikely(fd2 < 0)) {
1450 err = fd2; 1452 err = fd2;
1451 put_unused_fd(fd1); 1453 goto out_put_unused_1;
1452 goto out_release_both;
1453 } 1454 }
1454 1455
1455 newfile1 = sock_alloc_file(sock1, flags, NULL); 1456 newfile1 = sock_alloc_file(sock1, flags, NULL);
1456 if (unlikely(IS_ERR(newfile1))) { 1457 if (unlikely(IS_ERR(newfile1))) {
1457 err = PTR_ERR(newfile1); 1458 err = PTR_ERR(newfile1);
1458 put_unused_fd(fd1); 1459 goto out_put_unused_both;
1459 put_unused_fd(fd2);
1460 goto out_release_both;
1461 } 1460 }
1462 1461
1463 newfile2 = sock_alloc_file(sock2, flags, NULL); 1462 newfile2 = sock_alloc_file(sock2, flags, NULL);
1464 if (IS_ERR(newfile2)) { 1463 if (IS_ERR(newfile2)) {
1465 err = PTR_ERR(newfile2); 1464 err = PTR_ERR(newfile2);
1466 fput(newfile1); 1465 goto out_fput_1;
1467 put_unused_fd(fd1);
1468 put_unused_fd(fd2);
1469 sock_release(sock2);
1470 goto out;
1471 } 1466 }
1472 1467
1468 err = put_user(fd1, &usockvec[0]);
1469 if (err)
1470 goto out_fput_both;
1471
1472 err = put_user(fd2, &usockvec[1]);
1473 if (err)
1474 goto out_fput_both;
1475
1473 audit_fd_pair(fd1, fd2); 1476 audit_fd_pair(fd1, fd2);
1477
1474 fd_install(fd1, newfile1); 1478 fd_install(fd1, newfile1);
1475 fd_install(fd2, newfile2); 1479 fd_install(fd2, newfile2);
1476 /* fd1 and fd2 may be already another descriptors. 1480 /* fd1 and fd2 may be already another descriptors.
1477 * Not kernel problem. 1481 * Not kernel problem.
1478 */ 1482 */
1479 1483
1480 err = put_user(fd1, &usockvec[0]); 1484 return 0;
1481 if (!err)
1482 err = put_user(fd2, &usockvec[1]);
1483 if (!err)
1484 return 0;
1485 1485
1486 sys_close(fd2); 1486out_fput_both:
1487 sys_close(fd1); 1487 fput(newfile2);
1488 return err; 1488 fput(newfile1);
1489 put_unused_fd(fd2);
1490 put_unused_fd(fd1);
1491 goto out;
1492
1493out_fput_1:
1494 fput(newfile1);
1495 put_unused_fd(fd2);
1496 put_unused_fd(fd1);
1497 sock_release(sock2);
1498 goto out;
1489 1499
1500out_put_unused_both:
1501 put_unused_fd(fd2);
1502out_put_unused_1:
1503 put_unused_fd(fd1);
1490out_release_both: 1504out_release_both:
1491 sock_release(sock2); 1505 sock_release(sock2);
1492out_release_1: 1506out_release_1:
@@ -1972,6 +1986,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
1972{ 1986{
1973 if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) 1987 if (copy_from_user(kmsg, umsg, sizeof(struct msghdr)))
1974 return -EFAULT; 1988 return -EFAULT;
1989
1990 if (kmsg->msg_namelen < 0)
1991 return -EINVAL;
1992
1975 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) 1993 if (kmsg->msg_namelen > sizeof(struct sockaddr_storage))
1976 kmsg->msg_namelen = sizeof(struct sockaddr_storage); 1994 kmsg->msg_namelen = sizeof(struct sockaddr_storage);
1977 return 0; 1995 return 0;
@@ -2968,11 +2986,8 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
2968 struct compat_ifreq __user *ifr32) 2986 struct compat_ifreq __user *ifr32)
2969{ 2987{
2970 struct ifreq kifr; 2988 struct ifreq kifr;
2971 struct ifreq __user *uifr;
2972 mm_segment_t old_fs; 2989 mm_segment_t old_fs;
2973 int err; 2990 int err;
2974 u32 data;
2975 void __user *datap;
2976 2991
2977 switch (cmd) { 2992 switch (cmd) {
2978 case SIOCBONDENSLAVE: 2993 case SIOCBONDENSLAVE:
@@ -2989,26 +3004,13 @@ static int bond_ioctl(struct net *net, unsigned int cmd,
2989 set_fs(old_fs); 3004 set_fs(old_fs);
2990 3005
2991 return err; 3006 return err;
2992 case SIOCBONDSLAVEINFOQUERY:
2993 case SIOCBONDINFOQUERY:
2994 uifr = compat_alloc_user_space(sizeof(*uifr));
2995 if (copy_in_user(&uifr->ifr_name, &ifr32->ifr_name, IFNAMSIZ))
2996 return -EFAULT;
2997
2998 if (get_user(data, &ifr32->ifr_ifru.ifru_data))
2999 return -EFAULT;
3000
3001 datap = compat_ptr(data);
3002 if (put_user(datap, &uifr->ifr_ifru.ifru_data))
3003 return -EFAULT;
3004
3005 return dev_ioctl(net, cmd, uifr);
3006 default: 3007 default:
3007 return -ENOIOCTLCMD; 3008 return -ENOIOCTLCMD;
3008 } 3009 }
3009} 3010}
3010 3011
3011static int siocdevprivate_ioctl(struct net *net, unsigned int cmd, 3012/* Handle ioctls that use ifreq::ifr_data and just need struct ifreq converted */
3013static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
3012 struct compat_ifreq __user *u_ifreq32) 3014 struct compat_ifreq __user *u_ifreq32)
3013{ 3015{
3014 struct ifreq __user *u_ifreq64; 3016 struct ifreq __user *u_ifreq64;
@@ -3019,19 +3021,16 @@ static int siocdevprivate_ioctl(struct net *net, unsigned int cmd,
3019 if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]), 3021 if (copy_from_user(&tmp_buf[0], &(u_ifreq32->ifr_ifrn.ifrn_name[0]),
3020 IFNAMSIZ)) 3022 IFNAMSIZ))
3021 return -EFAULT; 3023 return -EFAULT;
3022 if (__get_user(data32, &u_ifreq32->ifr_ifru.ifru_data)) 3024 if (get_user(data32, &u_ifreq32->ifr_ifru.ifru_data))
3023 return -EFAULT; 3025 return -EFAULT;
3024 data64 = compat_ptr(data32); 3026 data64 = compat_ptr(data32);
3025 3027
3026 u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64)); 3028 u_ifreq64 = compat_alloc_user_space(sizeof(*u_ifreq64));
3027 3029
3028 /* Don't check these user accesses, just let that get trapped
3029 * in the ioctl handler instead.
3030 */
3031 if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0], 3030 if (copy_to_user(&u_ifreq64->ifr_ifrn.ifrn_name[0], &tmp_buf[0],
3032 IFNAMSIZ)) 3031 IFNAMSIZ))
3033 return -EFAULT; 3032 return -EFAULT;
3034 if (__put_user(data64, &u_ifreq64->ifr_ifru.ifru_data)) 3033 if (put_user(data64, &u_ifreq64->ifr_ifru.ifru_data))
3035 return -EFAULT; 3034 return -EFAULT;
3036 3035
3037 return dev_ioctl(net, cmd, u_ifreq64); 3036 return dev_ioctl(net, cmd, u_ifreq64);
@@ -3111,27 +3110,6 @@ static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
3111 return err; 3110 return err;
3112} 3111}
3113 3112
3114static int compat_siocshwtstamp(struct net *net, struct compat_ifreq __user *uifr32)
3115{
3116 void __user *uptr;
3117 compat_uptr_t uptr32;
3118 struct ifreq __user *uifr;
3119
3120 uifr = compat_alloc_user_space(sizeof(*uifr));
3121 if (copy_in_user(uifr, uifr32, sizeof(struct compat_ifreq)))
3122 return -EFAULT;
3123
3124 if (get_user(uptr32, &uifr32->ifr_data))
3125 return -EFAULT;
3126
3127 uptr = compat_ptr(uptr32);
3128
3129 if (put_user(uptr, &uifr->ifr_data))
3130 return -EFAULT;
3131
3132 return dev_ioctl(net, SIOCSHWTSTAMP, uifr);
3133}
3134
3135struct rtentry32 { 3113struct rtentry32 {
3136 u32 rt_pad1; 3114 u32 rt_pad1;
3137 struct sockaddr rt_dst; /* target address */ 3115 struct sockaddr rt_dst; /* target address */
@@ -3243,7 +3221,7 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3243 struct net *net = sock_net(sk); 3221 struct net *net = sock_net(sk);
3244 3222
3245 if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) 3223 if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15))
3246 return siocdevprivate_ioctl(net, cmd, argp); 3224 return compat_ifr_data_ioctl(net, cmd, argp);
3247 3225
3248 switch (cmd) { 3226 switch (cmd) {
3249 case SIOCSIFBR: 3227 case SIOCSIFBR:
@@ -3263,8 +3241,6 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3263 case SIOCBONDENSLAVE: 3241 case SIOCBONDENSLAVE:
3264 case SIOCBONDRELEASE: 3242 case SIOCBONDRELEASE:
3265 case SIOCBONDSETHWADDR: 3243 case SIOCBONDSETHWADDR:
3266 case SIOCBONDSLAVEINFOQUERY:
3267 case SIOCBONDINFOQUERY:
3268 case SIOCBONDCHANGEACTIVE: 3244 case SIOCBONDCHANGEACTIVE:
3269 return bond_ioctl(net, cmd, argp); 3245 return bond_ioctl(net, cmd, argp);
3270 case SIOCADDRT: 3246 case SIOCADDRT:
@@ -3274,8 +3250,11 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
3274 return do_siocgstamp(net, sock, cmd, argp); 3250 return do_siocgstamp(net, sock, cmd, argp);
3275 case SIOCGSTAMPNS: 3251 case SIOCGSTAMPNS:
3276 return do_siocgstampns(net, sock, cmd, argp); 3252 return do_siocgstampns(net, sock, cmd, argp);
3253 case SIOCBONDSLAVEINFOQUERY:
3254 case SIOCBONDINFOQUERY:
3277 case SIOCSHWTSTAMP: 3255 case SIOCSHWTSTAMP:
3278 return compat_siocshwtstamp(net, argp); 3256 case SIOCGHWTSTAMP:
3257 return compat_ifr_data_ioctl(net, cmd, argp);
3279 3258
3280 case FIOSETOWN: 3259 case FIOSETOWN:
3281 case SIOCSPGRP: 3260 case SIOCSPGRP: