diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 353 |
1 files changed, 212 insertions, 141 deletions
diff --git a/net/socket.c b/net/socket.c index 7e1bdef8b09e..e2d5bae994de 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -68,6 +68,7 @@ | |||
68 | #include <linux/netdevice.h> | 68 | #include <linux/netdevice.h> |
69 | #include <linux/proc_fs.h> | 69 | #include <linux/proc_fs.h> |
70 | #include <linux/seq_file.h> | 70 | #include <linux/seq_file.h> |
71 | #include <linux/mutex.h> | ||
71 | #include <linux/wanrouter.h> | 72 | #include <linux/wanrouter.h> |
72 | #include <linux/if_bridge.h> | 73 | #include <linux/if_bridge.h> |
73 | #include <linux/if_frad.h> | 74 | #include <linux/if_frad.h> |
@@ -106,6 +107,10 @@ static unsigned int sock_poll(struct file *file, | |||
106 | struct poll_table_struct *wait); | 107 | struct poll_table_struct *wait); |
107 | static long sock_ioctl(struct file *file, | 108 | static long sock_ioctl(struct file *file, |
108 | unsigned int cmd, unsigned long arg); | 109 | unsigned int cmd, unsigned long arg); |
110 | #ifdef CONFIG_COMPAT | ||
111 | static long compat_sock_ioctl(struct file *file, | ||
112 | unsigned int cmd, unsigned long arg); | ||
113 | #endif | ||
109 | static int sock_fasync(int fd, struct file *filp, int on); | 114 | static int sock_fasync(int fd, struct file *filp, int on); |
110 | static ssize_t sock_readv(struct file *file, const struct iovec *vector, | 115 | static ssize_t sock_readv(struct file *file, const struct iovec *vector, |
111 | unsigned long count, loff_t *ppos); | 116 | unsigned long count, loff_t *ppos); |
@@ -127,6 +132,9 @@ static struct file_operations socket_file_ops = { | |||
127 | .aio_write = sock_aio_write, | 132 | .aio_write = sock_aio_write, |
128 | .poll = sock_poll, | 133 | .poll = sock_poll, |
129 | .unlocked_ioctl = sock_ioctl, | 134 | .unlocked_ioctl = sock_ioctl, |
135 | #ifdef CONFIG_COMPAT | ||
136 | .compat_ioctl = compat_sock_ioctl, | ||
137 | #endif | ||
130 | .mmap = sock_mmap, | 138 | .mmap = sock_mmap, |
131 | .open = sock_no_open, /* special open code to disallow open via /proc */ | 139 | .open = sock_no_open, /* special open code to disallow open via /proc */ |
132 | .release = sock_close, | 140 | .release = sock_close, |
@@ -348,8 +356,8 @@ static struct dentry_operations sockfs_dentry_operations = { | |||
348 | /* | 356 | /* |
349 | * Obtains the first available file descriptor and sets it up for use. | 357 | * Obtains the first available file descriptor and sets it up for use. |
350 | * | 358 | * |
351 | * This function creates file structure and maps it to fd space | 359 | * These functions create file structures and maps them to fd space |
352 | * of current process. On success it returns file descriptor | 360 | * of the current process. On success it returns file descriptor |
353 | * and file struct implicitly stored in sock->file. | 361 | * and file struct implicitly stored in sock->file. |
354 | * Note that another thread may close file descriptor before we return | 362 | * Note that another thread may close file descriptor before we return |
355 | * from this function. We use the fact that now we do not refer | 363 | * from this function. We use the fact that now we do not refer |
@@ -362,53 +370,90 @@ static struct dentry_operations sockfs_dentry_operations = { | |||
362 | * but we take care of internal coherence yet. | 370 | * but we take care of internal coherence yet. |
363 | */ | 371 | */ |
364 | 372 | ||
365 | int sock_map_fd(struct socket *sock) | 373 | static int sock_alloc_fd(struct file **filep) |
366 | { | 374 | { |
367 | int fd; | 375 | int fd; |
368 | struct qstr this; | ||
369 | char name[32]; | ||
370 | |||
371 | /* | ||
372 | * Find a file descriptor suitable for return to the user. | ||
373 | */ | ||
374 | 376 | ||
375 | fd = get_unused_fd(); | 377 | fd = get_unused_fd(); |
376 | if (fd >= 0) { | 378 | if (likely(fd >= 0)) { |
377 | struct file *file = get_empty_filp(); | 379 | struct file *file = get_empty_filp(); |
378 | 380 | ||
379 | if (!file) { | 381 | *filep = file; |
382 | if (unlikely(!file)) { | ||
380 | put_unused_fd(fd); | 383 | put_unused_fd(fd); |
381 | fd = -ENFILE; | 384 | return -ENFILE; |
382 | goto out; | ||
383 | } | 385 | } |
386 | } else | ||
387 | *filep = NULL; | ||
388 | return fd; | ||
389 | } | ||
390 | |||
391 | static int sock_attach_fd(struct socket *sock, struct file *file) | ||
392 | { | ||
393 | struct qstr this; | ||
394 | char name[32]; | ||
384 | 395 | ||
385 | this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); | 396 | this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); |
386 | this.name = name; | 397 | this.name = name; |
387 | this.hash = SOCK_INODE(sock)->i_ino; | 398 | this.hash = SOCK_INODE(sock)->i_ino; |
388 | 399 | ||
389 | file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); | 400 | file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); |
390 | if (!file->f_dentry) { | 401 | if (unlikely(!file->f_dentry)) |
391 | put_filp(file); | 402 | return -ENOMEM; |
403 | |||
404 | file->f_dentry->d_op = &sockfs_dentry_operations; | ||
405 | d_add(file->f_dentry, SOCK_INODE(sock)); | ||
406 | file->f_vfsmnt = mntget(sock_mnt); | ||
407 | file->f_mapping = file->f_dentry->d_inode->i_mapping; | ||
408 | |||
409 | sock->file = file; | ||
410 | file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; | ||
411 | file->f_mode = FMODE_READ | FMODE_WRITE; | ||
412 | file->f_flags = O_RDWR; | ||
413 | file->f_pos = 0; | ||
414 | file->private_data = sock; | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | int sock_map_fd(struct socket *sock) | ||
420 | { | ||
421 | struct file *newfile; | ||
422 | int fd = sock_alloc_fd(&newfile); | ||
423 | |||
424 | if (likely(fd >= 0)) { | ||
425 | int err = sock_attach_fd(sock, newfile); | ||
426 | |||
427 | if (unlikely(err < 0)) { | ||
428 | put_filp(newfile); | ||
392 | put_unused_fd(fd); | 429 | put_unused_fd(fd); |
393 | fd = -ENOMEM; | 430 | return err; |
394 | goto out; | ||
395 | } | 431 | } |
396 | file->f_dentry->d_op = &sockfs_dentry_operations; | 432 | fd_install(fd, newfile); |
397 | d_add(file->f_dentry, SOCK_INODE(sock)); | 433 | } |
398 | file->f_vfsmnt = mntget(sock_mnt); | 434 | return fd; |
399 | file->f_mapping = file->f_dentry->d_inode->i_mapping; | 435 | } |
400 | 436 | ||
401 | sock->file = file; | 437 | static struct socket *sock_from_file(struct file *file, int *err) |
402 | file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; | 438 | { |
403 | file->f_mode = FMODE_READ | FMODE_WRITE; | 439 | struct inode *inode; |
404 | file->f_flags = O_RDWR; | 440 | struct socket *sock; |
405 | file->f_pos = 0; | 441 | |
406 | file->private_data = sock; | 442 | if (file->f_op == &socket_file_ops) |
407 | fd_install(fd, file); | 443 | return file->private_data; /* set in sock_map_fd */ |
444 | |||
445 | inode = file->f_dentry->d_inode; | ||
446 | if (!S_ISSOCK(inode->i_mode)) { | ||
447 | *err = -ENOTSOCK; | ||
448 | return NULL; | ||
408 | } | 449 | } |
409 | 450 | ||
410 | out: | 451 | sock = SOCKET_I(inode); |
411 | return fd; | 452 | if (sock->file != file) { |
453 | printk(KERN_ERR "socki_lookup: socket file changed!\n"); | ||
454 | sock->file = file; | ||
455 | } | ||
456 | return sock; | ||
412 | } | 457 | } |
413 | 458 | ||
414 | /** | 459 | /** |
@@ -427,31 +472,31 @@ out: | |||
427 | struct socket *sockfd_lookup(int fd, int *err) | 472 | struct socket *sockfd_lookup(int fd, int *err) |
428 | { | 473 | { |
429 | struct file *file; | 474 | struct file *file; |
430 | struct inode *inode; | ||
431 | struct socket *sock; | 475 | struct socket *sock; |
432 | 476 | ||
433 | if (!(file = fget(fd))) | 477 | if (!(file = fget(fd))) { |
434 | { | ||
435 | *err = -EBADF; | 478 | *err = -EBADF; |
436 | return NULL; | 479 | return NULL; |
437 | } | 480 | } |
438 | 481 | sock = sock_from_file(file, err); | |
439 | if (file->f_op == &socket_file_ops) | 482 | if (!sock) |
440 | return file->private_data; /* set in sock_map_fd */ | ||
441 | |||
442 | inode = file->f_dentry->d_inode; | ||
443 | if (!S_ISSOCK(inode->i_mode)) { | ||
444 | *err = -ENOTSOCK; | ||
445 | fput(file); | 483 | fput(file); |
446 | return NULL; | 484 | return sock; |
447 | } | 485 | } |
448 | 486 | ||
449 | sock = SOCKET_I(inode); | 487 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) |
450 | if (sock->file != file) { | 488 | { |
451 | printk(KERN_ERR "socki_lookup: socket file changed!\n"); | 489 | struct file *file; |
452 | sock->file = file; | 490 | struct socket *sock; |
491 | |||
492 | file = fget_light(fd, fput_needed); | ||
493 | if (file) { | ||
494 | sock = sock_from_file(file, err); | ||
495 | if (sock) | ||
496 | return sock; | ||
497 | fput_light(file, *fput_needed); | ||
453 | } | 498 | } |
454 | return sock; | 499 | return NULL; |
455 | } | 500 | } |
456 | 501 | ||
457 | /** | 502 | /** |
@@ -789,36 +834,36 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, | |||
789 | * with module unload. | 834 | * with module unload. |
790 | */ | 835 | */ |
791 | 836 | ||
792 | static DECLARE_MUTEX(br_ioctl_mutex); | 837 | static DEFINE_MUTEX(br_ioctl_mutex); |
793 | static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; | 838 | static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; |
794 | 839 | ||
795 | void brioctl_set(int (*hook)(unsigned int, void __user *)) | 840 | void brioctl_set(int (*hook)(unsigned int, void __user *)) |
796 | { | 841 | { |
797 | down(&br_ioctl_mutex); | 842 | mutex_lock(&br_ioctl_mutex); |
798 | br_ioctl_hook = hook; | 843 | br_ioctl_hook = hook; |
799 | up(&br_ioctl_mutex); | 844 | mutex_unlock(&br_ioctl_mutex); |
800 | } | 845 | } |
801 | EXPORT_SYMBOL(brioctl_set); | 846 | EXPORT_SYMBOL(brioctl_set); |
802 | 847 | ||
803 | static DECLARE_MUTEX(vlan_ioctl_mutex); | 848 | static DEFINE_MUTEX(vlan_ioctl_mutex); |
804 | static int (*vlan_ioctl_hook)(void __user *arg); | 849 | static int (*vlan_ioctl_hook)(void __user *arg); |
805 | 850 | ||
806 | void vlan_ioctl_set(int (*hook)(void __user *)) | 851 | void vlan_ioctl_set(int (*hook)(void __user *)) |
807 | { | 852 | { |
808 | down(&vlan_ioctl_mutex); | 853 | mutex_lock(&vlan_ioctl_mutex); |
809 | vlan_ioctl_hook = hook; | 854 | vlan_ioctl_hook = hook; |
810 | up(&vlan_ioctl_mutex); | 855 | mutex_unlock(&vlan_ioctl_mutex); |
811 | } | 856 | } |
812 | EXPORT_SYMBOL(vlan_ioctl_set); | 857 | EXPORT_SYMBOL(vlan_ioctl_set); |
813 | 858 | ||
814 | static DECLARE_MUTEX(dlci_ioctl_mutex); | 859 | static DEFINE_MUTEX(dlci_ioctl_mutex); |
815 | static int (*dlci_ioctl_hook)(unsigned int, void __user *); | 860 | static int (*dlci_ioctl_hook)(unsigned int, void __user *); |
816 | 861 | ||
817 | void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) | 862 | void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) |
818 | { | 863 | { |
819 | down(&dlci_ioctl_mutex); | 864 | mutex_lock(&dlci_ioctl_mutex); |
820 | dlci_ioctl_hook = hook; | 865 | dlci_ioctl_hook = hook; |
821 | up(&dlci_ioctl_mutex); | 866 | mutex_unlock(&dlci_ioctl_mutex); |
822 | } | 867 | } |
823 | EXPORT_SYMBOL(dlci_ioctl_set); | 868 | EXPORT_SYMBOL(dlci_ioctl_set); |
824 | 869 | ||
@@ -862,10 +907,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
862 | if (!br_ioctl_hook) | 907 | if (!br_ioctl_hook) |
863 | request_module("bridge"); | 908 | request_module("bridge"); |
864 | 909 | ||
865 | down(&br_ioctl_mutex); | 910 | mutex_lock(&br_ioctl_mutex); |
866 | if (br_ioctl_hook) | 911 | if (br_ioctl_hook) |
867 | err = br_ioctl_hook(cmd, argp); | 912 | err = br_ioctl_hook(cmd, argp); |
868 | up(&br_ioctl_mutex); | 913 | mutex_unlock(&br_ioctl_mutex); |
869 | break; | 914 | break; |
870 | case SIOCGIFVLAN: | 915 | case SIOCGIFVLAN: |
871 | case SIOCSIFVLAN: | 916 | case SIOCSIFVLAN: |
@@ -873,10 +918,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
873 | if (!vlan_ioctl_hook) | 918 | if (!vlan_ioctl_hook) |
874 | request_module("8021q"); | 919 | request_module("8021q"); |
875 | 920 | ||
876 | down(&vlan_ioctl_mutex); | 921 | mutex_lock(&vlan_ioctl_mutex); |
877 | if (vlan_ioctl_hook) | 922 | if (vlan_ioctl_hook) |
878 | err = vlan_ioctl_hook(argp); | 923 | err = vlan_ioctl_hook(argp); |
879 | up(&vlan_ioctl_mutex); | 924 | mutex_unlock(&vlan_ioctl_mutex); |
880 | break; | 925 | break; |
881 | case SIOCGIFDIVERT: | 926 | case SIOCGIFDIVERT: |
882 | case SIOCSIFDIVERT: | 927 | case SIOCSIFDIVERT: |
@@ -890,9 +935,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
890 | request_module("dlci"); | 935 | request_module("dlci"); |
891 | 936 | ||
892 | if (dlci_ioctl_hook) { | 937 | if (dlci_ioctl_hook) { |
893 | down(&dlci_ioctl_mutex); | 938 | mutex_lock(&dlci_ioctl_mutex); |
894 | err = dlci_ioctl_hook(cmd, argp); | 939 | err = dlci_ioctl_hook(cmd, argp); |
895 | up(&dlci_ioctl_mutex); | 940 | mutex_unlock(&dlci_ioctl_mutex); |
896 | } | 941 | } |
897 | break; | 942 | break; |
898 | default: | 943 | default: |
@@ -1286,19 +1331,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) | |||
1286 | { | 1331 | { |
1287 | struct socket *sock; | 1332 | struct socket *sock; |
1288 | char address[MAX_SOCK_ADDR]; | 1333 | char address[MAX_SOCK_ADDR]; |
1289 | int err; | 1334 | int err, fput_needed; |
1290 | 1335 | ||
1291 | if((sock = sockfd_lookup(fd,&err))!=NULL) | 1336 | if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL) |
1292 | { | 1337 | { |
1293 | if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { | 1338 | if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { |
1294 | err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); | 1339 | err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); |
1295 | if (err) { | 1340 | if (!err) |
1296 | sockfd_put(sock); | 1341 | err = sock->ops->bind(sock, |
1297 | return err; | 1342 | (struct sockaddr *)address, addrlen); |
1298 | } | ||
1299 | err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen); | ||
1300 | } | 1343 | } |
1301 | sockfd_put(sock); | 1344 | fput_light(sock->file, fput_needed); |
1302 | } | 1345 | } |
1303 | return err; | 1346 | return err; |
1304 | } | 1347 | } |
@@ -1315,20 +1358,17 @@ int sysctl_somaxconn = SOMAXCONN; | |||
1315 | asmlinkage long sys_listen(int fd, int backlog) | 1358 | asmlinkage long sys_listen(int fd, int backlog) |
1316 | { | 1359 | { |
1317 | struct socket *sock; | 1360 | struct socket *sock; |
1318 | int err; | 1361 | int err, fput_needed; |
1319 | 1362 | ||
1320 | if ((sock = sockfd_lookup(fd, &err)) != NULL) { | 1363 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { |
1321 | if ((unsigned) backlog > sysctl_somaxconn) | 1364 | if ((unsigned) backlog > sysctl_somaxconn) |
1322 | backlog = sysctl_somaxconn; | 1365 | backlog = sysctl_somaxconn; |
1323 | 1366 | ||
1324 | err = security_socket_listen(sock, backlog); | 1367 | err = security_socket_listen(sock, backlog); |
1325 | if (err) { | 1368 | if (!err) |
1326 | sockfd_put(sock); | 1369 | err = sock->ops->listen(sock, backlog); |
1327 | return err; | ||
1328 | } | ||
1329 | 1370 | ||
1330 | err=sock->ops->listen(sock, backlog); | 1371 | fput_light(sock->file, fput_needed); |
1331 | sockfd_put(sock); | ||
1332 | } | 1372 | } |
1333 | return err; | 1373 | return err; |
1334 | } | 1374 | } |
@@ -1349,10 +1389,11 @@ asmlinkage long sys_listen(int fd, int backlog) | |||
1349 | asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) | 1389 | asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) |
1350 | { | 1390 | { |
1351 | struct socket *sock, *newsock; | 1391 | struct socket *sock, *newsock; |
1352 | int err, len; | 1392 | struct file *newfile; |
1393 | int err, len, newfd, fput_needed; | ||
1353 | char address[MAX_SOCK_ADDR]; | 1394 | char address[MAX_SOCK_ADDR]; |
1354 | 1395 | ||
1355 | sock = sockfd_lookup(fd, &err); | 1396 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1356 | if (!sock) | 1397 | if (!sock) |
1357 | goto out; | 1398 | goto out; |
1358 | 1399 | ||
@@ -1369,35 +1410,48 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _ | |||
1369 | */ | 1410 | */ |
1370 | __module_get(newsock->ops->owner); | 1411 | __module_get(newsock->ops->owner); |
1371 | 1412 | ||
1413 | newfd = sock_alloc_fd(&newfile); | ||
1414 | if (unlikely(newfd < 0)) { | ||
1415 | err = newfd; | ||
1416 | goto out_release; | ||
1417 | } | ||
1418 | |||
1419 | err = sock_attach_fd(newsock, newfile); | ||
1420 | if (err < 0) | ||
1421 | goto out_fd; | ||
1422 | |||
1372 | err = security_socket_accept(sock, newsock); | 1423 | err = security_socket_accept(sock, newsock); |
1373 | if (err) | 1424 | if (err) |
1374 | goto out_release; | 1425 | goto out_fd; |
1375 | 1426 | ||
1376 | err = sock->ops->accept(sock, newsock, sock->file->f_flags); | 1427 | err = sock->ops->accept(sock, newsock, sock->file->f_flags); |
1377 | if (err < 0) | 1428 | if (err < 0) |
1378 | goto out_release; | 1429 | goto out_fd; |
1379 | 1430 | ||
1380 | if (upeer_sockaddr) { | 1431 | if (upeer_sockaddr) { |
1381 | if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { | 1432 | if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { |
1382 | err = -ECONNABORTED; | 1433 | err = -ECONNABORTED; |
1383 | goto out_release; | 1434 | goto out_fd; |
1384 | } | 1435 | } |
1385 | err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); | 1436 | err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); |
1386 | if (err < 0) | 1437 | if (err < 0) |
1387 | goto out_release; | 1438 | goto out_fd; |
1388 | } | 1439 | } |
1389 | 1440 | ||
1390 | /* File flags are not inherited via accept() unlike another OSes. */ | 1441 | /* File flags are not inherited via accept() unlike another OSes. */ |
1391 | 1442 | ||
1392 | if ((err = sock_map_fd(newsock)) < 0) | 1443 | fd_install(newfd, newfile); |
1393 | goto out_release; | 1444 | err = newfd; |
1394 | 1445 | ||
1395 | security_socket_post_accept(sock, newsock); | 1446 | security_socket_post_accept(sock, newsock); |
1396 | 1447 | ||
1397 | out_put: | 1448 | out_put: |
1398 | sockfd_put(sock); | 1449 | fput_light(sock->file, fput_needed); |
1399 | out: | 1450 | out: |
1400 | return err; | 1451 | return err; |
1452 | out_fd: | ||
1453 | put_filp(newfile); | ||
1454 | put_unused_fd(newfd); | ||
1401 | out_release: | 1455 | out_release: |
1402 | sock_release(newsock); | 1456 | sock_release(newsock); |
1403 | goto out_put; | 1457 | goto out_put; |
@@ -1420,9 +1474,9 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl | |||
1420 | { | 1474 | { |
1421 | struct socket *sock; | 1475 | struct socket *sock; |
1422 | char address[MAX_SOCK_ADDR]; | 1476 | char address[MAX_SOCK_ADDR]; |
1423 | int err; | 1477 | int err, fput_needed; |
1424 | 1478 | ||
1425 | sock = sockfd_lookup(fd, &err); | 1479 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1426 | if (!sock) | 1480 | if (!sock) |
1427 | goto out; | 1481 | goto out; |
1428 | err = move_addr_to_kernel(uservaddr, addrlen, address); | 1482 | err = move_addr_to_kernel(uservaddr, addrlen, address); |
@@ -1436,7 +1490,7 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl | |||
1436 | err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, | 1490 | err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, |
1437 | sock->file->f_flags); | 1491 | sock->file->f_flags); |
1438 | out_put: | 1492 | out_put: |
1439 | sockfd_put(sock); | 1493 | fput_light(sock->file, fput_needed); |
1440 | out: | 1494 | out: |
1441 | return err; | 1495 | return err; |
1442 | } | 1496 | } |
@@ -1450,9 +1504,9 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _ | |||
1450 | { | 1504 | { |
1451 | struct socket *sock; | 1505 | struct socket *sock; |
1452 | char address[MAX_SOCK_ADDR]; | 1506 | char address[MAX_SOCK_ADDR]; |
1453 | int len, err; | 1507 | int len, err, fput_needed; |
1454 | 1508 | ||
1455 | sock = sockfd_lookup(fd, &err); | 1509 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1456 | if (!sock) | 1510 | if (!sock) |
1457 | goto out; | 1511 | goto out; |
1458 | 1512 | ||
@@ -1466,7 +1520,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _ | |||
1466 | err = move_addr_to_user(address, len, usockaddr, usockaddr_len); | 1520 | err = move_addr_to_user(address, len, usockaddr, usockaddr_len); |
1467 | 1521 | ||
1468 | out_put: | 1522 | out_put: |
1469 | sockfd_put(sock); | 1523 | fput_light(sock->file, fput_needed); |
1470 | out: | 1524 | out: |
1471 | return err; | 1525 | return err; |
1472 | } | 1526 | } |
@@ -1480,20 +1534,19 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int _ | |||
1480 | { | 1534 | { |
1481 | struct socket *sock; | 1535 | struct socket *sock; |
1482 | char address[MAX_SOCK_ADDR]; | 1536 | char address[MAX_SOCK_ADDR]; |
1483 | int len, err; | 1537 | int len, err, fput_needed; |
1484 | 1538 | ||
1485 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1539 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { |
1486 | { | ||
1487 | err = security_socket_getpeername(sock); | 1540 | err = security_socket_getpeername(sock); |
1488 | if (err) { | 1541 | if (err) { |
1489 | sockfd_put(sock); | 1542 | fput_light(sock->file, fput_needed); |
1490 | return err; | 1543 | return err; |
1491 | } | 1544 | } |
1492 | 1545 | ||
1493 | err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); | 1546 | err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); |
1494 | if (!err) | 1547 | if (!err) |
1495 | err=move_addr_to_user(address,len, usockaddr, usockaddr_len); | 1548 | err=move_addr_to_user(address,len, usockaddr, usockaddr_len); |
1496 | sockfd_put(sock); | 1549 | fput_light(sock->file, fput_needed); |
1497 | } | 1550 | } |
1498 | return err; | 1551 | return err; |
1499 | } | 1552 | } |
@@ -1512,10 +1565,16 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag | |||
1512 | int err; | 1565 | int err; |
1513 | struct msghdr msg; | 1566 | struct msghdr msg; |
1514 | struct iovec iov; | 1567 | struct iovec iov; |
1515 | 1568 | int fput_needed; | |
1516 | sock = sockfd_lookup(fd, &err); | 1569 | struct file *sock_file; |
1570 | |||
1571 | sock_file = fget_light(fd, &fput_needed); | ||
1572 | if (!sock_file) | ||
1573 | return -EBADF; | ||
1574 | |||
1575 | sock = sock_from_file(sock_file, &err); | ||
1517 | if (!sock) | 1576 | if (!sock) |
1518 | goto out; | 1577 | goto out_put; |
1519 | iov.iov_base=buff; | 1578 | iov.iov_base=buff; |
1520 | iov.iov_len=len; | 1579 | iov.iov_len=len; |
1521 | msg.msg_name=NULL; | 1580 | msg.msg_name=NULL; |
@@ -1524,8 +1583,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag | |||
1524 | msg.msg_control=NULL; | 1583 | msg.msg_control=NULL; |
1525 | msg.msg_controllen=0; | 1584 | msg.msg_controllen=0; |
1526 | msg.msg_namelen=0; | 1585 | msg.msg_namelen=0; |
1527 | if(addr) | 1586 | if (addr) { |
1528 | { | ||
1529 | err = move_addr_to_kernel(addr, addr_len, address); | 1587 | err = move_addr_to_kernel(addr, addr_len, address); |
1530 | if (err < 0) | 1588 | if (err < 0) |
1531 | goto out_put; | 1589 | goto out_put; |
@@ -1538,8 +1596,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag | |||
1538 | err = sock_sendmsg(sock, &msg, len); | 1596 | err = sock_sendmsg(sock, &msg, len); |
1539 | 1597 | ||
1540 | out_put: | 1598 | out_put: |
1541 | sockfd_put(sock); | 1599 | fput_light(sock_file, fput_needed); |
1542 | out: | ||
1543 | return err; | 1600 | return err; |
1544 | } | 1601 | } |
1545 | 1602 | ||
@@ -1566,8 +1623,14 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f | |||
1566 | struct msghdr msg; | 1623 | struct msghdr msg; |
1567 | char address[MAX_SOCK_ADDR]; | 1624 | char address[MAX_SOCK_ADDR]; |
1568 | int err,err2; | 1625 | int err,err2; |
1626 | struct file *sock_file; | ||
1627 | int fput_needed; | ||
1628 | |||
1629 | sock_file = fget_light(fd, &fput_needed); | ||
1630 | if (!sock_file) | ||
1631 | return -EBADF; | ||
1569 | 1632 | ||
1570 | sock = sockfd_lookup(fd, &err); | 1633 | sock = sock_from_file(sock_file, &err); |
1571 | if (!sock) | 1634 | if (!sock) |
1572 | goto out; | 1635 | goto out; |
1573 | 1636 | ||
@@ -1589,8 +1652,8 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f | |||
1589 | if(err2<0) | 1652 | if(err2<0) |
1590 | err=err2; | 1653 | err=err2; |
1591 | } | 1654 | } |
1592 | sockfd_put(sock); | ||
1593 | out: | 1655 | out: |
1656 | fput_light(sock_file, fput_needed); | ||
1594 | return err; | 1657 | return err; |
1595 | } | 1658 | } |
1596 | 1659 | ||
@@ -1610,25 +1673,24 @@ asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags | |||
1610 | 1673 | ||
1611 | asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) | 1674 | asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) |
1612 | { | 1675 | { |
1613 | int err; | 1676 | int err, fput_needed; |
1614 | struct socket *sock; | 1677 | struct socket *sock; |
1615 | 1678 | ||
1616 | if (optlen < 0) | 1679 | if (optlen < 0) |
1617 | return -EINVAL; | 1680 | return -EINVAL; |
1618 | 1681 | ||
1619 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1682 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) |
1620 | { | 1683 | { |
1621 | err = security_socket_setsockopt(sock,level,optname); | 1684 | err = security_socket_setsockopt(sock,level,optname); |
1622 | if (err) { | 1685 | if (err) |
1623 | sockfd_put(sock); | 1686 | goto out_put; |
1624 | return err; | ||
1625 | } | ||
1626 | 1687 | ||
1627 | if (level == SOL_SOCKET) | 1688 | if (level == SOL_SOCKET) |
1628 | err=sock_setsockopt(sock,level,optname,optval,optlen); | 1689 | err=sock_setsockopt(sock,level,optname,optval,optlen); |
1629 | else | 1690 | else |
1630 | err=sock->ops->setsockopt(sock, level, optname, optval, optlen); | 1691 | err=sock->ops->setsockopt(sock, level, optname, optval, optlen); |
1631 | sockfd_put(sock); | 1692 | out_put: |
1693 | fput_light(sock->file, fput_needed); | ||
1632 | } | 1694 | } |
1633 | return err; | 1695 | return err; |
1634 | } | 1696 | } |
@@ -1640,23 +1702,20 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optv | |||
1640 | 1702 | ||
1641 | asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) | 1703 | asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) |
1642 | { | 1704 | { |
1643 | int err; | 1705 | int err, fput_needed; |
1644 | struct socket *sock; | 1706 | struct socket *sock; |
1645 | 1707 | ||
1646 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1708 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { |
1647 | { | 1709 | err = security_socket_getsockopt(sock, level, optname); |
1648 | err = security_socket_getsockopt(sock, level, | 1710 | if (err) |
1649 | optname); | 1711 | goto out_put; |
1650 | if (err) { | ||
1651 | sockfd_put(sock); | ||
1652 | return err; | ||
1653 | } | ||
1654 | 1712 | ||
1655 | if (level == SOL_SOCKET) | 1713 | if (level == SOL_SOCKET) |
1656 | err=sock_getsockopt(sock,level,optname,optval,optlen); | 1714 | err=sock_getsockopt(sock,level,optname,optval,optlen); |
1657 | else | 1715 | else |
1658 | err=sock->ops->getsockopt(sock, level, optname, optval, optlen); | 1716 | err=sock->ops->getsockopt(sock, level, optname, optval, optlen); |
1659 | sockfd_put(sock); | 1717 | out_put: |
1718 | fput_light(sock->file, fput_needed); | ||
1660 | } | 1719 | } |
1661 | return err; | 1720 | return err; |
1662 | } | 1721 | } |
@@ -1668,19 +1727,15 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optv | |||
1668 | 1727 | ||
1669 | asmlinkage long sys_shutdown(int fd, int how) | 1728 | asmlinkage long sys_shutdown(int fd, int how) |
1670 | { | 1729 | { |
1671 | int err; | 1730 | int err, fput_needed; |
1672 | struct socket *sock; | 1731 | struct socket *sock; |
1673 | 1732 | ||
1674 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1733 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL) |
1675 | { | 1734 | { |
1676 | err = security_socket_shutdown(sock, how); | 1735 | err = security_socket_shutdown(sock, how); |
1677 | if (err) { | 1736 | if (!err) |
1678 | sockfd_put(sock); | 1737 | err = sock->ops->shutdown(sock, how); |
1679 | return err; | 1738 | fput_light(sock->file, fput_needed); |
1680 | } | ||
1681 | |||
1682 | err=sock->ops->shutdown(sock, how); | ||
1683 | sockfd_put(sock); | ||
1684 | } | 1739 | } |
1685 | return err; | 1740 | return err; |
1686 | } | 1741 | } |
@@ -1709,6 +1764,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) | |||
1709 | unsigned char *ctl_buf = ctl; | 1764 | unsigned char *ctl_buf = ctl; |
1710 | struct msghdr msg_sys; | 1765 | struct msghdr msg_sys; |
1711 | int err, ctl_len, iov_size, total_len; | 1766 | int err, ctl_len, iov_size, total_len; |
1767 | int fput_needed; | ||
1712 | 1768 | ||
1713 | err = -EFAULT; | 1769 | err = -EFAULT; |
1714 | if (MSG_CMSG_COMPAT & flags) { | 1770 | if (MSG_CMSG_COMPAT & flags) { |
@@ -1717,7 +1773,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) | |||
1717 | } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) | 1773 | } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) |
1718 | return -EFAULT; | 1774 | return -EFAULT; |
1719 | 1775 | ||
1720 | sock = sockfd_lookup(fd, &err); | 1776 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1721 | if (!sock) | 1777 | if (!sock) |
1722 | goto out; | 1778 | goto out; |
1723 | 1779 | ||
@@ -1785,7 +1841,7 @@ out_freeiov: | |||
1785 | if (iov != iovstack) | 1841 | if (iov != iovstack) |
1786 | sock_kfree_s(sock->sk, iov, iov_size); | 1842 | sock_kfree_s(sock->sk, iov, iov_size); |
1787 | out_put: | 1843 | out_put: |
1788 | sockfd_put(sock); | 1844 | fput_light(sock->file, fput_needed); |
1789 | out: | 1845 | out: |
1790 | return err; | 1846 | return err; |
1791 | } | 1847 | } |
@@ -1803,6 +1859,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag | |||
1803 | struct msghdr msg_sys; | 1859 | struct msghdr msg_sys; |
1804 | unsigned long cmsg_ptr; | 1860 | unsigned long cmsg_ptr; |
1805 | int err, iov_size, total_len, len; | 1861 | int err, iov_size, total_len, len; |
1862 | int fput_needed; | ||
1806 | 1863 | ||
1807 | /* kernel mode address */ | 1864 | /* kernel mode address */ |
1808 | char addr[MAX_SOCK_ADDR]; | 1865 | char addr[MAX_SOCK_ADDR]; |
@@ -1818,7 +1875,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag | |||
1818 | if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) | 1875 | if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) |
1819 | return -EFAULT; | 1876 | return -EFAULT; |
1820 | 1877 | ||
1821 | sock = sockfd_lookup(fd, &err); | 1878 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1822 | if (!sock) | 1879 | if (!sock) |
1823 | goto out; | 1880 | goto out; |
1824 | 1881 | ||
@@ -1885,7 +1942,7 @@ out_freeiov: | |||
1885 | if (iov != iovstack) | 1942 | if (iov != iovstack) |
1886 | sock_kfree_s(sock->sk, iov, iov_size); | 1943 | sock_kfree_s(sock->sk, iov, iov_size); |
1887 | out_put: | 1944 | out_put: |
1888 | sockfd_put(sock); | 1945 | fput_light(sock->file, fput_needed); |
1889 | out: | 1946 | out: |
1890 | return err; | 1947 | return err; |
1891 | } | 1948 | } |
@@ -2086,6 +2143,20 @@ void socket_seq_show(struct seq_file *seq) | |||
2086 | } | 2143 | } |
2087 | #endif /* CONFIG_PROC_FS */ | 2144 | #endif /* CONFIG_PROC_FS */ |
2088 | 2145 | ||
2146 | #ifdef CONFIG_COMPAT | ||
2147 | static long compat_sock_ioctl(struct file *file, unsigned cmd, | ||
2148 | unsigned long arg) | ||
2149 | { | ||
2150 | struct socket *sock = file->private_data; | ||
2151 | int ret = -ENOIOCTLCMD; | ||
2152 | |||
2153 | if (sock->ops->compat_ioctl) | ||
2154 | ret = sock->ops->compat_ioctl(sock, cmd, arg); | ||
2155 | |||
2156 | return ret; | ||
2157 | } | ||
2158 | #endif | ||
2159 | |||
2089 | /* ABI emulation layers need these two */ | 2160 | /* ABI emulation layers need these two */ |
2090 | EXPORT_SYMBOL(move_addr_to_kernel); | 2161 | EXPORT_SYMBOL(move_addr_to_kernel); |
2091 | EXPORT_SYMBOL(move_addr_to_user); | 2162 | EXPORT_SYMBOL(move_addr_to_user); |