Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 105411
b: refs/heads/master
c: aaca0bd
h: refs/heads/master
i:
  105409: 837b7ec
  105407: e11b404
v: v3
  • Loading branch information
Ulrich Drepper authored and Linus Torvalds committed Jul 24, 2008
1 parent e899f0c commit 6712df8
Show file tree
Hide file tree
Showing 9 changed files with 140 additions and 13 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a677a039be7243357d93502bff2b40850c942e2d
refs/heads/master: aaca0bdca573f3f51ea03139f9c7289541e7bca3
5 changes: 5 additions & 0 deletions trunk/include/asm-alpha/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,9 @@

#define SO_MARK 36

/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
*/
#define SOCK_NONBLOCK 0x40000000

#endif /* _ASM_SOCKET_H */
5 changes: 5 additions & 0 deletions trunk/include/asm-parisc/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,9 @@

#define SO_MARK 0x401f

/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
* have to define SOCK_NONBLOCK to a different value here.
*/
#define SOCK_NONBLOCK 0x40000000

#endif /* _ASM_SOCKET_H */
2 changes: 2 additions & 0 deletions trunk/include/asm-x86/unistd_64.h
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,8 @@ __SYSCALL(__NR_fallocate, sys_fallocate)
__SYSCALL(__NR_timerfd_settime, sys_timerfd_settime)
#define __NR_timerfd_gettime 287
__SYSCALL(__NR_timerfd_gettime, sys_timerfd_gettime)
#define __NR_paccept 288
__SYSCALL(__NR_paccept, sys_paccept)


#ifndef __NO_STUBS
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct net;
#define SYS_GETSOCKOPT 15 /* sys_getsockopt(2) */
#define SYS_SENDMSG 16 /* sys_sendmsg(2) */
#define SYS_RECVMSG 17 /* sys_recvmsg(2) */
#define SYS_PACCEPT 18 /* sys_paccept(2) */

typedef enum {
SS_FREE = 0, /* not allocated */
Expand Down Expand Up @@ -219,6 +220,8 @@ extern int sock_map_fd(struct socket *sock, int flags);
extern struct socket *sockfd_lookup(int fd, int *err);
#define sockfd_put(sock) fput(sock->file)
extern int net_ratelimit(void);
extern long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags);

#define net_random() random32()
#define net_srandom(seed) srandom32((__force u32)seed)
Expand Down
2 changes: 2 additions & 0 deletions trunk/include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,8 @@ asmlinkage long sys_getsockopt(int fd, int level, int optname,
asmlinkage long sys_bind(int, struct sockaddr __user *, int);
asmlinkage long sys_connect(int, struct sockaddr __user *, int);
asmlinkage long sys_accept(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_paccept(int, struct sockaddr __user *, int __user *,
const sigset_t *, size_t, int);
asmlinkage long sys_getsockname(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_getpeername(int, struct sockaddr __user *, int __user *);
asmlinkage long sys_send(int, void __user *, size_t, unsigned);
Expand Down
1 change: 1 addition & 0 deletions trunk/kernel/sys_ni.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ cond_syscall(sys_socketpair);
cond_syscall(sys_bind);
cond_syscall(sys_listen);
cond_syscall(sys_accept);
cond_syscall(sys_paccept);
cond_syscall(sys_connect);
cond_syscall(sys_getsockname);
cond_syscall(sys_getpeername);
Expand Down
52 changes: 48 additions & 4 deletions trunk/net/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -722,9 +722,10 @@ EXPORT_SYMBOL(compat_mc_getsockopt);

/* Argument list sizes for compat_sys_socketcall */
#define AL(x) ((x) * sizeof(u32))
static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
AL(6)};
#undef AL

asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags)
Expand All @@ -737,13 +738,52 @@ asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, uns
return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
}

asmlinkage long compat_sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen,
const compat_sigset_t __user *sigmask,
compat_size_t sigsetsize, int flags)
{
compat_sigset_t ss32;
sigset_t ksigmask, sigsaved;
int ret;

if (sigmask) {
if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;
if (copy_from_user(&ss32, sigmask, sizeof(ss32)))
return -EFAULT;
sigset_from_compat(&ksigmask, &ss32);

sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
}

ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);

if (ret == -ERESTARTNOHAND) {
/*
* Don't restore the signal mask yet. Let do_signal() deliver
* the signal on the way back to userspace, before the signal
* mask is restored.
*/
if (sigmask) {
memcpy(&current->saved_sigmask, &sigsaved,
sizeof(sigsaved));
set_restore_sigmask();
}
} else if (sigmask)
sigprocmask(SIG_SETMASK, &sigsaved, NULL);

return ret;
}

asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
{
int ret;
u32 a[6];
u32 a0, a1;

if (call < SYS_SOCKET || call > SYS_RECVMSG)
if (call < SYS_SOCKET || call > SYS_PACCEPT)
return -EINVAL;
if (copy_from_user(a, args, nas[call]))
return -EFAULT;
Expand All @@ -764,7 +804,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
ret = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2]));
ret = do_accept(a0, compat_ptr(a1), compat_ptr(a[2]), 0);
break;
case SYS_GETSOCKNAME:
ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
Expand Down Expand Up @@ -804,6 +844,10 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
case SYS_RECVMSG:
ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
break;
case SYS_PACCEPT:
ret = compat_sys_paccept(a0, compat_ptr(a1), compat_ptr(a[2]),
compat_ptr(a[3]), a[4], a[5]);
break;
default:
ret = -EINVAL;
break;
Expand Down
81 changes: 73 additions & 8 deletions trunk/net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
#include <linux/file.h>
#include <linux/net.h>
#include <linux/interrupt.h>
#include <linux/thread_info.h>
#include <linux/rcupdate.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
Expand Down Expand Up @@ -1225,6 +1226,9 @@ asmlinkage long sys_socket(int family, int type, int protocol)
return -EINVAL;
type &= SOCK_TYPE_MASK;

if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;

retval = sock_create(family, type, protocol, &sock);
if (retval < 0)
goto out;
Expand Down Expand Up @@ -1259,6 +1263,9 @@ asmlinkage long sys_socketpair(int family, int type, int protocol,
return -EINVAL;
type &= SOCK_TYPE_MASK;

if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;

/*
* Obtain the first socket and check if the underlying protocol
* supports the socketpair call.
Expand Down Expand Up @@ -1413,14 +1420,20 @@ asmlinkage long sys_listen(int fd, int backlog)
* clean when we restucture accept also.
*/

asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen)
long do_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags)
{
struct socket *sock, *newsock;
struct file *newfile;
int err, len, newfd, fput_needed;
struct sockaddr_storage address;

if (flags & ~SOCK_CLOEXEC)
return -EINVAL;

if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;

sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
goto out;
Expand All @@ -1438,7 +1451,7 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
*/
__module_get(newsock->ops->owner);

newfd = sock_alloc_fd(&newfile, 0);
newfd = sock_alloc_fd(&newfile, flags & O_CLOEXEC);
if (unlikely(newfd < 0)) {
err = newfd;
sock_release(newsock);
Expand Down Expand Up @@ -1491,6 +1504,50 @@ asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
goto out_put;
}

asmlinkage long sys_paccept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen,
const sigset_t __user *sigmask,
size_t sigsetsize, int flags)
{
sigset_t ksigmask, sigsaved;
int ret;

if (sigmask) {
/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(sigset_t))
return -EINVAL;
if (copy_from_user(&ksigmask, sigmask, sizeof(ksigmask)))
return -EFAULT;

sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP));
sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved);
}

ret = do_accept(fd, upeer_sockaddr, upeer_addrlen, flags);

if (ret < 0 && signal_pending(current)) {
/*
* Don't restore the signal mask yet. Let do_signal() deliver
* the signal on the way back to userspace, before the signal
* mask is restored.
*/
if (sigmask) {
memcpy(&current->saved_sigmask, &sigsaved,
sizeof(sigsaved));
set_restore_sigmask();
}
} else if (sigmask)
sigprocmask(SIG_SETMASK, &sigsaved, NULL);

return ret;
}

asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen)
{
return do_accept(fd, upeer_sockaddr, upeer_addrlen, 0);
}

/*
* Attempt to connect to a socket with the server address. The address
* is in user space so we verify it is OK and move it to kernel space.
Expand Down Expand Up @@ -2011,10 +2068,11 @@ asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,

/* Argument list sizes for sys_socketcall */
#define AL(x) ((x) * sizeof(unsigned long))
static const unsigned char nargs[18]={
static const unsigned char nargs[19]={
AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),
AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)
AL(6),AL(2),AL(5),AL(5),AL(3),AL(3),
AL(6)
};

#undef AL
Expand All @@ -2033,7 +2091,7 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
unsigned long a0, a1;
int err;

if (call < 1 || call > SYS_RECVMSG)
if (call < 1 || call > SYS_PACCEPT)
return -EINVAL;

/* copy_from_user should be SMP safe. */
Expand Down Expand Up @@ -2062,8 +2120,8 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
break;
case SYS_ACCEPT:
err =
sys_accept(a0, (struct sockaddr __user *)a1,
(int __user *)a[2]);
do_accept(a0, (struct sockaddr __user *)a1,
(int __user *)a[2], 0);
break;
case SYS_GETSOCKNAME:
err =
Expand Down Expand Up @@ -2110,6 +2168,13 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args)
case SYS_RECVMSG:
err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
break;
case SYS_PACCEPT:
err =
sys_paccept(a0, (struct sockaddr __user *)a1,
(int __user *)a[2],
(const sigset_t __user *) a[3],
a[4], a[5]);
break;
default:
err = -EINVAL;
break;
Expand Down

0 comments on commit 6712df8

Please sign in to comment.