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 @@ unlock:
 | 
				
			||||||
			/* 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue