diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2012-09-06 18:20:01 +0000 | 
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2012-09-07 14:42:05 -0400 | 
| commit | dbe9a4173ea53b72b2c35d19f676a85b69f1c9fe (patch) | |
| tree | 49952d501032a2bc303d1d646ec6b1f00773b266 /include/net/scm.h | |
| parent | d679c5324d9a87c6295f56c2dea52d5f68834f41 (diff) | |
| download | olio-linux-3.10-dbe9a4173ea53b72b2c35d19f676a85b69f1c9fe.tar.xz olio-linux-3.10-dbe9a4173ea53b72b2c35d19f676a85b69f1c9fe.zip  | |
scm: Don't use struct ucred in NETLINK_CB and struct scm_cookie.
Passing uids and gids on NETLINK_CB from a process in one user
namespace to a process in another user namespace can result in the
wrong uid or gid being presented to userspace.  Avoid that problem by
passing kuids and kgids instead.
- define struct scm_creds for use in scm_cookie and netlink_skb_parms
  that holds uid and gid information in kuid_t and kgid_t.
- Modify scm_set_cred to fill out scm_creds by heand instead of using
  cred_to_ucred to fill out struct ucred.  This conversion ensures
  userspace does not get incorrect uid or gid values to look at.
- Modify scm_recv to convert from struct scm_creds to struct ucred
  before copying credential values to userspace.
- Modify __scm_send to populate struct scm_creds on in the scm_cookie,
  instead of just copying struct ucred from userspace.
- Modify netlink_sendmsg to copy scm_creds instead of struct ucred
  into the NETLINK_CB.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net/scm.h')
| -rw-r--r-- | include/net/scm.h | 23 | 
1 files changed, 19 insertions, 4 deletions
diff --git a/include/net/scm.h b/include/net/scm.h index 7dc0854f0b3..456695f5cbc 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -12,6 +12,12 @@   */  #define SCM_MAX_FD	253 +struct scm_creds { +	u32	pid; +	kuid_t	uid; +	kgid_t	gid; +}; +  struct scm_fp_list {  	short			count;  	short			max; @@ -22,7 +28,7 @@ struct scm_cookie {  	struct pid		*pid;		/* Skb credentials */  	const struct cred	*cred;  	struct scm_fp_list	*fp;		/* Passed files		*/ -	struct ucred		creds;		/* Skb credentials	*/ +	struct scm_creds	creds;		/* Skb credentials	*/  #ifdef CONFIG_SECURITY_NETWORK  	u32			secid;		/* Passed security ID 	*/  #endif @@ -49,7 +55,9 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm,  {  	scm->pid  = get_pid(pid);  	scm->cred = cred ? get_cred(cred) : NULL; -	cred_to_ucred(pid, cred, &scm->creds); +	scm->creds.pid = pid_vnr(pid); +	scm->creds.uid = cred ? cred->euid : INVALID_UID; +	scm->creds.gid = cred ? cred->egid : INVALID_GID;  }  static __inline__ void scm_destroy_cred(struct scm_cookie *scm) @@ -112,8 +120,15 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,  		return;  	} -	if (test_bit(SOCK_PASSCRED, &sock->flags)) -		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); +	if (test_bit(SOCK_PASSCRED, &sock->flags)) { +		struct user_namespace *current_ns = current_user_ns(); +		struct ucred ucreds = { +			.pid = scm->creds.pid, +			.uid = from_kuid_munged(current_ns, scm->creds.uid), +			.gid = from_kgid_munged(current_ns, scm->creds.gid), +		}; +		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds); +	}  	scm_destroy_cred(scm);  |