aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix')
-rw-r--r--net/unix/af_unix.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d901465ce013..b43a27828df5 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -83,7 +83,6 @@
83 */ 83 */
84 84
85#include <linux/module.h> 85#include <linux/module.h>
86#include <linux/config.h>
87#include <linux/kernel.h> 86#include <linux/kernel.h>
88#include <linux/signal.h> 87#include <linux/signal.h>
89#include <linux/sched.h> 88#include <linux/sched.h>
@@ -118,7 +117,7 @@
118#include <net/checksum.h> 117#include <net/checksum.h>
119#include <linux/security.h> 118#include <linux/security.h>
120 119
121int sysctl_unix_max_dgram_qlen = 10; 120int sysctl_unix_max_dgram_qlen __read_mostly = 10;
122 121
123struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; 122struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1];
124DEFINE_SPINLOCK(unix_table_lock); 123DEFINE_SPINLOCK(unix_table_lock);
@@ -128,6 +127,24 @@ static atomic_t unix_nr_socks = ATOMIC_INIT(0);
128 127
129#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) 128#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE)
130 129
130#ifdef CONFIG_SECURITY_NETWORK
131static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
132{
133 memcpy(UNIXSID(skb), &scm->secid, sizeof(u32));
134}
135
136static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
137{
138 scm->secid = *UNIXSID(skb);
139}
140#else
141static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
142{ }
143
144static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
145{ }
146#endif /* CONFIG_SECURITY_NETWORK */
147
131/* 148/*
132 * SMP locking strategy: 149 * SMP locking strategy:
133 * hash table is protected with spinlock unix_table_lock 150 * hash table is protected with spinlock unix_table_lock
@@ -542,6 +559,14 @@ static struct proto unix_proto = {
542 .obj_size = sizeof(struct unix_sock), 559 .obj_size = sizeof(struct unix_sock),
543}; 560};
544 561
562/*
563 * AF_UNIX sockets do not interact with hardware, hence they
564 * dont trigger interrupts - so it's safe for them to have
565 * bh-unsafe locking for their sk_receive_queue.lock. Split off
566 * this special lock-class by reinitializing the spinlock key:
567 */
568static struct lock_class_key af_unix_sk_receive_queue_lock_key;
569
545static struct sock * unix_create1(struct socket *sock) 570static struct sock * unix_create1(struct socket *sock)
546{ 571{
547 struct sock *sk = NULL; 572 struct sock *sk = NULL;
@@ -557,6 +582,8 @@ static struct sock * unix_create1(struct socket *sock)
557 atomic_inc(&unix_nr_socks); 582 atomic_inc(&unix_nr_socks);
558 583
559 sock_init_data(sock,sk); 584 sock_init_data(sock,sk);
585 lockdep_set_class(&sk->sk_receive_queue.lock,
586 &af_unix_sk_receive_queue_lock_key);
560 587
561 sk->sk_write_space = unix_write_space; 588 sk->sk_write_space = unix_write_space;
562 sk->sk_max_ack_backlog = sysctl_unix_max_dgram_qlen; 589 sk->sk_max_ack_backlog = sysctl_unix_max_dgram_qlen;
@@ -630,11 +657,10 @@ static int unix_autobind(struct socket *sock)
630 goto out; 657 goto out;
631 658
632 err = -ENOMEM; 659 err = -ENOMEM;
633 addr = kmalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL); 660 addr = kzalloc(sizeof(*addr) + sizeof(short) + 16, GFP_KERNEL);
634 if (!addr) 661 if (!addr)
635 goto out; 662 goto out;
636 663
637 memset(addr, 0, sizeof(*addr) + sizeof(short) + 16);
638 addr->name->sun_family = AF_UNIX; 664 addr->name->sun_family = AF_UNIX;
639 atomic_set(&addr->refcnt, 1); 665 atomic_set(&addr->refcnt, 1);
640 666
@@ -1022,7 +1048,7 @@ restart:
1022 goto out_unlock; 1048 goto out_unlock;
1023 } 1049 }
1024 1050
1025 unix_state_wlock(sk); 1051 unix_state_wlock_nested(sk);
1026 1052
1027 if (sk->sk_state != st) { 1053 if (sk->sk_state != st) {
1028 unix_state_wunlock(sk); 1054 unix_state_wunlock(sk);
@@ -1290,6 +1316,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1290 memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); 1316 memcpy(UNIXCREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
1291 if (siocb->scm->fp) 1317 if (siocb->scm->fp)
1292 unix_attach_fds(siocb->scm, skb); 1318 unix_attach_fds(siocb->scm, skb);
1319 unix_get_secdata(siocb->scm, skb);
1293 1320
1294 skb->h.raw = skb->data; 1321 skb->h.raw = skb->data;
1295 err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); 1322 err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
@@ -1570,6 +1597,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1570 memset(&tmp_scm, 0, sizeof(tmp_scm)); 1597 memset(&tmp_scm, 0, sizeof(tmp_scm));
1571 } 1598 }
1572 siocb->scm->creds = *UNIXCREDS(skb); 1599 siocb->scm->creds = *UNIXCREDS(skb);
1600 unix_set_secdata(siocb->scm, skb);
1573 1601
1574 if (!(flags & MSG_PEEK)) 1602 if (!(flags & MSG_PEEK))
1575 { 1603 {
@@ -2032,10 +2060,7 @@ static int __init af_unix_init(void)
2032 int rc = -1; 2060 int rc = -1;
2033 struct sk_buff *dummy_skb; 2061 struct sk_buff *dummy_skb;
2034 2062
2035 if (sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb)) { 2063 BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof(dummy_skb->cb));
2036 printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
2037 goto out;
2038 }
2039 2064
2040 rc = proto_register(&unix_proto, 1); 2065 rc = proto_register(&unix_proto, 1);
2041 if (rc != 0) { 2066 if (rc != 0) {