diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/msg.c | 8 | ||||
| -rw-r--r-- | ipc/namespace.c | 13 | ||||
| -rw-r--r-- | ipc/sem.c | 10 | ||||
| -rw-r--r-- | ipc/shm.c | 9 | ||||
| -rw-r--r-- | ipc/util.c | 26 | ||||
| -rw-r--r-- | ipc/util.h | 5 | 
6 files changed, 42 insertions, 29 deletions
diff --git a/ipc/msg.c b/ipc/msg.c index 747b65507a9..0e732e92e22 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -421,7 +421,7 @@ static int msgctl_down(struct ipc_namespace *ns, int msqid, int cmd,  			return -EFAULT;  	} -	ipcp = ipcctl_pre_down(&msg_ids(ns), msqid, cmd, +	ipcp = ipcctl_pre_down(ns, &msg_ids(ns), msqid, cmd,  			       &msqid64.msg_perm, msqid64.msg_qbytes);  	if (IS_ERR(ipcp))  		return PTR_ERR(ipcp); @@ -539,7 +539,7 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)  			success_return = 0;  		}  		err = -EACCES; -		if (ipcperms(&msq->q_perm, S_IRUGO)) +		if (ipcperms(ns, &msq->q_perm, S_IRUGO))  			goto out_unlock;  		err = security_msg_queue_msgctl(msq, cmd); @@ -664,7 +664,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,  		struct msg_sender s;  		err = -EACCES; -		if (ipcperms(&msq->q_perm, S_IWUGO)) +		if (ipcperms(ns, &msq->q_perm, S_IWUGO))  			goto out_unlock_free;  		err = security_msg_queue_msgsnd(msq, msg, msgflg); @@ -774,7 +774,7 @@ long do_msgrcv(int msqid, long *pmtype, void __user *mtext,  		struct list_head *tmp;  		msg = ERR_PTR(-EACCES); -		if (ipcperms(&msq->q_perm, S_IRUGO)) +		if (ipcperms(ns, &msq->q_perm, S_IRUGO))  			goto out_unlock;  		msg = ERR_PTR(-EAGAIN); diff --git a/ipc/namespace.c b/ipc/namespace.c index aa188996269..3c3e5223e7e 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -15,7 +15,8 @@  #include "util.h" -static struct ipc_namespace *create_ipc_ns(struct ipc_namespace *old_ns) +static struct ipc_namespace *create_ipc_ns(struct task_struct *tsk, +					   struct ipc_namespace *old_ns)  {  	struct ipc_namespace *ns;  	int err; @@ -44,17 +45,19 @@ static struct ipc_namespace *create_ipc_ns(struct ipc_namespace *old_ns)  	ipcns_notify(IPCNS_CREATED);  	register_ipcns_notifier(ns); -	ns->user_ns = old_ns->user_ns; -	get_user_ns(ns->user_ns); +	ns->user_ns = get_user_ns(task_cred_xxx(tsk, user)->user_ns);  	return ns;  } -struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) +struct ipc_namespace *copy_ipcs(unsigned long flags, +				struct task_struct *tsk)  { +	struct ipc_namespace *ns = tsk->nsproxy->ipc_ns; +  	if (!(flags & CLONE_NEWIPC))  		return get_ipc_ns(ns); -	return create_ipc_ns(ns); +	return create_ipc_ns(tsk, ns);  }  /* diff --git a/ipc/sem.c b/ipc/sem.c index 0e0d49bbb86..ae040a0727c 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -817,7 +817,7 @@ static int semctl_nolock(struct ipc_namespace *ns, int semid,  		}  		err = -EACCES; -		if (ipcperms (&sma->sem_perm, S_IRUGO)) +		if (ipcperms(ns, &sma->sem_perm, S_IRUGO))  			goto out_unlock;  		err = security_sem_semctl(sma, cmd); @@ -862,7 +862,8 @@ static int semctl_main(struct ipc_namespace *ns, int semid, int semnum,  	nsems = sma->sem_nsems;  	err = -EACCES; -	if (ipcperms (&sma->sem_perm, (cmd==SETVAL||cmd==SETALL)?S_IWUGO:S_IRUGO)) +	if (ipcperms(ns, &sma->sem_perm, +			(cmd == SETVAL || cmd == SETALL) ? S_IWUGO : S_IRUGO))  		goto out_unlock;  	err = security_sem_semctl(sma, cmd); @@ -1047,7 +1048,8 @@ static int semctl_down(struct ipc_namespace *ns, int semid,  			return -EFAULT;  	} -	ipcp = ipcctl_pre_down(&sem_ids(ns), semid, cmd, &semid64.sem_perm, 0); +	ipcp = ipcctl_pre_down(ns, &sem_ids(ns), semid, cmd, +			       &semid64.sem_perm, 0);  	if (IS_ERR(ipcp))  		return PTR_ERR(ipcp); @@ -1386,7 +1388,7 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,  		goto out_unlock_free;  	error = -EACCES; -	if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO)) +	if (ipcperms(ns, &sma->sem_perm, alter ? S_IWUGO : S_IRUGO))  		goto out_unlock_free;  	error = security_sem_semop(sma, sops, nsops, alter); diff --git a/ipc/shm.c b/ipc/shm.c index 7d3bb22a930..8644452f5c4 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -623,7 +623,8 @@ static int shmctl_down(struct ipc_namespace *ns, int shmid, int cmd,  			return -EFAULT;  	} -	ipcp = ipcctl_pre_down(&shm_ids(ns), shmid, cmd, &shmid64.shm_perm, 0); +	ipcp = ipcctl_pre_down(ns, &shm_ids(ns), shmid, cmd, +			       &shmid64.shm_perm, 0);  	if (IS_ERR(ipcp))  		return PTR_ERR(ipcp); @@ -737,7 +738,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)  			result = 0;  		}  		err = -EACCES; -		if (ipcperms (&shp->shm_perm, S_IRUGO)) +		if (ipcperms(ns, &shp->shm_perm, S_IRUGO))  			goto out_unlock;  		err = security_shm_shmctl(shp, cmd);  		if (err) @@ -773,7 +774,7 @@ SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)  		audit_ipc_obj(&(shp->shm_perm)); -		if (!capable(CAP_IPC_LOCK)) { +		if (!ns_capable(ns->user_ns, CAP_IPC_LOCK)) {  			uid_t euid = current_euid();  			err = -EPERM;  			if (euid != shp->shm_perm.uid && @@ -888,7 +889,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)  	}  	err = -EACCES; -	if (ipcperms(&shp->shm_perm, acc_mode)) +	if (ipcperms(ns, &shp->shm_perm, acc_mode))  		goto out_unlock;  	err = security_shm_shmat(shp, shmaddr, shmflg); diff --git a/ipc/util.c b/ipc/util.c index 69a0cc13d96..8fd1b891ec0 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -329,12 +329,14 @@ retry:   *   *	It is called with ipc_ids.rw_mutex and ipcp->lock held.   */ -static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, -			struct ipc_params *params) +static int ipc_check_perms(struct ipc_namespace *ns, +			   struct kern_ipc_perm *ipcp, +			   struct ipc_ops *ops, +			   struct ipc_params *params)  {  	int err; -	if (ipcperms(ipcp, params->flg)) +	if (ipcperms(ns, ipcp, params->flg))  		err = -EACCES;  	else {  		err = ops->associate(ipcp, params->flg); @@ -396,7 +398,7 @@ retry:  				 * ipc_check_perms returns the IPC id on  				 * success  				 */ -				err = ipc_check_perms(ipcp, ops, params); +				err = ipc_check_perms(ns, ipcp, ops, params);  		}  		ipc_unlock(ipcp);  	} @@ -610,10 +612,12 @@ void ipc_rcu_putref(void *ptr)   *   *	Check user, group, other permissions for access   *	to ipc resources. return 0 if allowed + * + * 	@flag will most probably be 0 or S_...UGO from <linux/stat.h>   */ -int ipcperms (struct kern_ipc_perm *ipcp, short flag) -{	/* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ +int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag) +{  	uid_t euid = current_euid();  	int requested_mode, granted_mode; @@ -627,7 +631,7 @@ int ipcperms (struct kern_ipc_perm *ipcp, short flag)  		granted_mode >>= 3;  	/* is there some bit set in requested_mode but not in granted_mode? */  	if ((requested_mode & ~granted_mode & 0007) &&  -	    !capable(CAP_IPC_OWNER)) +	    !ns_capable(ns->user_ns, CAP_IPC_OWNER))  		return -1;  	return security_ipc_permission(ipcp, flag); @@ -765,6 +769,7 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)  /**   * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd + * @ids:  the ipc namespace   * @ids:  the table of ids where to look for the ipc   * @id:   the id of the ipc to retrieve   * @cmd:  the cmd to check @@ -779,7 +784,8 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)   *  - returns the ipc with both ipc and rw_mutex locks held in case of success   *    or an err-code without any lock held otherwise.   */ -struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, +struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, +				      struct ipc_ids *ids, int id, int cmd,  				      struct ipc64_perm *perm, int extra_perm)  {  	struct kern_ipc_perm *ipcp; @@ -799,8 +805,8 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd,  					 perm->gid, perm->mode);  	euid = current_euid(); -	if (euid == ipcp->cuid || -	    euid == ipcp->uid  || capable(CAP_SYS_ADMIN)) +	if (euid == ipcp->cuid || euid == ipcp->uid  || +	    ns_capable(ns->user_ns, CAP_SYS_ADMIN))  		return ipcp;  	err = -EPERM; diff --git a/ipc/util.h b/ipc/util.h index 764b51a37a6..6f5c20bedaa 100644 --- a/ipc/util.h +++ b/ipc/util.h @@ -103,7 +103,7 @@ int ipc_get_maxid(struct ipc_ids *);  void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);  /* must be called with ipcp locked */ -int ipcperms(struct kern_ipc_perm *ipcp, short flg); +int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flg);  /* for rare, potentially huge allocations.   * both function can sleep @@ -126,7 +126,8 @@ struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);  void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);  void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);  void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out); -struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, +struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, +				      struct ipc_ids *ids, int id, int cmd,  				      struct ipc64_perm *perm, int extra_perm);  #ifndef __ARCH_WANT_IPC_PARSE_VERSION  |