diff options
| -rw-r--r-- | include/asm-alpha/socket.h | 5 | ||||
| -rw-r--r-- | include/asm-parisc/socket.h | 5 | ||||
| -rw-r--r-- | include/asm-x86/unistd_64.h | 2 | ||||
| -rw-r--r-- | include/linux/net.h | 3 | ||||
| -rw-r--r-- | include/linux/syscalls.h | 2 | ||||
| -rw-r--r-- | kernel/sys_ni.c | 1 | ||||
| -rw-r--r-- | net/compat.c | 52 | ||||
| -rw-r--r-- | net/socket.c | 81 |
8 files changed, 139 insertions, 12 deletions
diff --git a/include/asm-alpha/socket.h b/include/asm-alpha/socket.h index 08c979319929..a1057c2d95e7 100644 --- a/include/asm-alpha/socket.h +++ b/include/asm-alpha/socket.h | |||
| @@ -62,4 +62,9 @@ | |||
| 62 | 62 | ||
| 63 | #define SO_MARK 36 | 63 | #define SO_MARK 36 |
| 64 | 64 | ||
| 65 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | ||
| 66 | * have to define SOCK_NONBLOCK to a different value here. | ||
| 67 | */ | ||
| 68 | #define SOCK_NONBLOCK 0x40000000 | ||
| 69 | |||
| 65 | #endif /* _ASM_SOCKET_H */ | 70 | #endif /* _ASM_SOCKET_H */ |
diff --git a/include/asm-parisc/socket.h b/include/asm-parisc/socket.h index 69a7a0d30b02..fba402c95ac2 100644 --- a/include/asm-parisc/socket.h +++ b/include/asm-parisc/socket.h | |||
| @@ -54,4 +54,9 @@ | |||
| 54 | 54 | ||
| 55 | #define SO_MARK 0x401f | 55 | #define SO_MARK 0x401f |
| 56 | 56 | ||
| 57 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | ||
| 58 | * have to define SOCK_NONBLOCK to a different value here. | ||
| 59 | */ | ||
| 60 | #define SOCK_NONBLOCK 0x40000000 | ||
| 61 | |||
| 57 | #endif /* _ASM_SOCKET_H */ | 62 | #endif /* _ASM_SOCKET_H */ |
diff --git a/include/asm-x86/unistd_64.h b/include/asm-x86/unistd_64.h index 9c1a4a3470d9..e323994a370f 100644 --- a/include/asm-x86/unistd_64.h +++ b/include/asm-x86/unistd_64.h | |||
| @@ -639,6 +639,8 @@ __SYSCALL(__NR_fallocate, sys_fallocate) | |||
| 639 | __SYSCALL(__NR_timerfd_settime, sys_timerfd_settime) | 639 | __SYSCALL(__NR_timerfd_settime, sys_timerfd_settime) |
| 640 | #define __NR_timerfd_gettime 287 | 640 | #define __NR_timerfd_gettime 287 |
| 641 | __SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) | 641 | __SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime) |
| 642 | #define __NR_paccept 288 | ||
| 643 | __SYSCALL(__NR_paccept, sys_paccept) | ||
| 642 | 644 | ||
| 643 | 645 | ||
| 644 | #ifndef __NO_STUBS | 646 | #ifndef __NO_STUBS |
diff --git a/include/linux/net.h b/include/linux/net.h index 8b5383c45b45..3a9b06d4d0fe 100644 --- a/include/linux/net.h +++ b/include/linux/net.h | |||
| @@ -47,6 +47,7 @@ struct net; | |||
| 47 | #define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ | 47 | #define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */ |
| 48 | #define SYS_SENDMSG 16 /* sys_sendmsg(2) */ | 48 | #define SYS_SENDMSG 16 /* sys_sendmsg(2) */ |
| 49 | #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ | 49 | #define SYS_RECVMSG 17 /* sys_recvmsg(2) */ |
| 50 | #define SYS_PACCEPT 18 /* sys_paccept(2) */ | ||
| 50 | 51 | ||
| 51 | typedef enum { | 52 | typedef enum { |
| 52 | SS_FREE = 0, /* not allocated */ | 53 | SS_FREE = 0, /* not allocated */ |
| @@ -219,6 +220,8 @@ extern int sock_map_fd(struct socket *sock, int flags); | |||
| 219 | extern struct socket *sockfd_lookup(int fd, int *err); | 220 | extern struct socket *sockfd_lookup(int fd, int *err); |
| 220 | #define sockfd_put(sock) fput(sock->file) | 221 | #define sockfd_put(sock) fput(sock->file) |
| 221 | extern int net_ratelimit(void); | 222 | extern int net_ratelimit(void); |
| 223 | extern long do_accept(int fd, struct sockaddr __user *upeer_sockaddr, | ||
| 224 | int __user *upeer_addrlen, int flags); | ||
| 222 | 225 | ||
| 223 | #define net_random() random32() | 226 | #define net_random() random32() |
| 224 | #define net_srandom(seed) srandom32((__force u32)seed) | 227 | #define net_srandom(seed) srandom32((__force u32)seed) |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 4394dadff813..2a2a40af6b2c 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
| @@ -409,6 +409,8 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname, | |||
| 409 | asmlinkage long sys_bind(int, struct sockaddr __user *, int); | 409 | asmlinkage long sys_bind(int, struct sockaddr __user *, int); |
| 410 | asmlinkage long sys_connect(int, struct sockaddr __user *, int); | 410 | asmlinkage long sys_connect(int, struct sockaddr __user *, int); |
| 411 | asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); | 411 | asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *); |
| 412 | asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *, | ||
| 413 | const sigset_t *, size_t, int); | ||
| 412 | asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); | 414 | asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *); |
| 413 | asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); | 415 | asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *); |
| 414 | asmlinkage long sys_send(int, void __user *, size_t, unsigned); | 416 | asmlinkage long sys_send(int, void __user *, size_t, unsigned); |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 0fea0ee12da9..2f0b8a2e600f 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
| @@ -31,6 +31,7 @@ cond_syscall(sys_socketpair); | |||
| 31 | cond_syscall(sys_bind); | 31 | cond_syscall(sys_bind); |
| 32 | cond_syscall(sys_listen); | 32 | cond_syscall(sys_listen); |
| 33 | cond_syscall(sys_accept); | 33 | cond_syscall(sys_accept); |
| 34 | cond_syscall(sys_paccept); | ||
| 34 | cond_syscall(sys_connect); | 35 | cond_syscall(sys_connect); |
| 35 | cond_syscall(sys_getsockname); | 36 | cond_syscall(sys_getsockname); |
| 36 | cond_syscall(sys_getpeername); | 37 | cond_syscall(sys_getpeername); |
diff --git a/net/compat.c b/net/compat.c index 6e1b03b51933..67fb6a3834a3 100644 --- a/net/compat.c +++ b/net/compat.c | |||
| @@ -722,9 +722,10 @@ EXPORT_SYMBOL(compat_mc_getsockopt); | |||
| 722 | 722 | ||
| 723 | /* Argument list sizes for compat_sys_socketcall */ | 723 | /* Argument list sizes for compat_sys_socketcall */ |
| 724 | #define AL(x) ((x) * sizeof(u32)) | 724 | #define AL(x) ((x) * sizeof(u32)) |
| 725 | static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), | 725 | static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), |
| 726 | AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), | 726 | AL(3),AL(3),AL(4),AL(4),AL(4),AL(6), |
| 727 | AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)}; | 727 | AL(6),AL(2),AL(5),AL(5),AL(3),AL(3), |
| 728 | AL(6)}; | ||
| 728 | #undef AL | 729 | #undef AL |
| 729 | 730 | ||
| 730 | asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) | 731 | asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) |
| @@ -737,13 +738,52 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns | |||
| 737 | return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | 738 | return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); |
| 738 | } | 739 | } |
| 739 | 740 | ||
| 741 | asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr, | ||
| 742 | int __user *upeer_addrlen, | ||
| 743 | const compat_sigset_t __user *sigmask, | ||
| 744 | compat_size_t sigsetsize, int flags) | ||
| 745 | { | ||
| 746 | compat_sigset_t ss32; | ||
| 747 | sigset_t ksigmask, sigsaved; | ||
| 748 | int ret; | ||
| 749 | |||
| 750 | if (sigmask) { | ||
| 751 | if (sigsetsize != sizeof(compat_sigset_t)) | ||
| 752 | return -EINVAL; | ||
| 753 | if (copy_from_user(&ss32, sigmask, sizeof(ss32))) | ||
| 754 | return -EFAULT; | ||
| 755 | sigset_from_compat(&ksigmask, &ss32); | ||
| 756 | |||
| 757 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
| 758 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | ||
| 759 | } | ||
| 760 | |||
| 761 | ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags); | ||
| 762 | |||
| 763 | if (ret == -ERESTARTNOHAND) { | ||
| 764 | /* | ||
| 765 | * Don't restore the signal mask yet. Let do_signal() deliver | ||
| 766 | * the signal on the way back to userspace, before the signal | ||
| 767 | * mask is restored. | ||
| 768 | */ | ||
| 769 | if (sigmask) { | ||
| 770 | memcpy(¤t->saved_sigmask, &sigsaved, | ||
| 771 | sizeof(sigsaved)); | ||
| 772 | set_restore_sigmask(); | ||
| 773 | } | ||
| 774 | } else if (sigmask) | ||
| 775 | sigprocmask(SIG_SETMASK, &sigsaved, NULL); | ||
| 776 | |||
| 777 | return ret; | ||
| 778 | } | ||
| 779 | |||
| 740 | asmlinkage long compat_sys_socketcall(int call, u32 __user *args) | 780 | asmlinkage long compat_sys_socketcall(int call, u32 __user *args) |
| 741 | { | 781 | { |
| 742 | int ret; | 782 | int ret; |
| 743 | u32 a[6]; | 783 | u32 a[6]; |
| 744 | u32 a0, a1; | 784 | u32 a0, a1; |
| 745 | 785 | ||
| 746 | if (call < SYS_SOCKET || call > SYS_RECVMSG) | 786 | if (call < SYS_SOCKET || call > SYS_PACCEPT) |
| 747 | return -EINVAL; | 787 | return -EINVAL; |
| 748 | if (copy_from_user(a, args, nas[call])) | 788 | if (copy_from_user(a, args, nas[call])) |
| 749 | return -EFAULT; | 789 | return -EFAULT; |
| @@ -764,7 +804,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) | |||
| 764 | ret = sys_listen(a0, a1); | 804 | ret = sys_listen(a0, a1); |
| 765 | break; | 805 | break; |
| 766 | case SYS_ACCEPT: | 806 | case SYS_ACCEPT: |
| 767 | ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2])); | 807 | ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0); |
| 768 | break; | 808 | break; |
| 769 | case SYS_GETSOCKNAME: | 809 | case SYS_GETSOCKNAME: |
| 770 | ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2])); | 810 | ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2])); |
| @@ -804,6 +844,10 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) | |||
| 804 | case SYS_RECVMSG: | 844 | case SYS_RECVMSG: |
| 805 | ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); | 845 | ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); |
| 806 | break; | 846 | break; |
| 847 | case SYS_PACCEPT: | ||
| 848 | ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]), | ||
| 849 | compat_ptr(a[3]), a[4], a[5]); | ||
| 850 | break; | ||
| 807 | default: | 851 | default: |
| 808 | ret = -EINVAL; | 852 | ret = -EINVAL; |
| 809 | break; | 853 | break; |
diff --git a/net/socket.c b/net/socket.c index 64601f900352..a0ce8ad72252 10064 | |||
