Commit 37a9a8df authored by Stephen Smalley's avatar Stephen Smalley Committed by David S. Miller

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: default avatarStephen Smalley <sds@tycho.nsa.gov>
Acked-by: default avatarPaul Moore <paul@paul-moore.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bae23b68
...@@ -39,7 +39,6 @@ struct unix_skb_parms { ...@@ -39,7 +39,6 @@ struct unix_skb_parms {
}; };
#define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb)) #define UNIXCB(skb) (*(struct unix_skb_parms *)&((skb)->cb))
#define UNIXSID(skb) (&UNIXCB((skb)).secid)
#define unix_state_lock(s) spin_lock(&unix_sk(s)->lock) #define unix_state_lock(s) spin_lock(&unix_sk(s)->lock)
#define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock) #define unix_state_unlock(s) spin_unlock(&unix_sk(s)->lock)
......
...@@ -140,12 +140,17 @@ static struct hlist_head *unix_sockets_unbound(void *addr) ...@@ -140,12 +140,17 @@ static struct hlist_head *unix_sockets_unbound(void *addr)
#ifdef CONFIG_SECURITY_NETWORK #ifdef CONFIG_SECURITY_NETWORK
static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{ {
memcpy(UNIXSID(skb), &scm->secid, sizeof(u32)); UNIXCB(skb).secid = scm->secid;
} }
static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{ {
scm->secid = *UNIXSID(skb); scm->secid = UNIXCB(skb).secid;
}
static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
{
return (scm->secid == UNIXCB(skb).secid);
} }
#else #else
static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) 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,6 +158,11 @@ static inline void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb)
static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb) static inline void unix_set_secdata(struct scm_cookie *scm, struct sk_buff *skb)
{ } { }
static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
{
return true;
}
#endif /* CONFIG_SECURITY_NETWORK */ #endif /* CONFIG_SECURITY_NETWORK */
/* /*
...@@ -1414,6 +1424,7 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen ...@@ -1414,6 +1424,7 @@ static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool sen
UNIXCB(skb).uid = scm->creds.uid; UNIXCB(skb).uid = scm->creds.uid;
UNIXCB(skb).gid = scm->creds.gid; UNIXCB(skb).gid = scm->creds.gid;
UNIXCB(skb).fp = NULL; UNIXCB(skb).fp = NULL;
unix_get_secdata(scm, skb);
if (scm->fp && send_fds) if (scm->fp && send_fds)
err = unix_attach_fds(scm, skb); err = unix_attach_fds(scm, skb);
...@@ -1509,7 +1520,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, ...@@ -1509,7 +1520,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
if (err < 0) if (err < 0)
goto out_free; goto out_free;
max_level = err + 1; max_level = err + 1;
unix_get_secdata(&scm, skb);
skb_put(skb, len - data_len); skb_put(skb, len - data_len);
skb->data_len = data_len; skb->data_len = data_len;
...@@ -2118,11 +2128,13 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state) ...@@ -2118,11 +2128,13 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state)
/* Never glue messages from different writers */ /* Never glue messages from different writers */
if ((UNIXCB(skb).pid != scm.pid) || if ((UNIXCB(skb).pid != scm.pid) ||
!uid_eq(UNIXCB(skb).uid, scm.creds.uid) || !uid_eq(UNIXCB(skb).uid, scm.creds.uid) ||
!gid_eq(UNIXCB(skb).gid, scm.creds.gid)) !gid_eq(UNIXCB(skb).gid, scm.creds.gid) ||
!unix_secdata_eq(&scm, skb))
break; break;
} else if (test_bit(SOCK_PASSCRED, &sock->flags)) { } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
/* Copy credentials */ /* Copy credentials */
scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid); scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
unix_set_secdata(&scm, skb);
check_creds = true; check_creds = true;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment