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