git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
[NET_SCHED]: cls_flow: support classification based on VLAN tag
[safe/jmp/linux-2.6]
/
net
/
socket.c
diff --git
a/net/socket.c
b/net/socket.c
index
759825b
..
7651de0
100644
(file)
--- a/
net/socket.c
+++ b/
net/socket.c
@@
-84,6
+84,7
@@
#include <linux/kmod.h>
#include <linux/audit.h>
#include <linux/wireless.h>
#include <linux/kmod.h>
#include <linux/audit.h>
#include <linux/wireless.h>
+#include <linux/nsproxy.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
@@
-111,6
+112,9
@@
static long compat_sock_ioctl(struct file *file,
static int sock_fasync(int fd, struct file *filp, int on);
static ssize_t sock_sendpage(struct file *file, struct page *page,
int offset, size_t size, loff_t *ppos, int more);
static int sock_fasync(int fd, struct file *filp, int on);
static ssize_t sock_sendpage(struct file *file, struct page *page,
int offset, size_t size, loff_t *ppos, int more);
+static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags);
/*
* Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
/*
* Socket files have a set of 'special' operations as well as the generic file ones. These don't appear
@@
-133,6
+137,7
@@
static const struct file_operations socket_file_ops = {
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
+ .splice_read = sock_splice_read,
};
/*
};
/*
@@
-257,12
+262,11
@@
static void sock_destroy_inode(struct inode *inode)
container_of(inode, struct socket_alloc, vfs_inode));
}
container_of(inode, struct socket_alloc, vfs_inode));
}
-static void init_once(
void *foo, struct kmem_cache *cachep, unsigned long flags
)
+static void init_once(
struct kmem_cache *cachep, void *foo
)
{
struct socket_alloc *ei = (struct socket_alloc *)foo;
{
struct socket_alloc *ei = (struct socket_alloc *)foo;
- if (flags & SLAB_CTOR_CONSTRUCTOR)
- inode_init_once(&ei->vfs_inode);
+ inode_init_once(&ei->vfs_inode);
}
static int init_inodecache(void)
}
static int init_inodecache(void)
@@
-273,8
+277,7
@@
static int init_inodecache(void)
(SLAB_HWCACHE_ALIGN |
SLAB_RECLAIM_ACCOUNT |
SLAB_MEM_SPREAD),
(SLAB_HWCACHE_ALIGN |
SLAB_RECLAIM_ACCOUNT |
SLAB_MEM_SPREAD),
- init_once,
- NULL);
+ init_once);
if (sock_inode_cachep == NULL)
return -ENOMEM;
return 0;
if (sock_inode_cachep == NULL)
return -ENOMEM;
return 0;
@@
-313,8
+316,19
@@
static int sockfs_delete_dentry(struct dentry *dentry)
dentry->d_flags |= DCACHE_UNHASHED;
return 0;
}
dentry->d_flags |= DCACHE_UNHASHED;
return 0;
}
+
+/*
+ * sockfs_dname() is called from d_path().
+ */
+static char *sockfs_dname(struct dentry *dentry, char *buffer, int buflen)
+{
+ return dynamic_dname(dentry, buffer, buflen, "socket:[%lu]",
+ dentry->d_inode->i_ino);
+}
+
static struct dentry_operations sockfs_dentry_operations = {
.d_delete = sockfs_delete_dentry,
static struct dentry_operations sockfs_dentry_operations = {
.d_delete = sockfs_delete_dentry,
+ .d_dname = sockfs_dname,
};
/*
};
/*
@@
-354,31
+368,26
@@
static int sock_alloc_fd(struct file **filep)
static int sock_attach_fd(struct socket *sock, struct file *file)
{
static int sock_attach_fd(struct socket *sock, struct file *file)
{
- struct qstr this;
- char name[32];
-
- this.len = sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
- this.name = name;
- this.hash = 0;
+ struct dentry *dentry;
+ struct qstr name = { .name = "" };
-
file->f_path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this
);
- if (unlikely(!
file->f_path.
dentry))
+
dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name
);
+ if (unlikely(!dentry))
return -ENOMEM;
return -ENOMEM;
-
file->f_path.
dentry->d_op = &sockfs_dentry_operations;
+ dentry->d_op = &sockfs_dentry_operations;
/*
* We dont want to push this dentry into global dentry hash table.
* We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
* This permits a working /proc/$pid/fd/XXX on sockets
*/
/*
* We dont want to push this dentry into global dentry hash table.
* We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED
* This permits a working /proc/$pid/fd/XXX on sockets
*/
- file->f_path.dentry->d_flags &= ~DCACHE_UNHASHED;
- d_instantiate(file->f_path.dentry, SOCK_INODE(sock));
- file->f_path.mnt = mntget(sock_mnt);
- file->f_mapping = file->f_path.dentry->d_inode->i_mapping;
+ dentry->d_flags &= ~DCACHE_UNHASHED;
+ d_instantiate(dentry, SOCK_INODE(sock));
sock->file = file;
sock->file = file;
- file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
- file->f_mode = FMODE_READ | FMODE_WRITE;
+ 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_pos = 0;
file->private_data = sock;
file->f_flags = O_RDWR;
file->f_pos = 0;
file->private_data = sock;
@@
-686,6
+695,15
@@
static ssize_t sock_sendpage(struct file *file, struct page *page,
return sock->ops->sendpage(sock, page, offset, size, flags);
}
return sock->ops->sendpage(sock, page, offset, size, flags);
}
+static ssize_t sock_splice_read(struct file *file, loff_t *ppos,
+ struct pipe_inode_info *pipe, size_t len,
+ unsigned int flags)
+{
+ struct socket *sock = file->private_data;
+
+ return sock->ops->splice_read(sock, ppos, pipe, len, flags);
+}
+
static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
struct sock_iocb *siocb)
{
static struct sock_iocb *alloc_sock_iocb(struct kiocb *iocb,
struct sock_iocb *siocb)
{
@@
-773,9
+791,6
@@
static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (pos != 0)
return -ESPIPE;
if (pos != 0)
return -ESPIPE;
- if (iocb->ki_left == 0) /* Match SYS5 behaviour */
- return 0;
-
x = alloc_sock_iocb(iocb, &siocb);
if (!x)
return -ENOMEM;
x = alloc_sock_iocb(iocb, &siocb);
if (!x)
return -ENOMEM;
@@
-789,9
+804,9
@@
static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov,
*/
static DEFINE_MUTEX(br_ioctl_mutex);
*/
static DEFINE_MUTEX(br_ioctl_mutex);
-static int (*br_ioctl_hook) (unsigned int cmd, void __user *arg) = NULL;
+static int (*br_ioctl_hook) (
struct net *,
unsigned int cmd, void __user *arg) = NULL;
-void brioctl_set(int (*hook) (unsigned int, void __user *))
+void brioctl_set(int (*hook) (
struct net *,
unsigned int, void __user *))
{
mutex_lock(&br_ioctl_mutex);
br_ioctl_hook = hook;
{
mutex_lock(&br_ioctl_mutex);
br_ioctl_hook = hook;
@@
-801,9
+816,9
@@
void brioctl_set(int (*hook) (unsigned int, void __user *))
EXPORT_SYMBOL(brioctl_set);
static DEFINE_MUTEX(vlan_ioctl_mutex);
EXPORT_SYMBOL(brioctl_set);
static DEFINE_MUTEX(vlan_ioctl_mutex);
-static int (*vlan_ioctl_hook) (void __user *arg);
+static int (*vlan_ioctl_hook) (
struct net *,
void __user *arg);
-void vlan_ioctl_set(int (*hook) (void __user *))
+void vlan_ioctl_set(int (*hook) (
struct net *,
void __user *))
{
mutex_lock(&vlan_ioctl_mutex);
vlan_ioctl_hook = hook;
{
mutex_lock(&vlan_ioctl_mutex);
vlan_ioctl_hook = hook;
@@
-832,16
+847,20
@@
EXPORT_SYMBOL(dlci_ioctl_set);
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
struct socket *sock;
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
struct socket *sock;
+ struct sock *sk;
void __user *argp = (void __user *)arg;
int pid, err;
void __user *argp = (void __user *)arg;
int pid, err;
+ struct net *net;
sock = file->private_data;
sock = file->private_data;
+ sk = sock->sk;
+ net = sk->sk_net;
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
if (cmd >= SIOCDEVPRIVATE && cmd <= (SIOCDEVPRIVATE + 15)) {
- err = dev_ioctl(cmd, argp);
+ err = dev_ioctl(
net,
cmd, argp);
} else
#ifdef CONFIG_WIRELESS_EXT
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
} else
#ifdef CONFIG_WIRELESS_EXT
if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
- err = dev_ioctl(cmd, argp);
+ err = dev_ioctl(
net,
cmd, argp);
} else
#endif /* CONFIG_WIRELESS_EXT */
switch (cmd) {
} else
#endif /* CONFIG_WIRELESS_EXT */
switch (cmd) {
@@
-867,7
+886,7
@@
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&br_ioctl_mutex);
if (br_ioctl_hook)
mutex_lock(&br_ioctl_mutex);
if (br_ioctl_hook)
- err = br_ioctl_hook(cmd, argp);
+ err = br_ioctl_hook(
net,
cmd, argp);
mutex_unlock(&br_ioctl_mutex);
break;
case SIOCGIFVLAN:
mutex_unlock(&br_ioctl_mutex);
break;
case SIOCGIFVLAN:
@@
-878,7
+897,7
@@
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
mutex_lock(&vlan_ioctl_mutex);
if (vlan_ioctl_hook)
mutex_lock(&vlan_ioctl_mutex);
if (vlan_ioctl_hook)
- err = vlan_ioctl_hook(argp);
+ err = vlan_ioctl_hook(
net,
argp);
mutex_unlock(&vlan_ioctl_mutex);
break;
case SIOCADDDLCI:
mutex_unlock(&vlan_ioctl_mutex);
break;
case SIOCADDDLCI:
@@
-901,7
+920,7
@@
static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
* to the NIC driver.
*/
if (err == -ENOIOCTLCMD)
* to the NIC driver.
*/
if (err == -ENOIOCTLCMD)
- err = dev_ioctl(cmd, argp);
+ err = dev_ioctl(
net,
cmd, argp);
break;
}
return err;
break;
}
return err;
@@
-1051,26
+1070,25
@@
int sock_wake_async(struct socket *sock, int how, int band)
if (!sock || !sock->fasync_list)
return -1;
switch (how) {
if (!sock || !sock->fasync_list)
return -1;
switch (how) {
- case 1:
-
+ case SOCK_WAKE_WAITD:
if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
break;
goto call_kill;
if (test_bit(SOCK_ASYNC_WAITDATA, &sock->flags))
break;
goto call_kill;
- case
2
:
+ case
SOCK_WAKE_SPACE
:
if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
break;
/* fall through */
if (!test_and_clear_bit(SOCK_ASYNC_NOSPACE, &sock->flags))
break;
/* fall through */
- case
0
:
+ case
SOCK_WAKE_IO
:
call_kill:
__kill_fasync(sock->fasync_list, SIGIO, band);
break;
call_kill:
__kill_fasync(sock->fasync_list, SIGIO, band);
break;
- case
3
:
+ case
SOCK_WAKE_URG
:
__kill_fasync(sock->fasync_list, SIGURG, band);
}
return 0;
}
__kill_fasync(sock->fasync_list, SIGURG, band);
}
return 0;
}
-static int __sock_create(int family, int type, int protocol,
+static int __sock_create(
struct net *net,
int family, int type, int protocol,
struct socket **res, int kern)
{
int err;
struct socket **res, int kern)
{
int err;
@@
-1146,7
+1164,7
@@
static int __sock_create(int family, int type, int protocol,
/* Now protected by module ref count */
rcu_read_unlock();
/* Now protected by module ref count */
rcu_read_unlock();
- err = pf->create(sock, protocol);
+ err = pf->create(
net,
sock, protocol);
if (err < 0)
goto out_module_put;
if (err < 0)
goto out_module_put;
@@
-1164,7
+1182,7
@@
static int __sock_create(int family, int type, int protocol,
module_put(pf->owner);
err = security_socket_post_create(sock, family, type, protocol, kern);
if (err)
module_put(pf->owner);
err = security_socket_post_create(sock, family, type, protocol, kern);
if (err)
- goto out_release;
+ goto out_
sock_
release;
*res = sock;
return 0;
*res = sock;
return 0;
@@
-1185,12
+1203,12
@@
out_release:
int sock_create(int family, int type, int protocol, struct socket **res)
{
int sock_create(int family, int type, int protocol, struct socket **res)
{
- return __sock_create(family, type, protocol, res, 0);
+ return __sock_create(
current->nsproxy->net_ns,
family, type, protocol, res, 0);
}
int sock_create_kern(int family, int type, int protocol, struct socket **res)
{
}
int sock_create_kern(int family, int type, int protocol, struct socket **res)
{
- return __sock_create(family, type, protocol, res, 1);
+ return __sock_create(
&init_net,
family, type, protocol, res, 1);
}
asmlinkage long sys_socket(int family, int type, int protocol)
}
asmlinkage long sys_socket(int family, int type, int protocol)
@@
-1244,11
+1262,14
@@
asmlinkage long sys_socketpair(int family, int type, int protocol,
goto out_release_both;
fd1 = sock_alloc_fd(&newfile1);
goto out_release_both;
fd1 = sock_alloc_fd(&newfile1);
- if (unlikely(fd1 < 0))
+ if (unlikely(fd1 < 0)) {
+ err = fd1;
goto out_release_both;
goto out_release_both;
+ }
fd2 = sock_alloc_fd(&newfile2);
if (unlikely(fd2 < 0)) {
fd2 = sock_alloc_fd(&newfile2);
if (unlikely(fd2 < 0)) {
+ err = fd2;
put_filp(newfile1);
put_unused_fd(fd1);
goto out_release_both;
put_filp(newfile1);
put_unused_fd(fd1);
goto out_release_both;
@@
-1344,17
+1365,17
@@
asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
* ready for listening.
*/
* ready for listening.
*/
-int sysctl_somaxconn __read_mostly = SOMAXCONN;
-
asmlinkage long sys_listen(int fd, int backlog)
{
struct socket *sock;
int err, fput_needed;
asmlinkage long sys_listen(int fd, int backlog)
{
struct socket *sock;
int err, fput_needed;
+ int somaxconn;
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (sock) {
- if ((unsigned)backlog > sysctl_somaxconn)
- backlog = sysctl_somaxconn;
+ somaxconn = sock->sk->sk_net->sysctl_somaxconn;
+ if ((unsigned)backlog > somaxconn)
+ backlog = somaxconn;
err = security_socket_listen(sock, backlog);
if (!err)
err = security_socket_listen(sock, backlog);
if (!err)
@@
-1572,16
+1593,11
@@
asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
struct msghdr msg;
struct iovec iov;
int fput_needed;
struct msghdr msg;
struct iovec iov;
int fput_needed;
- struct file *sock_file;
- sock_file = fget_light(fd, &fput_needed);
- err = -EBADF;
- if (!sock_file)
+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
+ if (!sock)
goto out;
goto out;
- sock = sock_from_file(sock_file, &err);
- if (!sock)
- goto out_put;
iov.iov_base = buff;
iov.iov_len = len;
msg.msg_name = NULL;
iov.iov_base = buff;
iov.iov_len = len;
msg.msg_name = NULL;
@@
-1603,7
+1619,7
@@
asmlinkage long sys_sendto(int fd, void __user *buff, size_t len,
err = sock_sendmsg(sock, &msg, len);
out_put:
err = sock_sendmsg(sock, &msg, len);
out_put:
- fput_light(sock
_
file, fput_needed);
+ fput_light(sock
->
file, fput_needed);
out:
return err;
}
out:
return err;
}
@@
-1632,17
+1648,11
@@
asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
struct msghdr msg;
char address[MAX_SOCK_ADDR];
int err, err2;
struct msghdr msg;
char address[MAX_SOCK_ADDR];
int err, err2;
- struct file *sock_file;
int fput_needed;
int fput_needed;
- sock_file = fget_light(fd, &fput_needed);
- err = -EBADF;
- if (!sock_file)
- goto out;
-
- sock = sock_from_file(sock_file, &err);
+ sock = sockfd_lookup_light(fd, &err, &fput_needed);
if (!sock)
if (!sock)
- goto out
_put
;
+ goto out;
msg.msg_control = NULL;
msg.msg_controllen = 0;
msg.msg_control = NULL;
msg.msg_controllen = 0;
@@
-1661,8
+1671,8
@@
asmlinkage long sys_recvfrom(int fd, void __user *ubuf, size_t size,
if (err2 < 0)
err = err2;
}
if (err2 < 0)
err = err2;
}
-out_put:
- fput_light(sock
_
file, fput_needed);
+
+ fput_light(sock
->
file, fput_needed);
out:
return err;
}
out:
return err;
}
@@
-1923,7
+1933,7
@@
asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
* kernel msghdr to use the kernel address space)
*/
* kernel msghdr to use the kernel address space)
*/
- uaddr = (void __user *)msg_sys.msg_name;
+ uaddr = (
__force
void __user *)msg_sys.msg_name;
uaddr_len = COMPAT_NAMELEN(msg);
if (MSG_CMSG_COMPAT & flags) {
err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
uaddr_len = COMPAT_NAMELEN(msg);
if (MSG_CMSG_COMPAT & flags) {
err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE);
@@
-1934,9
+1944,7
@@
asmlinkage long sys_recvmsg(int fd, struct msghdr __user *msg,
total_len = err;
cmsg_ptr = (unsigned long)msg_sys.msg_control;
total_len = err;
cmsg_ptr = (unsigned long)msg_sys.msg_control;
- msg_sys.msg_flags = 0;
- if (MSG_CMSG_COMPAT & flags)
- msg_sys.msg_flags = MSG_CMSG_COMPAT;
+ msg_sys.msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT);
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
if (sock->file->f_flags & O_NONBLOCK)
flags |= MSG_DONTWAIT;
@@
-2231,6
+2239,7
@@
int kernel_accept(struct socket *sock, struct socket **newsock, int flags)
err = sock->ops->accept(sock, *newsock, flags);
if (err < 0) {
sock_release(*newsock);
err = sock->ops->accept(sock, *newsock, flags);
if (err < 0) {
sock_release(*newsock);
+ *newsock = NULL;
goto done;
}
goto done;
}
@@
-2311,6
+2320,11
@@
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg)
return err;
}
return err;
}
+int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how)
+{
+ return sock->ops->shutdown(sock, how);
+}
+
/* ABI emulation layers need these two */
EXPORT_SYMBOL(move_addr_to_kernel);
EXPORT_SYMBOL(move_addr_to_user);
/* ABI emulation layers need these two */
EXPORT_SYMBOL(move_addr_to_kernel);
EXPORT_SYMBOL(move_addr_to_user);
@@
-2337,3
+2351,4
@@
EXPORT_SYMBOL(kernel_getsockopt);
EXPORT_SYMBOL(kernel_setsockopt);
EXPORT_SYMBOL(kernel_sendpage);
EXPORT_SYMBOL(kernel_sock_ioctl);
EXPORT_SYMBOL(kernel_setsockopt);
EXPORT_SYMBOL(kernel_sendpage);
EXPORT_SYMBOL(kernel_sock_ioctl);
+EXPORT_SYMBOL(kernel_sock_shutdown);