- merge revision 1.7
authorMark Huang <mlhuang@cs.princeton.edu>
Thu, 27 Jan 2005 20:51:05 +0000 (20:51 +0000)
committerMark Huang <mlhuang@cs.princeton.edu>
Thu, 27 Jan 2005 20:51:05 +0000 (20:51 +0000)
date: 2005/01/19 22:42:27;  author: mef;  state: Exp;  lines: +33 -6
Fixes CAN-2004 security reports 1016, 1017, and 1068

net/unix/af_unix.c

index 08432ce..5deed5c 100644 (file)
@@ -147,7 +147,7 @@ static inline unsigned unix_hash_fold(unsigned hash)
        return hash&(UNIX_HASH_SIZE-1);
 }
 
-#define unix_peer(sk) ((sk)->sk_pair)
+#define unix_peer(sk) (unix_sk(sk)->peer)
 
 static inline int unix_our_peer(struct sock *sk, struct sock *osk)
 {
@@ -483,6 +483,8 @@ static int unix_dgram_recvmsg(struct kiocb *, struct socket *,
                              struct msghdr *, size_t, int);
 static int unix_dgram_connect(struct socket *, struct sockaddr *,
                              int, int);
+static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *,
+                                 struct msghdr *, size_t);
 
 static struct proto_ops unix_stream_ops = {
        .family =       PF_UNIX,
@@ -541,7 +543,7 @@ static struct proto_ops unix_seqpacket_ops = {
        .shutdown =     unix_shutdown,
        .setsockopt =   sock_no_setsockopt,
        .getsockopt =   sock_no_getsockopt,
-       .sendmsg =      unix_dgram_sendmsg,
+       .sendmsg =      unix_seqpacket_sendmsg,
        .recvmsg =      unix_dgram_recvmsg,
        .mmap =         sock_no_mmap,
        .sendpage =     sock_no_sendpage,
@@ -1378,9 +1380,11 @@ restart:
        if (other->sk_shutdown & RCV_SHUTDOWN)
                goto out_unlock;
 
-       err = security_unix_may_send(sk->sk_socket, other->sk_socket);
-       if (err)
-               goto out_unlock;
+       if (sk->sk_type != SOCK_SEQPACKET) {
+               err = security_unix_may_send(sk->sk_socket, other->sk_socket);
+               if (err)
+                       goto out_unlock;
+       }
 
        if (unix_peer(other) != sk &&
            (skb_queue_len(&other->sk_receive_queue) >
@@ -1530,6 +1534,25 @@ out_err:
        return sent ? : err;
 }
 
+static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock,
+                                 struct msghdr *msg, size_t len)
+{
+       int err;
+       struct sock *sk = sock->sk;
+       
+       err = sock_error(sk);
+       if (err)
+               return err;
+
+       if (sk->sk_state != TCP_ESTABLISHED)
+               return -ENOTCONN;
+
+       if (msg->msg_namelen)
+               msg->msg_namelen = 0;
+
+       return unix_dgram_sendmsg(kiocb, sock, msg, len);
+}
+                                                                                            
 static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
 {
        struct unix_sock *u = unix_sk(sk);
@@ -1559,9 +1582,11 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        msg->msg_namelen = 0;
 
+       down(&u->readsem);
+
        skb = skb_recv_datagram(sk, flags, noblock, &err);
        if (!skb)
-               goto out;
+               goto out_unlock;
 
        wake_up_interruptible(&u->peer_wait);
 
@@ -1611,6 +1636,8 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 out_free:
        skb_free_datagram(sk,skb);
+out_unlock:
+       up(&u->readsem);
 out:
        return err;
 }