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>
This commit is contained in:
parent
bae23b6840
commit
37a9a8df8c
2 changed files with 16 additions and 5 deletions
|
@ -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)
|
||||||
#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)
|
||||||
|
|
||||||
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
|
||||||
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,
|
||||||
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)
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue