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: unix: fix sending fds in multiple buffers
[safe/jmp/linux-2.6]
/
net
/
unix
/
af_unix.c
diff --git
a/net/unix/af_unix.c
b/net/unix/af_unix.c
index
58db2a2
..
51ab497
100644
(file)
--- a/
net/unix/af_unix.c
+++ b/
net/unix/af_unix.c
@@
-216,7
+216,7
@@
static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp)
return len;
}
return len;
}
- *hashp = unix_hash_fold(csum_partial(
(char *)
sunaddr, len, 0));
+ *hashp = unix_hash_fold(csum_partial(sunaddr, len, 0));
return len;
}
return len;
}
@@
-315,7
+315,7
@@
static void unix_write_space(struct sock *sk)
{
read_lock(&sk->sk_callback_lock);
if (unix_writable(sk)) {
{
read_lock(&sk->sk_callback_lock);
if (unix_writable(sk)) {
- if (sk
->sk_sleep && waitqueue_active(sk->sk_sleep
))
+ if (sk
_has_sleeper(sk
))
wake_up_interruptible_sync(sk->sk_sleep);
sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
}
wake_up_interruptible_sync(sk->sk_sleep);
sk_wake_async(sk, SOCK_WAKE_SPACE, POLL_OUT);
}
@@
-353,7
+353,7
@@
static void unix_sock_destructor(struct sock *sk)
WARN_ON(!sk_unhashed(sk));
WARN_ON(sk->sk_socket);
if (!sock_flag(sk, SOCK_DEAD)) {
WARN_ON(!sk_unhashed(sk));
WARN_ON(sk->sk_socket);
if (!sock_flag(sk, SOCK_DEAD)) {
- printk(KERN_
DEBUG
"Attempt to release alive unix socket: %p\n", sk);
+ printk(KERN_
INFO
"Attempt to release alive unix socket: %p\n", sk);
return;
}
return;
}
@@
-361,6
+361,9
@@
static void unix_sock_destructor(struct sock *sk)
unix_release_addr(u->addr);
atomic_dec(&unix_nr_socks);
unix_release_addr(u->addr);
atomic_dec(&unix_nr_socks);
+ local_bh_disable();
+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
+ local_bh_enable();
#ifdef UNIX_REFCNT_DEBUG
printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk,
atomic_read(&unix_nr_socks));
#ifdef UNIX_REFCNT_DEBUG
printk(KERN_DEBUG "UNIX %p is destroyed, %d are still alive.\n", sk,
atomic_read(&unix_nr_socks));
@@
-467,8
+470,7
@@
static int unix_listen(struct socket *sock, int backlog)
sk->sk_state = TCP_LISTEN;
/* set credentials so connect can copy them */
sk->sk_peercred.pid = task_tgid_vnr(current);
sk->sk_state = TCP_LISTEN;
/* set credentials so connect can copy them */
sk->sk_peercred.pid = task_tgid_vnr(current);
- sk->sk_peercred.uid = current->euid;
- sk->sk_peercred.gid = current->egid;
+ current_euid_egid(&sk->sk_peercred.uid, &sk->sk_peercred.gid);
err = 0;
out_unlock:
err = 0;
out_unlock:
@@
-566,9
+568,9
@@
static const struct proto_ops unix_seqpacket_ops = {
};
static struct proto unix_proto = {
};
static struct proto unix_proto = {
- .name = "UNIX",
- .owner = THIS_MODULE,
- .obj_size = sizeof(struct unix_sock),
+ .name
= "UNIX",
+ .owner
= THIS_MODULE,
+ .obj_size
= sizeof(struct unix_sock),
};
/*
};
/*
@@
-611,6
+613,11
@@
static struct sock *unix_create1(struct net *net, struct socket *sock)
out:
if (sk == NULL)
atomic_dec(&unix_nr_socks);
out:
if (sk == NULL)
atomic_dec(&unix_nr_socks);
+ else {
+ local_bh_disable();
+ sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
+ local_bh_enable();
+ }
return sk;
}
return sk;
}
@@
-681,7
+688,7
@@
static int unix_autobind(struct socket *sock)
retry:
addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
retry:
addr->len = sprintf(addr->name->sun_path+1, "%05x", ordernum) + 1 + sizeof(short);
- addr->hash = unix_hash_fold(csum_partial(
(void *)
addr->name, addr->len, 0));
+ addr->hash = unix_hash_fold(csum_partial(addr->name, addr->len, 0));
spin_lock(&unix_table_lock);
ordernum = (ordernum+1)&0xFFFFF;
spin_lock(&unix_table_lock);
ordernum = (ordernum+1)&0xFFFFF;
@@
-825,11
+832,15
@@
static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
* All right, let's create it.
*/
mode = S_IFSOCK |
* All right, let's create it.
*/
mode = S_IFSOCK |
- (SOCK_INODE(sock)->i_mode & ~current
->fs->umask
);
+ (SOCK_INODE(sock)->i_mode & ~current
_umask()
);
err = mnt_want_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
err = mnt_want_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
+ err = security_path_mknod(&nd.path, dentry, mode, 0);
+ if (err)
+ goto out_mknod_drop_write;
err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0);
+out_mknod_drop_write:
mnt_drop_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
mnt_drop_write(nd.path.mnt);
if (err)
goto out_mknod_dput;
@@
-1126,8
+1137,7
@@
restart:
newsk->sk_state = TCP_ESTABLISHED;
newsk->sk_type = sk->sk_type;
newsk->sk_peercred.pid = task_tgid_vnr(current);
newsk->sk_state = TCP_ESTABLISHED;
newsk->sk_type = sk->sk_type;
newsk->sk_peercred.pid = task_tgid_vnr(current);
- newsk->sk_peercred.uid = current->euid;
- newsk->sk_peercred.gid = current->egid;
+ current_euid_egid(&newsk->sk_peercred.uid, &newsk->sk_peercred.gid);
newu = unix_sk(newsk);
newsk->sk_sleep = &newu->peer_wait;
otheru = unix_sk(other);
newu = unix_sk(newsk);
newsk->sk_sleep = &newu->peer_wait;
otheru = unix_sk(other);
@@
-1168,8
+1178,7
@@
out_unlock:
unix_state_unlock(other);
out:
unix_state_unlock(other);
out:
- if (skb)
- kfree_skb(skb);
+ kfree_skb(skb);
if (newsk)
unix_release_sock(newsk, 0);
if (other)
if (newsk)
unix_release_sock(newsk, 0);
if (other)
@@
-1187,8
+1196,9
@@
static int unix_socketpair(struct socket *socka, struct socket *sockb)
unix_peer(ska) = skb;
unix_peer(skb) = ska;
ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current);
unix_peer(ska) = skb;
unix_peer(skb) = ska;
ska->sk_peercred.pid = skb->sk_peercred.pid = task_tgid_vnr(current);
- ska->sk_peercred.uid = skb->sk_peercred.uid = current->euid;
- ska->sk_peercred.gid = skb->sk_peercred.gid = current->egid;
+ current_euid_egid(&skb->sk_peercred.uid, &skb->sk_peercred.gid);
+ ska->sk_peercred.uid = skb->sk_peercred.uid;
+ ska->sk_peercred.gid = skb->sk_peercred.gid;
if (ska->sk_type != SOCK_DGRAM) {
ska->sk_state = TCP_ESTABLISHED;
if (ska->sk_type != SOCK_DGRAM) {
ska->sk_state = TCP_ESTABLISHED;
@@
-1343,6
+1353,7
@@
static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
+ wait_for_unix_gc();
err = scm_send(sock, msg, siocb->scm);
if (err < 0)
return err;
err = scm_send(sock, msg, siocb->scm);
if (err < 0)
return err;
@@
-1490,9
+1501,11
@@
static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct sk_buff *skb;
int sent = 0;
struct scm_cookie tmp_scm;
struct sk_buff *skb;
int sent = 0;
struct scm_cookie tmp_scm;
+ bool fds_sent = false;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
+ wait_for_unix_gc();
err = scm_send(sock, msg, siocb->scm);
if (err < 0)
return err;
err = scm_send(sock, msg, siocb->scm);
if (err < 0)
return err;
@@
-1550,12
+1563,14
@@
static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
size = min_t(int, size, skb_tailroom(skb));
memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
size = min_t(int, size, skb_tailroom(skb));
memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
- if (siocb->scm->fp) {
+ /* Only send the fds in the first buffer */
+ if (siocb->scm->fp && !fds_sent) {
err = unix_attach_fds(siocb->scm, skb);
if (err) {
kfree_skb(skb);
goto out_err;
}
err = unix_attach_fds(siocb->scm, skb);
if (err) {
kfree_skb(skb);
goto out_err;
}
+ fds_sent = true;
}
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
}
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
@@
-1934,7
+1949,7
@@
static int unix_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
switch (cmd) {
case SIOCOUTQ:
switch (cmd) {
case SIOCOUTQ:
- amount =
atomic_read(&sk->sk_wmem_alloc
);
+ amount =
sk_wmem_alloc_get(sk
);
err = put_user(amount, (int __user *)arg);
break;
case SIOCINQ:
err = put_user(amount, (int __user *)arg);
break;
case SIOCINQ:
@@
-1973,7
+1988,7
@@
static unsigned int unix_poll(struct file *file, struct socket *sock, poll_table
struct sock *sk = sock->sk;
unsigned int mask;
struct sock *sk = sock->sk;
unsigned int mask;
- poll_wait(file, sk->sk_sleep, wait);
+
sock_
poll_wait(file, sk->sk_sleep, wait);
mask = 0;
/* exceptional events? */
mask = 0;
/* exceptional events? */
@@
-2010,7
+2025,7
@@
static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
struct sock *sk = sock->sk, *other;
unsigned int mask, writable;
struct sock *sk = sock->sk, *other;
unsigned int mask, writable;
- poll_wait(file, sk->sk_sleep, wait);
+
sock_
poll_wait(file, sk->sk_sleep, wait);
mask = 0;
/* exceptional events? */
mask = 0;
/* exceptional events? */
@@
-2041,7
+2056,7
@@
static unsigned int unix_dgram_poll(struct file *file, struct socket *sock,
other = unix_peer_get(sk);
if (other) {
if (unix_peer(other) != sk) {
other = unix_peer_get(sk);
if (other) {
if (unix_peer(other) != sk) {
- poll_wait(file, &unix_sk(other)->peer_wait,
+
sock_
poll_wait(file, &unix_sk(other)->peer_wait,
wait);
if (unix_recvq_full(other))
writable = 0;
wait);
if (unix_recvq_full(other))
writable = 0;