diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 332 |
1 files changed, 191 insertions, 141 deletions
diff --git a/net/socket.c b/net/socket.c index 7e1bdef8b09e..e3c21d5ec288 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> |
@@ -348,8 +349,8 @@ static struct dentry_operations sockfs_dentry_operations = { | |||
348 | /* | 349 | /* |
349 | * Obtains the first available file descriptor and sets it up for use. | 350 | * Obtains the first available file descriptor and sets it up for use. |
350 | * | 351 | * |
351 | * This function creates file structure and maps it to fd space | 352 | * These functions create file structures and maps them to fd space |
352 | * of current process. On success it returns file descriptor | 353 | * of the current process. On success it returns file descriptor |
353 | * and file struct implicitly stored in sock->file. | 354 | * and file struct implicitly stored in sock->file. |
354 | * Note that another thread may close file descriptor before we return | 355 | * 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 | 356 | * from this function. We use the fact that now we do not refer |
@@ -362,53 +363,90 @@ static struct dentry_operations sockfs_dentry_operations = { | |||
362 | * but we take care of internal coherence yet. | 363 | * but we take care of internal coherence yet. |
363 | */ | 364 | */ |
364 | 365 | ||
365 | int sock_map_fd(struct socket *sock) | 366 | static int sock_alloc_fd(struct file **filep) |
366 | { | 367 | { |
367 | int fd; | 368 | 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 | 369 | ||
375 | fd = get_unused_fd(); | 370 | fd = get_unused_fd(); |
376 | if (fd >= 0) { | 371 | if (likely(fd >= 0)) { |
377 | struct file *file = get_empty_filp(); | 372 | struct file *file = get_empty_filp(); |
378 | 373 | ||
379 | if (!file) { | 374 | *filep = file; |
375 | if (unlikely(!file)) { | ||
380 | put_unused_fd(fd); | 376 | put_unused_fd(fd); |
381 | fd = -ENFILE; | 377 | return -ENFILE; |
382 | goto out; | ||
383 | } | 378 | } |
379 | } else | ||
380 | *filep = NULL; | ||
381 | return fd; | ||
382 | } | ||
383 | |||
384 | static int sock_attach_fd(struct socket *sock, struct file *file) | ||
385 | { | ||
386 | struct qstr this; | ||
387 | char name[32]; | ||
388 | |||
389 | this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); | ||
390 | this.name = name; | ||
391 | this.hash = SOCK_INODE(sock)->i_ino; | ||
384 | 392 | ||
385 | this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino); | 393 | file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); |
386 | this.name = name; | 394 | if (unlikely(!file->f_dentry)) |
387 | this.hash = SOCK_INODE(sock)->i_ino; | 395 | return -ENOMEM; |
396 | |||
397 | file->f_dentry->d_op = &sockfs_dentry_operations; | ||
398 | d_add(file->f_dentry, SOCK_INODE(sock)); | ||
399 | file->f_vfsmnt = mntget(sock_mnt); | ||
400 | file->f_mapping = file->f_dentry->d_inode->i_mapping; | ||
401 | |||
402 | sock->file = file; | ||
403 | file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; | ||
404 | file->f_mode = FMODE_READ | FMODE_WRITE; | ||
405 | file->f_flags = O_RDWR; | ||
406 | file->f_pos = 0; | ||
407 | file->private_data = sock; | ||
408 | |||
409 | return 0; | ||
410 | } | ||
388 | 411 | ||
389 | file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); | 412 | int sock_map_fd(struct socket *sock) |
390 | if (!file->f_dentry) { | 413 | { |
391 | put_filp(file); | 414 | struct file *newfile; |
415 | int fd = sock_alloc_fd(&newfile); | ||
416 | |||
417 | if (likely(fd >= 0)) { | ||
418 | int err = sock_attach_fd(sock, newfile); | ||
419 | |||
420 | if (unlikely(err < 0)) { | ||
421 | put_filp(newfile); | ||
392 | put_unused_fd(fd); | 422 | put_unused_fd(fd); |
393 | fd = -ENOMEM; | 423 | return err; |
394 | goto out; | ||
395 | } | 424 | } |
396 | file->f_dentry->d_op = &sockfs_dentry_operations; | 425 | fd_install(fd, newfile); |
397 | d_add(file->f_dentry, SOCK_INODE(sock)); | 426 | } |
398 | file->f_vfsmnt = mntget(sock_mnt); | 427 | return fd; |
399 | file->f_mapping = file->f_dentry->d_inode->i_mapping; | 428 | } |
400 | 429 | ||
401 | sock->file = file; | 430 | static struct socket *sock_from_file(struct file *file, int *err) |
402 | file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops; | 431 | { |
403 | file->f_mode = FMODE_READ | FMODE_WRITE; | 432 | struct inode *inode; |
404 | file->f_flags = O_RDWR; | 433 | struct socket *sock; |
405 | file->f_pos = 0; | 434 | |
406 | file->private_data = sock; | 435 | if (file->f_op == &socket_file_ops) |
407 | fd_install(fd, file); | 436 | return file->private_data; /* set in sock_map_fd */ |
437 | |||
438 | inode = file->f_dentry->d_inode; | ||
439 | if (!S_ISSOCK(inode->i_mode)) { | ||
440 | *err = -ENOTSOCK; | ||
441 | return NULL; | ||
408 | } | 442 | } |
409 | 443 | ||
410 | out: | 444 | sock = SOCKET_I(inode); |
411 | return fd; | 445 | if (sock->file != file) { |
446 | printk(KERN_ERR "socki_lookup: socket file changed!\n"); | ||
447 | sock->file = file; | ||
448 | } | ||
449 | return sock; | ||
412 | } | 450 | } |
413 | 451 | ||
414 | /** | 452 | /** |
@@ -427,31 +465,31 @@ out: | |||
427 | struct socket *sockfd_lookup(int fd, int *err) | 465 | struct socket *sockfd_lookup(int fd, int *err) |
428 | { | 466 | { |
429 | struct file *file; | 467 | struct file *file; |
430 | struct inode *inode; | ||
431 | struct socket *sock; | 468 | struct socket *sock; |
432 | 469 | ||
433 | if (!(file = fget(fd))) | 470 | if (!(file = fget(fd))) { |
434 | { | ||
435 | *err = -EBADF; | 471 | *err = -EBADF; |
436 | return NULL; | 472 | return NULL; |
437 | } | 473 | } |
438 | 474 | sock = sock_from_file(file, err); | |
439 | if (file->f_op == &socket_file_ops) | 475 | 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); | 476 | fput(file); |
446 | return NULL; | 477 | return sock; |
447 | } | 478 | } |
448 | 479 | ||
449 | sock = SOCKET_I(inode); | 480 | static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) |
450 | if (sock->file != file) { | 481 | { |
451 | printk(KERN_ERR "socki_lookup: socket file changed!\n"); | 482 | struct file *file; |
452 | sock->file = file; | 483 | struct socket *sock; |
484 | |||
485 | file = fget_light(fd, fput_needed); | ||
486 | if (file) { | ||
487 | sock = sock_from_file(file, err); | ||
488 | if (sock) | ||
489 | return sock; | ||
490 | fput_light(file, *fput_needed); | ||
453 | } | 491 | } |
454 | return sock; | 492 | return NULL; |
455 | } | 493 | } |
456 | 494 | ||
457 | /** | 495 | /** |
@@ -789,36 +827,36 @@ static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, | |||
789 | * with module unload. | 827 | * with module unload. |
790 | */ | 828 | */ |
791 | 829 | ||
792 | static DECLARE_MUTEX(br_ioctl_mutex); | 830 | static DEFINE_MUTEX(br_ioctl_mutex); |
793 | static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; | 831 | static int (*br_ioctl_hook)(unsigned int cmd, void __user *arg) = NULL; |
794 | 832 | ||
795 | void brioctl_set(int (*hook)(unsigned int, void __user *)) | 833 | void brioctl_set(int (*hook)(unsigned int, void __user *)) |
796 | { | 834 | { |
797 | down(&br_ioctl_mutex); | 835 | mutex_lock(&br_ioctl_mutex); |
798 | br_ioctl_hook = hook; | 836 | br_ioctl_hook = hook; |
799 | up(&br_ioctl_mutex); | 837 | mutex_unlock(&br_ioctl_mutex); |
800 | } | 838 | } |
801 | EXPORT_SYMBOL(brioctl_set); | 839 | EXPORT_SYMBOL(brioctl_set); |
802 | 840 | ||
803 | static DECLARE_MUTEX(vlan_ioctl_mutex); | 841 | static DEFINE_MUTEX(vlan_ioctl_mutex); |
804 | static int (*vlan_ioctl_hook)(void __user *arg); | 842 | static int (*vlan_ioctl_hook)(void __user *arg); |
805 | 843 | ||
806 | void vlan_ioctl_set(int (*hook)(void __user *)) | 844 | void vlan_ioctl_set(int (*hook)(void __user *)) |
807 | { | 845 | { |
808 | down(&vlan_ioctl_mutex); | 846 | mutex_lock(&vlan_ioctl_mutex); |
809 | vlan_ioctl_hook = hook; | 847 | vlan_ioctl_hook = hook; |
810 | up(&vlan_ioctl_mutex); | 848 | mutex_unlock(&vlan_ioctl_mutex); |
811 | } | 849 | } |
812 | EXPORT_SYMBOL(vlan_ioctl_set); | 850 | EXPORT_SYMBOL(vlan_ioctl_set); |
813 | 851 | ||
814 | static DECLARE_MUTEX(dlci_ioctl_mutex); | 852 | static DEFINE_MUTEX(dlci_ioctl_mutex); |
815 | static int (*dlci_ioctl_hook)(unsigned int, void __user *); | 853 | static int (*dlci_ioctl_hook)(unsigned int, void __user *); |
816 | 854 | ||
817 | void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) | 855 | void dlci_ioctl_set(int (*hook)(unsigned int, void __user *)) |
818 | { | 856 | { |
819 | down(&dlci_ioctl_mutex); | 857 | mutex_lock(&dlci_ioctl_mutex); |
820 | dlci_ioctl_hook = hook; | 858 | dlci_ioctl_hook = hook; |
821 | up(&dlci_ioctl_mutex); | 859 | mutex_unlock(&dlci_ioctl_mutex); |
822 | } | 860 | } |
823 | EXPORT_SYMBOL(dlci_ioctl_set); | 861 | EXPORT_SYMBOL(dlci_ioctl_set); |
824 | 862 | ||
@@ -862,10 +900,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
862 | if (!br_ioctl_hook) | 900 | if (!br_ioctl_hook) |
863 | request_module("bridge"); | 901 | request_module("bridge"); |
864 | 902 | ||
865 | down(&br_ioctl_mutex); | 903 | mutex_lock(&br_ioctl_mutex); |
866 | if (br_ioctl_hook) | 904 | if (br_ioctl_hook) |
867 | err = br_ioctl_hook(cmd, argp); | 905 | err = br_ioctl_hook(cmd, argp); |
868 | up(&br_ioctl_mutex); | 906 | mutex_unlock(&br_ioctl_mutex); |
869 | break; | 907 | break; |
870 | case SIOCGIFVLAN: | 908 | case SIOCGIFVLAN: |
871 | case SIOCSIFVLAN: | 909 | case SIOCSIFVLAN: |
@@ -873,10 +911,10 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
873 | if (!vlan_ioctl_hook) | 911 | if (!vlan_ioctl_hook) |
874 | request_module("8021q"); | 912 | request_module("8021q"); |
875 | 913 | ||
876 | down(&vlan_ioctl_mutex); | 914 | mutex_lock(&vlan_ioctl_mutex); |
877 | if (vlan_ioctl_hook) | 915 | if (vlan_ioctl_hook) |
878 | err = vlan_ioctl_hook(argp); | 916 | err = vlan_ioctl_hook(argp); |
879 | up(&vlan_ioctl_mutex); | 917 | mutex_unlock(&vlan_ioctl_mutex); |
880 | break; | 918 | break; |
881 | case SIOCGIFDIVERT: | 919 | case SIOCGIFDIVERT: |
882 | case SIOCSIFDIVERT: | 920 | case SIOCSIFDIVERT: |
@@ -890,9 +928,9 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
890 | request_module("dlci"); | 928 | request_module("dlci"); |
891 | 929 | ||
892 | if (dlci_ioctl_hook) { | 930 | if (dlci_ioctl_hook) { |
893 | down(&dlci_ioctl_mutex); | 931 | mutex_lock(&dlci_ioctl_mutex); |
894 | err = dlci_ioctl_hook(cmd, argp); | 932 | err = dlci_ioctl_hook(cmd, argp); |
895 | up(&dlci_ioctl_mutex); | 933 | mutex_unlock(&dlci_ioctl_mutex); |
896 | } | 934 | } |
897 | break; | 935 | break; |
898 | default: | 936 | default: |
@@ -1286,19 +1324,17 @@ asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen) | |||
1286 | { | 1324 | { |
1287 | struct socket *sock; | 1325 | struct socket *sock; |
1288 | char address[MAX_SOCK_ADDR]; | 1326 | char address[MAX_SOCK_ADDR]; |
1289 | int err; | 1327 | int err, fput_needed; |
1290 | 1328 | ||
1291 | if((sock = sockfd_lookup(fd,&err))!=NULL) | 1329 | if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL) |
1292 | { | 1330 | { |
1293 | if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { | 1331 | if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { |
1294 | err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); | 1332 | err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); |
1295 | if (err) { | 1333 | if (!err) |
1296 | sockfd_put(sock); | 1334 | err = sock->ops->bind(sock, |
1297 | return err; | 1335 | (struct sockaddr *)address, addrlen); |
1298 | } | ||
1299 | err = sock->ops->bind(sock, (struct sockaddr *)address, addrlen); | ||
1300 | } | 1336 | } |
1301 | sockfd_put(sock); | 1337 | fput_light(sock->file, fput_needed); |
1302 | } | 1338 | } |
1303 | return err; | 1339 | return err; |
1304 | } | 1340 | } |
@@ -1315,20 +1351,17 @@ int sysctl_somaxconn = SOMAXCONN; | |||
1315 | asmlinkage long sys_listen(int fd, int backlog) | 1351 | asmlinkage long sys_listen(int fd, int backlog) |
1316 | { | 1352 | { |
1317 | struct socket *sock; | 1353 | struct socket *sock; |
1318 | int err; | 1354 | int err, fput_needed; |
1319 | 1355 | ||
1320 | if ((sock = sockfd_lookup(fd, &err)) != NULL) { | 1356 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { |
1321 | if ((unsigned) backlog > sysctl_somaxconn) | 1357 | if ((unsigned) backlog > sysctl_somaxconn) |
1322 | backlog = sysctl_somaxconn; | 1358 | backlog = sysctl_somaxconn; |
1323 | 1359 | ||
1324 | err = security_socket_listen(sock, backlog); | 1360 | err = security_socket_listen(sock, backlog); |
1325 | if (err) { | 1361 | if (!err) |
1326 | sockfd_put(sock); | 1362 | err = sock->ops->listen(sock, backlog); |
1327 | return err; | ||
1328 | } | ||
1329 | 1363 | ||
1330 | err=sock->ops->listen(sock, backlog); | 1364 | fput_light(sock->file, fput_needed); |
1331 | sockfd_put(sock); | ||
1332 | } | 1365 | } |
1333 | return err; | 1366 | return err; |
1334 | } | 1367 | } |
@@ -1349,10 +1382,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) | 1382 | asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int __user *upeer_addrlen) |
1350 | { | 1383 | { |
1351 | struct socket *sock, *newsock; | 1384 | struct socket *sock, *newsock; |
1352 | int err, len; | 1385 | struct file *newfile; |
1386 | int err, len, newfd, fput_needed; | ||
1353 | char address[MAX_SOCK_ADDR]; | 1387 | char address[MAX_SOCK_ADDR]; |
1354 | 1388 | ||
1355 | sock = sockfd_lookup(fd, &err); | 1389 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1356 | if (!sock) | 1390 | if (!sock) |
1357 | goto out; | 1391 | goto out; |
1358 | 1392 | ||
@@ -1369,35 +1403,48 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr, int _ | |||
1369 | */ | 1403 | */ |
1370 | __module_get(newsock->ops->owner); | 1404 | __module_get(newsock->ops->owner); |
1371 | 1405 | ||
1406 | newfd = sock_alloc_fd(&newfile); | ||
1407 | if (unlikely(newfd < 0)) { | ||
1408 | err = newfd; | ||
1409 | goto out_release; | ||
1410 | } | ||
1411 | |||
1412 | err = sock_attach_fd(newsock, newfile); | ||
1413 | if (err < 0) | ||
1414 | goto out_fd; | ||
1415 | |||
1372 | err = security_socket_accept(sock, newsock); | 1416 | err = security_socket_accept(sock, newsock); |
1373 | if (err) | 1417 | if (err) |
1374 | goto out_release; | 1418 | goto out_fd; |
1375 | 1419 | ||
1376 | err = sock->ops->accept(sock, newsock, sock->file->f_flags); | 1420 | err = sock->ops->accept(sock, newsock, sock->file->f_flags); |
1377 | if (err < 0) | 1421 | if (err < 0) |
1378 | goto out_release; | 1422 | goto out_fd; |
1379 | 1423 | ||
1380 | if (upeer_sockaddr) { | 1424 | if (upeer_sockaddr) { |
1381 | if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { | 1425 | if(newsock->ops->getname(newsock, (struct sockaddr *)address, &len, 2)<0) { |
1382 | err = -ECONNABORTED; | 1426 | err = -ECONNABORTED; |
1383 | goto out_release; | 1427 | goto out_fd; |
1384 | } | 1428 | } |
1385 | err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); | 1429 | err = move_addr_to_user(address, len, upeer_sockaddr, upeer_addrlen); |
1386 | if (err < 0) | 1430 | if (err < 0) |
1387 | goto out_release; | 1431 | goto out_fd; |
1388 | } | 1432 | } |
1389 | 1433 | ||
1390 | /* File flags are not inherited via accept() unlike another OSes. */ | 1434 | /* File flags are not inherited via accept() unlike another OSes. */ |
1391 | 1435 | ||
1392 | if ((err = sock_map_fd(newsock)) < 0) | 1436 | fd_install(newfd, newfile); |
1393 | goto out_release; | 1437 | err = newfd; |
1394 | 1438 | ||
1395 | security_socket_post_accept(sock, newsock); | 1439 | security_socket_post_accept(sock, newsock); |
1396 | 1440 | ||
1397 | out_put: | 1441 | out_put: |
1398 | sockfd_put(sock); | 1442 | fput_light(sock->file, fput_needed); |
1399 | out: | 1443 | out: |
1400 | return err; | 1444 | return err; |
1445 | out_fd: | ||
1446 | put_filp(newfile); | ||
1447 | put_unused_fd(newfd); | ||
1401 | out_release: | 1448 | out_release: |
1402 | sock_release(newsock); | 1449 | sock_release(newsock); |
1403 | goto out_put; | 1450 | goto out_put; |
@@ -1420,9 +1467,9 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl | |||
1420 | { | 1467 | { |
1421 | struct socket *sock; | 1468 | struct socket *sock; |
1422 | char address[MAX_SOCK_ADDR]; | 1469 | char address[MAX_SOCK_ADDR]; |
1423 | int err; | 1470 | int err, fput_needed; |
1424 | 1471 | ||
1425 | sock = sockfd_lookup(fd, &err); | 1472 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1426 | if (!sock) | 1473 | if (!sock) |
1427 | goto out; | 1474 | goto out; |
1428 | err = move_addr_to_kernel(uservaddr, addrlen, address); | 1475 | err = move_addr_to_kernel(uservaddr, addrlen, address); |
@@ -1436,7 +1483,7 @@ asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr, int addrl | |||
1436 | err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, | 1483 | err = sock->ops->connect(sock, (struct sockaddr *) address, addrlen, |
1437 | sock->file->f_flags); | 1484 | sock->file->f_flags); |
1438 | out_put: | 1485 | out_put: |
1439 | sockfd_put(sock); | 1486 | fput_light(sock->file, fput_needed); |
1440 | out: | 1487 | out: |
1441 | return err; | 1488 | return err; |
1442 | } | 1489 | } |
@@ -1450,9 +1497,9 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _ | |||
1450 | { | 1497 | { |
1451 | struct socket *sock; | 1498 | struct socket *sock; |
1452 | char address[MAX_SOCK_ADDR]; | 1499 | char address[MAX_SOCK_ADDR]; |
1453 | int len, err; | 1500 | int len, err, fput_needed; |
1454 | 1501 | ||
1455 | sock = sockfd_lookup(fd, &err); | 1502 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1456 | if (!sock) | 1503 | if (!sock) |
1457 | goto out; | 1504 | goto out; |
1458 | 1505 | ||
@@ -1466,7 +1513,7 @@ asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr, int _ | |||
1466 | err = move_addr_to_user(address, len, usockaddr, usockaddr_len); | 1513 | err = move_addr_to_user(address, len, usockaddr, usockaddr_len); |
1467 | 1514 | ||
1468 | out_put: | 1515 | out_put: |
1469 | sockfd_put(sock); | 1516 | fput_light(sock->file, fput_needed); |
1470 | out: | 1517 | out: |
1471 | return err; | 1518 | return err; |
1472 | } | 1519 | } |
@@ -1480,20 +1527,19 @@ asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr, int _ | |||
1480 | { | 1527 | { |
1481 | struct socket *sock; | 1528 | struct socket *sock; |
1482 | char address[MAX_SOCK_ADDR]; | 1529 | char address[MAX_SOCK_ADDR]; |
1483 | int len, err; | 1530 | int len, err, fput_needed; |
1484 | 1531 | ||
1485 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1532 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { |
1486 | { | ||
1487 | err = security_socket_getpeername(sock); | 1533 | err = security_socket_getpeername(sock); |
1488 | if (err) { | 1534 | if (err) { |
1489 | sockfd_put(sock); | 1535 | fput_light(sock->file, fput_needed); |
1490 | return err; | 1536 | return err; |
1491 | } | 1537 | } |
1492 | 1538 | ||
1493 | err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); | 1539 | err = sock->ops->getname(sock, (struct sockaddr *)address, &len, 1); |
1494 | if (!err) | 1540 | if (!err) |
1495 | err=move_addr_to_user(address,len, usockaddr, usockaddr_len); | 1541 | err=move_addr_to_user(address,len, usockaddr, usockaddr_len); |
1496 | sockfd_put(sock); | 1542 | fput_light(sock->file, fput_needed); |
1497 | } | 1543 | } |
1498 | return err; | 1544 | return err; |
1499 | } | 1545 | } |
@@ -1512,10 +1558,16 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag | |||
1512 | int err; | 1558 | int err; |
1513 | struct msghdr msg; | 1559 | struct msghdr msg; |
1514 | struct iovec iov; | 1560 | struct iovec iov; |
1515 | 1561 | int fput_needed; | |
1516 | sock = sockfd_lookup(fd, &err); | 1562 | struct file *sock_file; |
1563 | |||
1564 | sock_file = fget_light(fd, &fput_needed); | ||
1565 | if (!sock_file) | ||
1566 | return -EBADF; | ||
1567 | |||
1568 | sock = sock_from_file(sock_file, &err); | ||
1517 | if (!sock) | 1569 | if (!sock) |
1518 | goto out; | 1570 | goto out_put; |
1519 | iov.iov_base=buff; | 1571 | iov.iov_base=buff; |
1520 | iov.iov_len=len; | 1572 | iov.iov_len=len; |
1521 | msg.msg_name=NULL; | 1573 | msg.msg_name=NULL; |
@@ -1524,8 +1576,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag | |||
1524 | msg.msg_control=NULL; | 1576 | msg.msg_control=NULL; |
1525 | msg.msg_controllen=0; | 1577 | msg.msg_controllen=0; |
1526 | msg.msg_namelen=0; | 1578 | msg.msg_namelen=0; |
1527 | if(addr) | 1579 | if (addr) { |
1528 | { | ||
1529 | err = move_addr_to_kernel(addr, addr_len, address); | 1580 | err = move_addr_to_kernel(addr, addr_len, address); |
1530 | if (err < 0) | 1581 | if (err < 0) |
1531 | goto out_put; | 1582 | goto out_put; |
@@ -1538,8 +1589,7 @@ asmlinkage long sys_sendto(int fd, void __user * buff, size_t len, unsigned flag | |||
1538 | err = sock_sendmsg(sock, &msg, len); | 1589 | err = sock_sendmsg(sock, &msg, len); |
1539 | 1590 | ||
1540 | out_put: | 1591 | out_put: |
1541 | sockfd_put(sock); | 1592 | fput_light(sock_file, fput_needed); |
1542 | out: | ||
1543 | return err; | 1593 | return err; |
1544 | } | 1594 | } |
1545 | 1595 | ||
@@ -1566,8 +1616,14 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f | |||
1566 | struct msghdr msg; | 1616 | struct msghdr msg; |
1567 | char address[MAX_SOCK_ADDR]; | 1617 | char address[MAX_SOCK_ADDR]; |
1568 | int err,err2; | 1618 | int err,err2; |
1619 | struct file *sock_file; | ||
1620 | int fput_needed; | ||
1569 | 1621 | ||
1570 | sock = sockfd_lookup(fd, &err); | 1622 | sock_file = fget_light(fd, &fput_needed); |
1623 | if (!sock_file) | ||
1624 | return -EBADF; | ||
1625 | |||
1626 | sock = sock_from_file(sock_file, &err); | ||
1571 | if (!sock) | 1627 | if (!sock) |
1572 | goto out; | 1628 | goto out; |
1573 | 1629 | ||
@@ -1589,8 +1645,8 @@ asmlinkage long sys_recvfrom(int fd, void __user * ubuf, size_t size, unsigned f | |||
1589 | if(err2<0) | 1645 | if(err2<0) |
1590 | err=err2; | 1646 | err=err2; |
1591 | } | 1647 | } |
1592 | sockfd_put(sock); | ||
1593 | out: | 1648 | out: |
1649 | fput_light(sock_file, fput_needed); | ||
1594 | return err; | 1650 | return err; |
1595 | } | 1651 | } |
1596 | 1652 | ||
@@ -1610,25 +1666,24 @@ asmlinkage long sys_recv(int fd, void __user * ubuf, size_t size, unsigned flags | |||
1610 | 1666 | ||
1611 | asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) | 1667 | asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optval, int optlen) |
1612 | { | 1668 | { |
1613 | int err; | 1669 | int err, fput_needed; |
1614 | struct socket *sock; | 1670 | struct socket *sock; |
1615 | 1671 | ||
1616 | if (optlen < 0) | 1672 | if (optlen < 0) |
1617 | return -EINVAL; | 1673 | return -EINVAL; |
1618 | 1674 | ||
1619 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1675 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) |
1620 | { | 1676 | { |
1621 | err = security_socket_setsockopt(sock,level,optname); | 1677 | err = security_socket_setsockopt(sock,level,optname); |
1622 | if (err) { | 1678 | if (err) |
1623 | sockfd_put(sock); | 1679 | goto out_put; |
1624 | return err; | ||
1625 | } | ||
1626 | 1680 | ||
1627 | if (level == SOL_SOCKET) | 1681 | if (level == SOL_SOCKET) |
1628 | err=sock_setsockopt(sock,level,optname,optval,optlen); | 1682 | err=sock_setsockopt(sock,level,optname,optval,optlen); |
1629 | else | 1683 | else |
1630 | err=sock->ops->setsockopt(sock, level, optname, optval, optlen); | 1684 | err=sock->ops->setsockopt(sock, level, optname, optval, optlen); |
1631 | sockfd_put(sock); | 1685 | out_put: |
1686 | fput_light(sock->file, fput_needed); | ||
1632 | } | 1687 | } |
1633 | return err; | 1688 | return err; |
1634 | } | 1689 | } |
@@ -1640,23 +1695,20 @@ asmlinkage long sys_setsockopt(int fd, int level, int optname, char __user *optv | |||
1640 | 1695 | ||
1641 | asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) | 1696 | asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optval, int __user *optlen) |
1642 | { | 1697 | { |
1643 | int err; | 1698 | int err, fput_needed; |
1644 | struct socket *sock; | 1699 | struct socket *sock; |
1645 | 1700 | ||
1646 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1701 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed)) != NULL) { |
1647 | { | 1702 | err = security_socket_getsockopt(sock, level, optname); |
1648 | err = security_socket_getsockopt(sock, level, | 1703 | if (err) |
1649 | optname); | 1704 | goto out_put; |
1650 | if (err) { | ||
1651 | sockfd_put(sock); | ||
1652 | return err; | ||
1653 | } | ||
1654 | 1705 | ||
1655 | if (level == SOL_SOCKET) | 1706 | if (level == SOL_SOCKET) |
1656 | err=sock_getsockopt(sock,level,optname,optval,optlen); | 1707 | err=sock_getsockopt(sock,level,optname,optval,optlen); |
1657 | else | 1708 | else |
1658 | err=sock->ops->getsockopt(sock, level, optname, optval, optlen); | 1709 | err=sock->ops->getsockopt(sock, level, optname, optval, optlen); |
1659 | sockfd_put(sock); | 1710 | out_put: |
1711 | fput_light(sock->file, fput_needed); | ||
1660 | } | 1712 | } |
1661 | return err; | 1713 | return err; |
1662 | } | 1714 | } |
@@ -1668,19 +1720,15 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, char __user *optv | |||
1668 | 1720 | ||
1669 | asmlinkage long sys_shutdown(int fd, int how) | 1721 | asmlinkage long sys_shutdown(int fd, int how) |
1670 | { | 1722 | { |
1671 | int err; | 1723 | int err, fput_needed; |
1672 | struct socket *sock; | 1724 | struct socket *sock; |
1673 | 1725 | ||
1674 | if ((sock = sockfd_lookup(fd, &err))!=NULL) | 1726 | if ((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL) |
1675 | { | 1727 | { |
1676 | err = security_socket_shutdown(sock, how); | 1728 | err = security_socket_shutdown(sock, how); |
1677 | if (err) { | 1729 | if (!err) |
1678 | sockfd_put(sock); | 1730 | err = sock->ops->shutdown(sock, how); |
1679 | return err; | 1731 | fput_light(sock->file, fput_needed); |
1680 | } | ||
1681 | |||
1682 | err=sock->ops->shutdown(sock, how); | ||
1683 | sockfd_put(sock); | ||
1684 | } | 1732 | } |
1685 | return err; | 1733 | return err; |
1686 | } | 1734 | } |
@@ -1709,6 +1757,7 @@ asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) | |||
1709 | unsigned char *ctl_buf = ctl; | 1757 | unsigned char *ctl_buf = ctl; |
1710 | struct msghdr msg_sys; | 1758 | struct msghdr msg_sys; |
1711 | int err, ctl_len, iov_size, total_len; | 1759 | int err, ctl_len, iov_size, total_len; |
1760 | int fput_needed; | ||
1712 | 1761 | ||
1713 | err = -EFAULT; | 1762 | err = -EFAULT; |
1714 | if (MSG_CMSG_COMPAT & flags) { | 1763 | if (MSG_CMSG_COMPAT & flags) { |
@@ -1717,7 +1766,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))) | 1766 | } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) |
1718 | return -EFAULT; | 1767 | return -EFAULT; |
1719 | 1768 | ||
1720 | sock = sockfd_lookup(fd, &err); | 1769 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1721 | if (!sock) | 1770 | if (!sock) |
1722 | goto out; | 1771 | goto out; |
1723 | 1772 | ||
@@ -1785,7 +1834,7 @@ out_freeiov: | |||
1785 | if (iov != iovstack) | 1834 | if (iov != iovstack) |
1786 | sock_kfree_s(sock->sk, iov, iov_size); | 1835 | sock_kfree_s(sock->sk, iov, iov_size); |
1787 | out_put: | 1836 | out_put: |
1788 | sockfd_put(sock); | 1837 | fput_light(sock->file, fput_needed); |
1789 | out: | 1838 | out: |
1790 | return err; | 1839 | return err; |
1791 | } | 1840 | } |
@@ -1803,6 +1852,7 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg, unsigned int flag | |||
1803 | struct msghdr msg_sys; | 1852 | struct msghdr msg_sys; |
1804 | unsigned long cmsg_ptr; | 1853 | unsigned long cmsg_ptr; |
1805 | int err, iov_size, total_len, len; | 1854 | int err, iov_size, total_len, len; |
1855 | int fput_needed; | ||
1806 | 1856 | ||
1807 | /* kernel mode address */ | 1857 | /* kernel mode address */ |
1808 | char addr[MAX_SOCK_ADDR]; | 1858 | char addr[MAX_SOCK_ADDR]; |
@@ -1818,7 +1868,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))) | 1868 | if (copy_from_user(&msg_sys,msg,sizeof(struct msghdr))) |
1819 | return -EFAULT; | 1869 | return -EFAULT; |
1820 | 1870 | ||
1821 | sock = sockfd_lookup(fd, &err); | 1871 | sock = sockfd_lookup_light(fd, &err, &fput_needed); |
1822 | if (!sock) | 1872 | if (!sock) |
1823 | goto out; | 1873 | goto out; |
1824 | 1874 | ||
@@ -1885,7 +1935,7 @@ out_freeiov: | |||
1885 | if (iov != iovstack) | 1935 | if (iov != iovstack) |
1886 | sock_kfree_s(sock->sk, iov, iov_size); | 1936 | sock_kfree_s(sock->sk, iov, iov_size); |
1887 | out_put: | 1937 | out_put: |
1888 | sockfd_put(sock); | 1938 | fput_light(sock->file, fput_needed); |
1889 | out: | 1939 | out: |
1890 | return err; | 1940 | return err; |
1891 | } | 1941 | } |