#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>
container_of(inode, struct socket_alloc, vfs_inode));
}
-static void init_once(struct kmem_cache *cachep, void *foo)
+static void init_once(void *foo)
{
struct socket_alloc *ei = (struct socket_alloc *)foo;
return fd;
}
-static int sock_attach_fd(struct socket *sock, struct file *file)
+static int sock_attach_fd(struct socket *sock, struct file *file, int flags)
{
struct dentry *dentry;
struct qstr name = { .name = "" };
init_file(file, sock_mnt, dentry, FMODE_READ | FMODE_WRITE,
&socket_file_ops);
SOCK_INODE(sock)->i_fop = &socket_file_ops;
- file->f_flags = O_RDWR;
+ file->f_flags = O_RDWR | (flags & O_NONBLOCK);
file->f_pos = 0;
file->private_data = sock;
int fd = sock_alloc_fd(&newfile, flags);
if (likely(fd >= 0)) {
- int err = sock_attach_fd(sock, newfile);
+ int err = sock_attach_fd(sock, newfile, flags);
if (unlikely(err < 0)) {
put_filp(newfile);
sock = SOCKET_I(inode);
inode->i_mode = S_IFSOCK | S_IRWXUGO;
- inode->i_uid = current->fsuid;
- inode->i_gid = current->fsgid;
+ inode->i_uid = current_fsuid();
+ inode->i_gid = current_fsgid();
get_cpu_var(sockets_in_use)++;
put_cpu_var(sockets_in_use);
printk(KERN_DEBUG "sock_close: NULL inode\n");
return 0;
}
- sock_fasync(-1, filp, 0);
sock_release(SOCKET_I(inode));
return 0;
}
sock->type = type;
-#if defined(CONFIG_KMOD)
+#ifdef CONFIG_MODULES
/* Attempt to load a protocol module if the find failed.
*
* 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
return __sock_create(&init_net, family, type, protocol, res, 1);
}
-asmlinkage long sys_socket(int family, int type, int protocol)
+SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
int retval;
struct socket *sock;
int flags;
+ /* Check the SOCK_* constants for consistency. */
+ BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
+ BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
+ BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
+ BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
+
flags = type & ~SOCK_TYPE_MASK;
- if (flags & ~SOCK_CLOEXEC)
+ if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
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;
- retval = sock_map_fd(sock, flags & O_CLOEXEC);
+ retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
if (retval < 0)
goto out_release;
* Create a pair of connected sockets.
*/
-asmlinkage long sys_socketpair(int family, int type, int protocol,
- int __user *usockvec)
+SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
+ int __user *, usockvec)
{
struct socket *sock1, *sock2;
int fd1, fd2, err;
int flags;
flags = type & ~SOCK_TYPE_MASK;
- if (flags & ~SOCK_CLOEXEC)
+ if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
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.
goto out_release_both;
}
- err = sock_attach_fd(sock1, newfile1);
+ err = sock_attach_fd(sock1, newfile1, flags & O_NONBLOCK);
if (unlikely(err < 0)) {
goto out_fd2;
}
- err = sock_attach_fd(sock2, newfile2);
+ err = sock_attach_fd(sock2, newfile2, flags & O_NONBLOCK);
if (unlikely(err < 0)) {
fput(newfile1);
goto out_fd1;
}
- err = audit_fd_pair(fd1, fd2);
- if (err < 0) {
- fput(newfile1);
- fput(newfile2);
- goto out_fd;
- }
-
+ audit_fd_pair(fd1, fd2);
fd_install(fd1, newfile1);
fd_install(fd2, newfile2);
/* fd1 and fd2 may be already another descriptors.
out_fd1:
put_filp(newfile2);
sock_release(sock2);
-out_fd:
put_unused_fd(fd1);
put_unused_fd(fd2);
goto out;
* the protocol layer (having also checked the address is ok).
*/
-asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
+SYSCALL_DEFINE3(bind, int, fd, struct sockaddr __user *, umyaddr, int, addrlen)
{
struct socket *sock;
struct sockaddr_storage address;
* ready for listening.
*/
-asmlinkage long sys_listen(int fd, int backlog)
+SYSCALL_DEFINE2(listen, int, fd, int, backlog)
{
struct socket *sock;
int err, fput_needed;
* clean when we restucture accept also.
*/
-asmlinkage long sys_accept(int fd, struct sockaddr __user *upeer_sockaddr,
- int __user *upeer_addrlen)
+SYSCALL_DEFINE4(accept4, 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 | SOCK_NONBLOCK))
+ 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;
*/
__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);
goto out_put;
}
- err = sock_attach_fd(newsock, newfile);
+ err = sock_attach_fd(newsock, newfile, flags & O_NONBLOCK);
if (err < 0)
goto out_fd_simple;
goto out_put;
}
+SYSCALL_DEFINE3(accept, int, fd, struct sockaddr __user *, upeer_sockaddr,
+ int __user *, upeer_addrlen)
+{
+ return sys_accept4(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.
* include the -EINPROGRESS status for such sockets.
*/
-asmlinkage long sys_connect(int fd, struct sockaddr __user *uservaddr,
- int addrlen)
+SYSCALL_DEFINE3(connect, int, fd, struct sockaddr __user *, uservaddr,
+ int, addrlen)
{
struct socket *sock;
struct sockaddr_storage address;
* name to user space.
*/
-asmlinkage long sys_getsockname(int fd, struct sockaddr __user *usockaddr,
- int __user *usockaddr_len)
+SYSCALL_DEFINE3(getsockname, int, fd, struct sockaddr __user *, usockaddr,
+ int __user *, usockaddr_len)
{
struct socket *sock;
struct sockaddr_storage address;
* name to user space.
*/
-asmlinkage long sys_getpeername(int fd, struct sockaddr __user *usockaddr,
- int __user *usockaddr_len)
+SYSCALL_DEFINE3(getpeername, int, fd, struct sockaddr __user *, usockaddr,
+ int __user *, usockaddr_len)
{
struct socket *sock;
struct sockaddr_storage address;
* the protocol.
*/
-asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
- unsigned flags, struct sockaddr __user *addr,
- int addr_len)
+SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,
+ unsigned, flags, struct sockaddr __user *, addr,
+ int, addr_len)
{
struct socket *sock;
struct sockaddr_storage address;
* Send a datagram down a socket.
*/
-asmlinkage long sys_send(int fd, void __user *buff, size_t len, unsigned flags)
+SYSCALL_DEFINE4(send, int, fd, void __user *, buff, size_t, len,
+ unsigned, flags)
{
return sys_sendto(fd, buff, len, flags, NULL, 0);
}
* sender address from kernel to user space.
*/
-asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
- unsigned flags, struct sockaddr __user *addr,
- int __user *addr_len)
+SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,
+ unsigned, flags, struct sockaddr __user *, addr,
+ int __user *, addr_len)
{
struct socket *sock;
struct iovec iov;
* to pass the user mode parameter for the protocols to sort out.
*/
-asmlinkage long sys_setsockopt(int fd, int level, int optname,
- char __user *optval, int optlen)
+SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname,
+ char __user *, optval, int, optlen)
{
int err, fput_needed;
struct socket *sock;
* to pass a user mode parameter for the protocols to sort out.
*/
-asmlinkage long sys_getsockopt(int fd, int level, int optname,
- char __user *optval, int __user *optlen)
+SYSCALL_DEFINE5(getsockopt, int, fd, int, level, int, optname,
+ char __user *, optval, int __user *, optlen)
{
int err, fput_needed;
struct socket *sock;
* Shutdown a socket.
*/
-asmlinkage long sys_shutdown(int fd, int how)
+SYSCALL_DEFINE2(shutdown, int, fd, int, how)
{
int err, fput_needed;
struct socket *sock;
* BSD sendmsg interface
*/
-asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
+SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags)
{
struct compat_msghdr __user *msg_compat =
(struct compat_msghdr __user *)msg;
* BSD recvmsg interface
*/
-asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
- unsigned int flags)
+SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
+ unsigned int, flags)
{
struct compat_msghdr __user *msg_compat =
(struct compat_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(4)
};
#undef AL
* it is set by the callees.
*/
-asmlinkage long sys_socketcall(int call, unsigned long __user *args)
+SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
{
unsigned long a[6];
unsigned long a0, a1;
int err;
- if (call < 1 || call > SYS_RECVMSG)
+ if (call < 1 || call > SYS_ACCEPT4)
return -EINVAL;
/* copy_from_user should be SMP safe. */
if (copy_from_user(a, args, nargs[call]))
return -EFAULT;
- err = audit_socketcall(nargs[call] / sizeof(unsigned long), a);
- if (err)
- return err;
+ audit_socketcall(nargs[call] / sizeof(unsigned long), a);
a0 = a[0];
a1 = a[1];
err = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- err =
- sys_accept(a0, (struct sockaddr __user *)a1,
- (int __user *)a[2]);
+ err = sys_accept4(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2], 0);
break;
case SYS_GETSOCKNAME:
err =
case SYS_RECVMSG:
err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
break;
+ case SYS_ACCEPT4:
+ err = sys_accept4(a0, (struct sockaddr __user *)a1,
+ (int __user *)a[2], a[3]);
+ break;
default:
err = -EINVAL;
break;
}
(*newsock)->ops = sock->ops;
+ __module_get((*newsock)->ops->owner);
done:
return err;