diff options
Diffstat (limited to 'include/net/scm.h')
| -rw-r--r-- | include/net/scm.h | 53 | 
1 files changed, 32 insertions, 21 deletions
diff --git a/include/net/scm.h b/include/net/scm.h index 745460fa2f0..262532d111f 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -12,8 +12,13 @@   */  #define SCM_MAX_FD	253 +struct scm_creds { +	u32	pid; +	kuid_t	uid; +	kgid_t	gid; +}; +  struct scm_fp_list { -	struct list_head	list;  	short			count;  	short			max;  	struct file		*fp[SCM_MAX_FD]; @@ -21,19 +26,18 @@ struct scm_fp_list {  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  }; -extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); -extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); -extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); -extern void __scm_destroy(struct scm_cookie *scm); -extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl); +void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm); +void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm); +int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm); +void __scm_destroy(struct scm_cookie *scm); +struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl);  #ifdef CONFIG_SECURITY_NETWORK  static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm) @@ -46,35 +50,35 @@ static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_co  #endif /* CONFIG_SECURITY_NETWORK */  static __inline__ void scm_set_cred(struct scm_cookie *scm, -				    struct pid *pid, const struct cred *cred) +				    struct pid *pid, kuid_t uid, kgid_t gid)  {  	scm->pid  = get_pid(pid); -	scm->cred = get_cred(cred); -	cred_to_ucred(pid, cred, &scm->creds); +	scm->creds.pid = pid_vnr(pid); +	scm->creds.uid = uid; +	scm->creds.gid = gid;  }  static __inline__ void scm_destroy_cred(struct scm_cookie *scm)  {  	put_pid(scm->pid);  	scm->pid  = NULL; - -	if (scm->cred) -		put_cred(scm->cred); -	scm->cred = NULL;  }  static __inline__ void scm_destroy(struct scm_cookie *scm)  {  	scm_destroy_cred(scm); -	if (scm && scm->fp) +	if (scm->fp)  		__scm_destroy(scm);  }  static __inline__ int scm_send(struct socket *sock, struct msghdr *msg, -			       struct scm_cookie *scm) +			       struct scm_cookie *scm, bool forcecreds)  { -	scm_set_cred(scm, task_tgid(current), current_cred()); -	scm->fp = NULL; +	memset(scm, 0, sizeof(*scm)); +	scm->creds.uid = INVALID_UID; +	scm->creds.gid = INVALID_GID; +	if (forcecreds) +		scm_set_cred(scm, task_tgid(current), current_uid(), current_gid());  	unix_get_peersec_dgram(sock, scm);  	if (msg->msg_controllen <= 0)  		return 0; @@ -112,8 +116,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);  | 
