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