diff options
-rw-r--r-- | include/net/scm.h | 22 | ||||
-rw-r--r-- | net/unix/af_unix.c | 45 |
2 files changed, 19 insertions, 48 deletions
diff --git a/include/net/scm.h b/include/net/scm.h index 68e1e481658e..745460fa2f02 100644 --- a/include/net/scm.h +++ b/include/net/scm.h | |||
@@ -53,14 +53,6 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, | |||
53 | cred_to_ucred(pid, cred, &scm->creds); | 53 | cred_to_ucred(pid, cred, &scm->creds); |
54 | } | 54 | } |
55 | 55 | ||
56 | static __inline__ void scm_set_cred_noref(struct scm_cookie *scm, | ||
57 | struct pid *pid, const struct cred *cred) | ||
58 | { | ||
59 | scm->pid = pid; | ||
60 | scm->cred = cred; | ||
61 | cred_to_ucred(pid, cred, &scm->creds); | ||
62 | } | ||
63 | |||
64 | static __inline__ void scm_destroy_cred(struct scm_cookie *scm) | 56 | static __inline__ void scm_destroy_cred(struct scm_cookie *scm) |
65 | { | 57 | { |
66 | put_pid(scm->pid); | 58 | put_pid(scm->pid); |
@@ -78,15 +70,6 @@ static __inline__ void scm_destroy(struct scm_cookie *scm) | |||
78 | __scm_destroy(scm); | 70 | __scm_destroy(scm); |
79 | } | 71 | } |
80 | 72 | ||
81 | static __inline__ void scm_release(struct scm_cookie *scm) | ||
82 | { | ||
83 | /* keep ref on pid and cred */ | ||
84 | scm->pid = NULL; | ||
85 | scm->cred = NULL; | ||
86 | if (scm->fp) | ||
87 | __scm_destroy(scm); | ||
88 | } | ||
89 | |||
90 | static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, | 73 | static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, |
91 | struct scm_cookie *scm) | 74 | struct scm_cookie *scm) |
92 | { | 75 | { |
@@ -125,14 +108,15 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, | |||
125 | if (!msg->msg_control) { | 108 | if (!msg->msg_control) { |
126 | if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) | 109 | if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) |
127 | msg->msg_flags |= MSG_CTRUNC; | 110 | msg->msg_flags |= MSG_CTRUNC; |
128 | if (scm && scm->fp) | 111 | scm_destroy(scm); |
129 | __scm_destroy(scm); | ||
130 | return; | 112 | return; |
131 | } | 113 | } |
132 | 114 | ||
133 | if (test_bit(SOCK_PASSCRED, &sock->flags)) | 115 | if (test_bit(SOCK_PASSCRED, &sock->flags)) |
134 | put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); | 116 | put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); |
135 | 117 | ||
118 | scm_destroy_cred(scm); | ||
119 | |||
136 | scm_passec(sock, msg, scm); | 120 | scm_passec(sock, msg, scm); |
137 | 121 | ||
138 | if (!scm->fp) | 122 | if (!scm->fp) |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e6d9d1014ed2..ec68e1c05b85 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1378,17 +1378,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) | |||
1378 | return max_level; | 1378 | return max_level; |
1379 | } | 1379 | } |
1380 | 1380 | ||
1381 | static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, | 1381 | static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds) |
1382 | bool send_fds, bool ref) | ||
1383 | { | 1382 | { |
1384 | int err = 0; | 1383 | int err = 0; |
1385 | if (ref) { | 1384 | UNIXCB(skb).pid = get_pid(scm->pid); |
1386 | UNIXCB(skb).pid = get_pid(scm->pid); | 1385 | UNIXCB(skb).cred = get_cred(scm->cred); |
1387 | UNIXCB(skb).cred = get_cred(scm->cred); | ||
1388 | } else { | ||
1389 | UNIXCB(skb).pid = scm->pid; | ||
1390 | UNIXCB(skb).cred = scm->cred; | ||
1391 | } | ||
1392 | UNIXCB(skb).fp = NULL; | 1386 | UNIXCB(skb).fp = NULL; |
1393 | if (scm->fp && send_fds) | 1387 | if (scm->fp && send_fds) |
1394 | err = unix_attach_fds(scm, skb); | 1388 | err = unix_attach_fds(scm, skb); |
@@ -1413,7 +1407,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1413 | int namelen = 0; /* fake GCC */ | 1407 | int namelen = 0; /* fake GCC */ |
1414 | int err; | 1408 | int err; |
1415 | unsigned hash; | 1409 | unsigned hash; |
1416 | struct sk_buff *skb = NULL; | 1410 | struct sk_buff *skb; |
1417 | long timeo; | 1411 | long timeo; |
1418 | struct scm_cookie tmp_scm; | 1412 | struct scm_cookie tmp_scm; |
1419 | int max_level; | 1413 | int max_level; |
@@ -1454,7 +1448,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1454 | if (skb == NULL) | 1448 | if (skb == NULL) |
1455 | goto out; | 1449 | goto out; |
1456 | 1450 | ||
1457 | err = unix_scm_to_skb(siocb->scm, skb, true, false); | 1451 | err = unix_scm_to_skb(siocb->scm, skb, true); |
1458 | if (err < 0) | 1452 | if (err < 0) |
1459 | goto out_free; | 1453 | goto out_free; |
1460 | max_level = err + 1; | 1454 | max_level = err + 1; |
@@ -1550,7 +1544,7 @@ restart: | |||
1550 | unix_state_unlock(other); | 1544 | unix_state_unlock(other); |
1551 | other->sk_data_ready(other, len); | 1545 | other->sk_data_ready(other, len); |
1552 | sock_put(other); | 1546 | sock_put(other); |
1553 | scm_release(siocb->scm); | 1547 | scm_destroy(siocb->scm); |
1554 | return len; | 1548 | return len; |
1555 | 1549 | ||
1556 | out_unlock: | 1550 | out_unlock: |
@@ -1560,8 +1554,7 @@ out_free: | |||
1560 | out: | 1554 | out: |
1561 | if (other) | 1555 | if (other) |
1562 | sock_put(other); | 1556 | sock_put(other); |
1563 | if (skb == NULL) | 1557 | scm_destroy(siocb->scm); |
1564 | scm_destroy(siocb->scm); | ||
1565 | return err; | 1558 | return err; |
1566 | } | 1559 | } |
1567 | 1560 | ||
@@ -1573,7 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1573 | struct sock *sk = sock->sk; | 1566 | struct sock *sk = sock->sk; |
1574 | struct sock *other = NULL; | 1567 | struct sock *other = NULL; |
1575 | int err, size; | 1568 | int err, size; |
1576 | struct sk_buff *skb = NULL; | 1569 | struct sk_buff *skb; |
1577 | int sent = 0; | 1570 | int sent = 0; |
1578 | struct scm_cookie tmp_scm; | 1571 | struct scm_cookie tmp_scm; |
1579 | bool fds_sent = false; | 1572 | bool fds_sent = false; |
@@ -1638,11 +1631,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1638 | size = min_t(int, size, skb_tailroom(skb)); | 1631 | size = min_t(int, size, skb_tailroom(skb)); |
1639 | 1632 | ||
1640 | 1633 | ||
1641 | /* Only send the fds and no ref to pid in the first buffer */ | 1634 | /* Only send the fds in the first buffer */ |
1642 | err = unix_scm_to_skb(siocb->scm, skb, !fds_sent, fds_sent); | 1635 | err = unix_scm_to_skb(siocb->scm, skb, !fds_sent); |
1643 | if (err < 0) { | 1636 | if (err < 0) { |
1644 | kfree_skb(skb); | 1637 | kfree_skb(skb); |
1645 | goto out; | 1638 | goto out_err; |
1646 | } | 1639 | } |
1647 | max_level = err + 1; | 1640 | max_level = err + 1; |
1648 | fds_sent = true; | 1641 | fds_sent = true; |
@@ -1650,7 +1643,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1650 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); | 1643 | err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size); |
1651 | if (err) { | 1644 | if (err) { |
1652 | kfree_skb(skb); | 1645 | kfree_skb(skb); |
1653 | goto out; | 1646 | goto out_err; |
1654 | } | 1647 | } |
1655 | 1648 | ||
1656 | unix_state_lock(other); | 1649 | unix_state_lock(other); |
@@ -1667,10 +1660,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1667 | sent += size; | 1660 | sent += size; |
1668 | } | 1661 | } |
1669 | 1662 | ||
1670 | if (skb) | 1663 | scm_destroy(siocb->scm); |
1671 | scm_release(siocb->scm); | ||
1672 | else | ||
1673 | scm_destroy(siocb->scm); | ||
1674 | siocb->scm = NULL; | 1664 | siocb->scm = NULL; |
1675 | 1665 | ||
1676 | return sent; | 1666 | return sent; |
@@ -1683,9 +1673,7 @@ pipe_err: | |||
1683 | send_sig(SIGPIPE, current, 0); | 1673 | send_sig(SIGPIPE, current, 0); |
1684 | err = -EPIPE; | 1674 | err = -EPIPE; |
1685 | out_err: | 1675 | out_err: |
1686 | if (skb == NULL) | 1676 | scm_destroy(siocb->scm); |
1687 | scm_destroy(siocb->scm); | ||
1688 | out: | ||
1689 | siocb->scm = NULL; | 1677 | siocb->scm = NULL; |
1690 | return sent ? : err; | 1678 | return sent ? : err; |
1691 | } | 1679 | } |
@@ -1789,7 +1777,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1789 | siocb->scm = &tmp_scm; | 1777 | siocb->scm = &tmp_scm; |
1790 | memset(&tmp_scm, 0, sizeof(tmp_scm)); | 1778 | memset(&tmp_scm, 0, sizeof(tmp_scm)); |
1791 | } | 1779 | } |
1792 | scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); | 1780 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); |
1793 | unix_set_secdata(siocb->scm, skb); | 1781 | unix_set_secdata(siocb->scm, skb); |
1794 | 1782 | ||
1795 | if (!(flags & MSG_PEEK)) { | 1783 | if (!(flags & MSG_PEEK)) { |
@@ -1951,8 +1939,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
1951 | } | 1939 | } |
1952 | } else { | 1940 | } else { |
1953 | /* Copy credentials */ | 1941 | /* Copy credentials */ |
1954 | scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, | 1942 | scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); |
1955 | UNIXCB(skb).cred); | ||
1956 | check_creds = 1; | 1943 | check_creds = 1; |
1957 | } | 1944 | } |
1958 | 1945 | ||