diff options
Diffstat (limited to 'ipc/util.c')
| -rw-r--r-- | ipc/util.c | 35 | 
1 files changed, 21 insertions, 14 deletions
diff --git a/ipc/util.c b/ipc/util.c index eb07fd356f2..72fd0785ac9 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -249,8 +249,8 @@ int ipc_get_maxid(struct ipc_ids *ids)  int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)  { -	uid_t euid; -	gid_t egid; +	kuid_t euid; +	kgid_t egid;  	int id, err;  	if (size > IPCMNI) @@ -606,14 +606,14 @@ void ipc_rcu_putref(void *ptr)  int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)  { -	uid_t euid = current_euid(); +	kuid_t euid = current_euid();  	int requested_mode, granted_mode;  	audit_ipc_obj(ipcp);  	requested_mode = (flag >> 6) | (flag >> 3) | flag;  	granted_mode = ipcp->mode; -	if (euid == ipcp->cuid || -	    euid == ipcp->uid) +	if (uid_eq(euid, ipcp->cuid) || +	    uid_eq(euid, ipcp->uid))  		granted_mode >>= 6;  	else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))  		granted_mode >>= 3; @@ -643,10 +643,10 @@ int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)  void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)  {  	out->key	= in->key; -	out->uid	= in->uid; -	out->gid	= in->gid; -	out->cuid	= in->cuid; -	out->cgid	= in->cgid; +	out->uid	= from_kuid_munged(current_user_ns(), in->uid); +	out->gid	= from_kgid_munged(current_user_ns(), in->gid); +	out->cuid	= from_kuid_munged(current_user_ns(), in->cuid); +	out->cgid	= from_kgid_munged(current_user_ns(), in->cgid);  	out->mode	= in->mode;  	out->seq	= in->seq;  } @@ -747,12 +747,19 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,   * @in:  the permission given as input.   * @out: the permission of the ipc to set.   */ -void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out) +int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)  { -	out->uid = in->uid; -	out->gid = in->gid; +	kuid_t uid = make_kuid(current_user_ns(), in->uid); +	kgid_t gid = make_kgid(current_user_ns(), in->gid); +	if (!uid_valid(uid) || !gid_valid(gid)) +		return -EINVAL; + +	out->uid = uid; +	out->gid = gid;  	out->mode = (out->mode & ~S_IRWXUGO)  		| (in->mode & S_IRWXUGO); + +	return 0;  }  /** @@ -777,7 +784,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,  				      struct ipc64_perm *perm, int extra_perm)  {  	struct kern_ipc_perm *ipcp; -	uid_t euid; +	kuid_t euid;  	int err;  	down_write(&ids->rw_mutex); @@ -793,7 +800,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,  					 perm->gid, perm->mode);  	euid = current_euid(); -	if (euid == ipcp->cuid || euid == ipcp->uid  || +	if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid)  ||  	    ns_capable(ns->user_ns, CAP_SYS_ADMIN))  		return ipcp;  |