aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/scm.h22
-rw-r--r--net/unix/af_unix.c45
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
56static __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
64static __inline__ void scm_destroy_cred(struct scm_cookie *scm) 56static __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
81static __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
90static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, 73static __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
1381static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, 1381static 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
1556out_unlock: 1550out_unlock:
@@ -1560,8 +1554,7 @@ out_free:
1560out: 1554out:
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;
1685out_err: 1675out_err:
1686 if (skb == NULL) 1676 scm_destroy(siocb->scm);
1687 scm_destroy(siocb->scm);
1688out:
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