diff options
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 367 |
1 files changed, 218 insertions, 149 deletions
diff --git a/net/socket.c b/net/socket.c index a00851f981db..fcd77eac0ccf 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 | /** |
@@ -496,7 +539,7 @@ static int sock_no_open(struct inode *irrelevant, struct file *dontcare) | |||
496 | return -ENXIO; | 539 | return -ENXIO; |
497 | } | 540 | } |
498 | 541 | ||
499 | struct file_operations bad_sock_fops = { | 542 | const struct file_operations bad_sock_fops = { |
500 | .owner = THIS_MODULE, | 543 | .owner = THIS_MODULE, |
501 | .open = sock_no_open, | 544 | .open = sock_no_open, |
502 | }; | 545 | }; |
@@ -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); |