diff options
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 45 |
1 files changed, 23 insertions, 22 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 2db702d82e7d..826e09938bff 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1340,7 +1340,6 @@ static void unix_destruct_scm(struct sk_buff *skb) | |||
1340 | struct scm_cookie scm; | 1340 | struct scm_cookie scm; |
1341 | memset(&scm, 0, sizeof(scm)); | 1341 | memset(&scm, 0, sizeof(scm)); |
1342 | scm.pid = UNIXCB(skb).pid; | 1342 | scm.pid = UNIXCB(skb).pid; |
1343 | scm.cred = UNIXCB(skb).cred; | ||
1344 | if (UNIXCB(skb).fp) | 1343 | if (UNIXCB(skb).fp) |
1345 | unix_detach_fds(&scm, skb); | 1344 | unix_detach_fds(&scm, skb); |
1346 | 1345 | ||
@@ -1391,8 +1390,8 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen | |||
1391 | int err = 0; | 1390 | int err = 0; |
1392 | 1391 | ||
1393 | UNIXCB(skb).pid = get_pid(scm->pid); | 1392 | UNIXCB(skb).pid = get_pid(scm->pid); |
1394 | if (scm->cred) | 1393 | UNIXCB(skb).uid = scm->creds.uid; |
1395 | UNIXCB(skb).cred = get_cred(scm->cred); | 1394 | UNIXCB(skb).gid = scm->creds.gid; |
1396 | UNIXCB(skb).fp = NULL; | 1395 | UNIXCB(skb).fp = NULL; |
1397 | if (scm->fp && send_fds) | 1396 | if (scm->fp && send_fds) |
1398 | err = unix_attach_fds(scm, skb); | 1397 | err = unix_attach_fds(scm, skb); |
@@ -1409,13 +1408,13 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen | |||
1409 | static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock, | 1408 | static void maybe_add_creds(struct sk_buff *skb, const struct socket *sock, |
1410 | const struct sock *other) | 1409 | const struct sock *other) |
1411 | { | 1410 | { |
1412 | if (UNIXCB(skb).cred) | 1411 | if (UNIXCB(skb).pid) |
1413 | return; | 1412 | return; |
1414 | if (test_bit(SOCK_PASSCRED, &sock->flags) || | 1413 | if (test_bit(SOCK_PASSCRED, &sock->flags) || |
1415 | !other->sk_socket || | 1414 | !other->sk_socket || |
1416 | test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) { | 1415 | test_bit(SOCK_PASSCRED, &other->sk_socket->flags)) { |
1417 | UNIXCB(skb).pid = get_pid(task_tgid(current)); | 1416 | UNIXCB(skb).pid = get_pid(task_tgid(current)); |
1418 | UNIXCB(skb).cred = get_current_cred(); | 1417 | current_uid_gid(&UNIXCB(skb).uid, &UNIXCB(skb).gid); |
1419 | } | 1418 | } |
1420 | } | 1419 | } |
1421 | 1420 | ||
@@ -1819,7 +1818,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1819 | siocb->scm = &tmp_scm; | 1818 | siocb->scm = &tmp_scm; |
1820 | memset(&tmp_scm, 0, sizeof(tmp_scm)); | 1819 | memset(&tmp_scm, 0, sizeof(tmp_scm)); |
1821 | } | 1820 | } |
1822 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); | 1821 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); |
1823 | unix_set_secdata(siocb->scm, skb); | 1822 | unix_set_secdata(siocb->scm, skb); |
1824 | 1823 | ||
1825 | if (!(flags & MSG_PEEK)) { | 1824 | if (!(flags & MSG_PEEK)) { |
@@ -1859,10 +1858,10 @@ out: | |||
1859 | } | 1858 | } |
1860 | 1859 | ||
1861 | /* | 1860 | /* |
1862 | * Sleep until data has arrive. But check for races.. | 1861 | * Sleep until more data has arrived. But check for races.. |
1863 | */ | 1862 | */ |
1864 | 1863 | static long unix_stream_data_wait(struct sock *sk, long timeo, | |
1865 | static long unix_stream_data_wait(struct sock *sk, long timeo) | 1864 | struct sk_buff *last) |
1866 | { | 1865 | { |
1867 | DEFINE_WAIT(wait); | 1866 | DEFINE_WAIT(wait); |
1868 | 1867 | ||
@@ -1871,7 +1870,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1871 | for (;;) { | 1870 | for (;;) { |
1872 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 1871 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
1873 | 1872 | ||
1874 | if (!skb_queue_empty(&sk->sk_receive_queue) || | 1873 | if (skb_peek_tail(&sk->sk_receive_queue) != last || |
1875 | sk->sk_err || | 1874 | sk->sk_err || |
1876 | (sk->sk_shutdown & RCV_SHUTDOWN) || | 1875 | (sk->sk_shutdown & RCV_SHUTDOWN) || |
1877 | signal_pending(current) || | 1876 | signal_pending(current) || |
@@ -1890,8 +1889,6 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) | |||
1890 | return timeo; | 1889 | return timeo; |
1891 | } | 1890 | } |
1892 | 1891 | ||
1893 | |||
1894 | |||
1895 | static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | 1892 | static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, |
1896 | struct msghdr *msg, size_t size, | 1893 | struct msghdr *msg, size_t size, |
1897 | int flags) | 1894 | int flags) |
@@ -1936,14 +1933,12 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1936 | goto out; | 1933 | goto out; |
1937 | } | 1934 | } |
1938 | 1935 | ||
1939 | skip = sk_peek_offset(sk, flags); | ||
1940 | |||
1941 | do { | 1936 | do { |
1942 | int chunk; | 1937 | int chunk; |
1943 | struct sk_buff *skb; | 1938 | struct sk_buff *skb, *last; |
1944 | 1939 | ||
1945 | unix_state_lock(sk); | 1940 | unix_state_lock(sk); |
1946 | skb = skb_peek(&sk->sk_receive_queue); | 1941 | last = skb = skb_peek(&sk->sk_receive_queue); |
1947 | again: | 1942 | again: |
1948 | if (skb == NULL) { | 1943 | if (skb == NULL) { |
1949 | unix_sk(sk)->recursion_level = 0; | 1944 | unix_sk(sk)->recursion_level = 0; |
@@ -1966,7 +1961,7 @@ again: | |||
1966 | break; | 1961 | break; |
1967 | mutex_unlock(&u->readlock); | 1962 | mutex_unlock(&u->readlock); |
1968 | 1963 | ||
1969 | timeo = unix_stream_data_wait(sk, timeo); | 1964 | timeo = unix_stream_data_wait(sk, timeo, last); |
1970 | 1965 | ||
1971 | if (signal_pending(current) | 1966 | if (signal_pending(current) |
1972 | || mutex_lock_interruptible(&u->readlock)) { | 1967 | || mutex_lock_interruptible(&u->readlock)) { |
@@ -1980,10 +1975,13 @@ again: | |||
1980 | break; | 1975 | break; |
1981 | } | 1976 | } |
1982 | 1977 | ||
1983 | if (skip >= skb->len) { | 1978 | skip = sk_peek_offset(sk, flags); |
1979 | while (skip >= skb->len) { | ||
1984 | skip -= skb->len; | 1980 | skip -= skb->len; |
1981 | last = skb; | ||
1985 | skb = skb_peek_next(skb, &sk->sk_receive_queue); | 1982 | skb = skb_peek_next(skb, &sk->sk_receive_queue); |
1986 | goto again; | 1983 | if (!skb) |
1984 | goto again; | ||
1987 | } | 1985 | } |
1988 | 1986 | ||
1989 | unix_state_unlock(sk); | 1987 | unix_state_unlock(sk); |
@@ -1991,11 +1989,12 @@ again: | |||
1991 | if (check_creds) { | 1989 | if (check_creds) { |
1992 | /* Never glue messages from different writers */ | 1990 | /* Never glue messages from different writers */ |
1993 | if ((UNIXCB(skb).pid != siocb->scm->pid) || | 1991 | if ((UNIXCB(skb).pid != siocb->scm->pid) || |
1994 | (UNIXCB(skb).cred != siocb->scm->cred)) | 1992 | !uid_eq(UNIXCB(skb).uid, siocb->scm->creds.uid) || |
1993 | !gid_eq(UNIXCB(skb).gid, siocb->scm->creds.gid)) | ||
1995 | break; | 1994 | break; |
1996 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { | 1995 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { |
1997 | /* Copy credentials */ | 1996 | /* Copy credentials */ |
1998 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); | 1997 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); |
1999 | check_creds = 1; | 1998 | check_creds = 1; |
2000 | } | 1999 | } |
2001 | 2000 | ||
@@ -2196,7 +2195,9 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, | |||
2196 | 2195 | ||
2197 | /* exceptional events? */ | 2196 | /* exceptional events? */ |
2198 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) | 2197 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) |
2199 | mask |= POLLERR; | 2198 | mask |= POLLERR | |
2199 | (sock_flag(sk, SOCK_SELECT_ERR_QUEUE) ? POLLPRI : 0); | ||
2200 | |||
2200 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 2201 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
2201 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; | 2202 | mask |= POLLRDHUP | POLLIN | POLLRDNORM; |
2202 | if (sk->sk_shutdown == SHUTDOWN_MASK) | 2203 | if (sk->sk_shutdown == SHUTDOWN_MASK) |