diff options
Diffstat (limited to 'net/unix/af_unix.c')
| -rw-r--r-- | net/unix/af_unix.c | 74 |
1 files changed, 40 insertions, 34 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 437a99e560e1..1663e1a2efdd 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -850,7 +850,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 850 | * Get the parent directory, calculate the hash for last | 850 | * Get the parent directory, calculate the hash for last |
| 851 | * component. | 851 | * component. |
| 852 | */ | 852 | */ |
| 853 | err = path_lookup(sunaddr->sun_path, LOOKUP_PARENT, &nd); | 853 | err = kern_path_parent(sunaddr->sun_path, &nd); |
| 854 | if (err) | 854 | if (err) |
| 855 | goto out_mknod_parent; | 855 | goto out_mknod_parent; |
| 856 | 856 | ||
| @@ -1124,7 +1124,7 @@ restart: | |||
| 1124 | 1124 | ||
| 1125 | /* Latch our state. | 1125 | /* Latch our state. |
| 1126 | 1126 | ||
| 1127 | It is tricky place. We need to grab write lock and cannot | 1127 | It is tricky place. We need to grab our state lock and cannot |
| 1128 | drop lock on peer. It is dangerous because deadlock is | 1128 | drop lock on peer. It is dangerous because deadlock is |
| 1129 | possible. Connect to self case and simultaneous | 1129 | possible. Connect to self case and simultaneous |
| 1130 | attempt to connect are eliminated by checking socket | 1130 | attempt to connect are eliminated by checking socket |
| @@ -1171,7 +1171,7 @@ restart: | |||
| 1171 | newsk->sk_type = sk->sk_type; | 1171 | newsk->sk_type = sk->sk_type; |
| 1172 | init_peercred(newsk); | 1172 | init_peercred(newsk); |
| 1173 | newu = unix_sk(newsk); | 1173 | newu = unix_sk(newsk); |
| 1174 | newsk->sk_wq = &newu->peer_wq; | 1174 | RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq); |
| 1175 | otheru = unix_sk(other); | 1175 | otheru = unix_sk(other); |
| 1176 | 1176 | ||
| 1177 | /* copy address information from listening to new sock*/ | 1177 | /* copy address information from listening to new sock*/ |
| @@ -1475,6 +1475,12 @@ restart: | |||
| 1475 | goto out_free; | 1475 | goto out_free; |
| 1476 | } | 1476 | } |
| 1477 | 1477 | ||
| 1478 | if (sk_filter(other, skb) < 0) { | ||
| 1479 | /* Toss the packet but do not return any error to the sender */ | ||
| 1480 | err = len; | ||
| 1481 | goto out_free; | ||
| 1482 | } | ||
| 1483 | |||
| 1478 | unix_state_lock(other); | 1484 | unix_state_lock(other); |
| 1479 | err = -EPERM; | 1485 | err = -EPERM; |
| 1480 | if (!unix_may_send(sk, other)) | 1486 | if (!unix_may_send(sk, other)) |
| @@ -1561,7 +1567,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1561 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); | 1567 | struct sock_iocb *siocb = kiocb_to_siocb(kiocb); |
| 1562 | struct sock *sk = sock->sk; | 1568 | struct sock *sk = sock->sk; |
| 1563 | struct sock *other = NULL; | 1569 | struct sock *other = NULL; |
| 1564 | struct sockaddr_un *sunaddr = msg->msg_name; | ||
| 1565 | int err, size; | 1570 | int err, size; |
| 1566 | struct sk_buff *skb; | 1571 | struct sk_buff *skb; |
| 1567 | int sent = 0; | 1572 | int sent = 0; |
| @@ -1584,7 +1589,6 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1584 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; | 1589 | err = sk->sk_state == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP; |
| 1585 | goto out_err; | 1590 | goto out_err; |
| 1586 | } else { | 1591 | } else { |
| 1587 | sunaddr = NULL; | ||
| 1588 | err = -ENOTCONN; | 1592 | err = -ENOTCONN; |
| 1589 | other = unix_peer(sk); | 1593 | other = unix_peer(sk); |
| 1590 | if (!other) | 1594 | if (!other) |
| @@ -1987,36 +1991,38 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
| 1987 | 1991 | ||
| 1988 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); | 1992 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); |
| 1989 | 1993 | ||
| 1990 | if (mode) { | 1994 | if (!mode) |
| 1991 | unix_state_lock(sk); | 1995 | return 0; |
| 1992 | sk->sk_shutdown |= mode; | 1996 | |
| 1993 | other = unix_peer(sk); | 1997 | unix_state_lock(sk); |
| 1994 | if (other) | 1998 | sk->sk_shutdown |= mode; |
| 1995 | sock_hold(other); | 1999 | other = unix_peer(sk); |
| 1996 | unix_state_unlock(sk); | 2000 | if (other) |
| 1997 | sk->sk_state_change(sk); | 2001 | sock_hold(other); |
| 1998 | 2002 | unix_state_unlock(sk); | |
| 1999 | if (other && | 2003 | sk->sk_state_change(sk); |
| 2000 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { | 2004 | |
| 2001 | 2005 | if (other && | |
| 2002 | int peer_mode = 0; | 2006 | (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_SEQPACKET)) { |
| 2003 | 2007 | ||
| 2004 | if (mode&RCV_SHUTDOWN) | 2008 | int peer_mode = 0; |
| 2005 | peer_mode |= SEND_SHUTDOWN; | 2009 | |
| 2006 | if (mode&SEND_SHUTDOWN) | 2010 | if (mode&RCV_SHUTDOWN) |
| 2007 | peer_mode |= RCV_SHUTDOWN; | 2011 | peer_mode |= SEND_SHUTDOWN; |
| 2008 | unix_state_lock(other); | 2012 | if (mode&SEND_SHUTDOWN) |
| 2009 | other->sk_shutdown |= peer_mode; | 2013 | peer_mode |= RCV_SHUTDOWN; |
| 2010 | unix_state_unlock(other); | 2014 | unix_state_lock(other); |
| 2011 | other->sk_state_change(other); | 2015 | other->sk_shutdown |= peer_mode; |
| 2012 | if (peer_mode == SHUTDOWN_MASK) | 2016 | unix_state_unlock(other); |
| 2013 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); | 2017 | other->sk_state_change(other); |
| 2014 | else if (peer_mode & RCV_SHUTDOWN) | 2018 | if (peer_mode == SHUTDOWN_MASK) |
| 2015 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); | 2019 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_HUP); |
| 2016 | } | 2020 | else if (peer_mode & RCV_SHUTDOWN) |
| 2017 | if (other) | 2021 | sk_wake_async(other, SOCK_WAKE_WAITD, POLL_IN); |
| 2018 | sock_put(other); | ||
| 2019 | } | 2022 | } |
| 2023 | if (other) | ||
| 2024 | sock_put(other); | ||
| 2025 | |||
| 2020 | return 0; | 2026 | return 0; |
| 2021 | } | 2027 | } |
| 2022 | 2028 | ||
