aboutsummaryrefslogtreecommitdiffstats
path: root/net/unix/af_unix.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r--net/unix/af_unix.c40
1 files changed, 38 insertions, 2 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d901465ce013..f70475bfb62a 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>
@@ -128,6 +127,30 @@ 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_peersec_dgram(struct sk_buff *skb)
132{
133 int err;
134
135 err = security_socket_getpeersec_dgram(skb, UNIXSECDATA(skb),
136 UNIXSECLEN(skb));
137 if (err)
138 *(UNIXSECDATA(skb)) = NULL;
139}
140
141static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
142{
143 scm->secdata = *UNIXSECDATA(skb);
144 scm->seclen = *UNIXSECLEN(skb);
145}
146#else
147static inline void unix_get_peersec_dgram(struct sk_buff *skb)
148{ }
149
150static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
151{ }
152#endif /* CONFIG_SECURITY_NETWORK */
153
131/* 154/*
132 * SMP locking strategy: 155 * SMP locking strategy:
133 * hash table is protected with spinlock unix_table_lock 156 * hash table is protected with spinlock unix_table_lock
@@ -542,6 +565,14 @@ static struct proto unix_proto = {
542 .obj_size = sizeof(struct unix_sock), 565 .obj_size = sizeof(struct unix_sock),
543}; 566};
544 567
568/*
569 * AF_UNIX sockets do not interact with hardware, hence they
570 * dont trigger interrupts - so it's safe for them to have
571 * bh-unsafe locking for their sk_receive_queue.lock. Split off
572 * this special lock-class by reinitializing the spinlock key:
573 */
574static struct lock_class_key af_unix_sk_receive_queue_lock_key;
575
545static struct sock * unix_create1(struct socket *sock) 576static struct sock * unix_create1(struct socket *sock)
546{ 577{
547 struct sock *sk = NULL; 578 struct sock *sk = NULL;
@@ -557,6 +588,8 @@ static struct sock * unix_create1(struct socket *sock)
557 atomic_inc(&unix_nr_socks); 588 atomic_inc(&unix_nr_socks);
558 589
559 sock_init_data(sock,sk); 590 sock_init_data(sock,sk);
591 lockdep_set_class(&sk->sk_receive_queue.lock,
592 &af_unix_sk_receive_queue_lock_key);
560 593
561 sk->sk_write_space = unix_write_space; 594 sk->sk_write_space = unix_write_space;
562 sk->sk_max_ack_backlog = sysctl_unix_max_dgram_qlen; 595 sk->sk_max_ack_backlog = sysctl_unix_max_dgram_qlen;
@@ -1022,7 +1055,7 @@ restart:
1022 goto out_unlock; 1055 goto out_unlock;
1023 } 1056 }
1024 1057
1025 unix_state_wlock(sk); 1058 unix_state_wlock_nested(sk);
1026 1059
1027 if (sk->sk_state != st) { 1060 if (sk->sk_state != st) {
1028 unix_state_wunlock(sk); 1061 unix_state_wunlock(sk);
@@ -1291,6 +1324,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
1291 if (siocb->scm->fp) 1324 if (siocb->scm->fp)
1292 unix_attach_fds(siocb->scm, skb); 1325 unix_attach_fds(siocb->scm, skb);
1293 1326
1327 unix_get_peersec_dgram(skb);
1328
1294 skb->h.raw = skb->data; 1329 skb->h.raw = skb->data;
1295 err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len); 1330 err = memcpy_fromiovec(skb_put(skb,len), msg->msg_iov, len);
1296 if (err) 1331 if (err)
@@ -1570,6 +1605,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
1570 memset(&tmp_scm, 0, sizeof(tmp_scm)); 1605 memset(&tmp_scm, 0, sizeof(tmp_scm));
1571 } 1606 }
1572 siocb->scm->creds = *UNIXCREDS(skb); 1607 siocb->scm->creds = *UNIXCREDS(skb);
1608 unix_set_secdata(siocb->scm, skb);
1573 1609
1574 if (!(flags & MSG_PEEK)) 1610 if (!(flags & MSG_PEEK))
1575 { 1611 {