diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2015-06-10 08:44:59 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-06-11 01:49:20 -0400 |
commit | 37a9a8df8ce9de6ea73349c9ac8bdf6ba4ec4f70 (patch) | |
tree | 255b2d8c931e665feabf697cfd28f633f44232ea /net/unix/af_unix.c | |
parent | bae23b6840a6a15947173d8282028458dbcdeb5b (diff) |
net/unix: support SCM_SECURITY for stream sockets
SCM_SECURITY was originally only implemented for datagram sockets,
not for stream sockets. However, SCM_CREDENTIALS is supported on
Unix stream sockets. For consistency, implement Unix stream support
for SCM_SECURITY as well. Also clean up the existing code and get
rid of the superfluous UNIXSID macro.
Motivated by https://bugzilla.redhat.com/show_bug.cgi?id=1224211,
where systemd was using SCM_CREDENTIALS and assumed wrongly that
SCM_SECURITY was also supported on Unix stream sockets.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: Paul Moore <paul@paul-moore.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/unix/af_unix.c')
-rw-r--r-- | net/unix/af_unix.c | 20 |
1 files changed, 16 insertions, 4 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index f25e1675b865..03ee4d359f6a 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -140,12 +140,17 @@ static struct hlist_head *unix_sockets_unbound(void *addr) | |||
140 | #ifdef CONFIG_SECURITY_NETWORK | 140 | #ifdef CONFIG_SECURITY_NETWORK |
141 | static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) | 141 | static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) |
142 | { | 142 | { |
143 | memcpy(UNIXSID(skb), &scm->secid, sizeof(u32)); | 143 | UNIXCB(skb).secid = scm->secid; |
144 | } | 144 | } |
145 | 145 | ||
146 | static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) | 146 | static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) |
147 | { | 147 | { |
148 | scm->secid = *UNIXSID(skb); | 148 | scm->secid = UNIXCB(skb).secid; |
149 | } | ||
150 | |||
151 | static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb) | ||
152 | { | ||
153 | return (scm->secid == UNIXCB(skb).secid); | ||
149 | } | 154 | } |
150 | #else | 155 | #else |
151 | static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) | 156 | static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) |
@@ -153,6 +158,11 @@ static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) | |||
153 | 158 | ||
154 | static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) | 159 | static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) |
155 | { } | 160 | { } |
161 | |||
162 | static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb) | ||
163 | { | ||
164 | return true; | ||
165 | } | ||
156 | #endif /* CONFIG_SECURITY_NETWORK */ | 166 | #endif /* CONFIG_SECURITY_NETWORK */ |
157 | 167 | ||
158 | /* | 168 | /* |
@@ -1414,6 +1424,7 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen | |||
1414 | UNIXCB(skb).uid = scm->creds.uid; | 1424 | UNIXCB(skb).uid = scm->creds.uid; |
1415 | UNIXCB(skb).gid = scm->creds.gid; | 1425 | UNIXCB(skb).gid = scm->creds.gid; |
1416 | UNIXCB(skb).fp = NULL; | 1426 | UNIXCB(skb).fp = NULL; |
1427 | unix_get_secdata(scm, skb); | ||
1417 | if (scm->fp && send_fds) | 1428 | if (scm->fp && send_fds) |
1418 | err = unix_attach_fds(scm, skb); | 1429 | err = unix_attach_fds(scm, skb); |
1419 | 1430 | ||
@@ -1509,7 +1520,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, | |||
1509 | if (err < 0) | 1520 | if (err < 0) |
1510 | goto out_free; | 1521 | goto out_free; |
1511 | max_level = err + 1; | 1522 | max_level = err + 1; |
1512 | unix_get_secdata(&scm, skb); | ||
1513 | 1523 | ||
1514 | skb_put(skb, len - data_len); | 1524 | skb_put(skb, len - data_len); |
1515 | skb->data_len = data_len; | 1525 | skb->data_len = data_len; |
@@ -2118,11 +2128,13 @@ unlock: | |||
2118 | /* Never glue messages from different writers */ | 2128 | /* Never glue messages from different writers */ |
2119 | if ((UNIXCB(skb).pid != scm.pid) || | 2129 | if ((UNIXCB(skb).pid != scm.pid) || |
2120 | !uid_eq(UNIXCB(skb).uid, scm.creds.uid) || | 2130 | !uid_eq(UNIXCB(skb).uid, scm.creds.uid) || |
2121 | !gid_eq(UNIXCB(skb).gid, scm.creds.gid)) | 2131 | !gid_eq(UNIXCB(skb).gid, scm.creds.gid) || |
2132 | !unix_secdata_eq(&scm, skb)) | ||
2122 | break; | 2133 | break; |
2123 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { | 2134 | } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { |
2124 | /* Copy credentials */ | 2135 | /* Copy credentials */ |
2125 | scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); | 2136 | scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); |
2137 | unix_set_secdata(&scm, skb); | ||
2126 | check_creds = true; | 2138 | check_creds = true; |
2127 | } | 2139 | } |
2128 | 2140 | ||