IPC_SEM_IDS, sysvipc_sem_proc_show);
}
-/*
- * This routine is called in the paths where the rw_mutex is held to protect
- * access to the idr tree.
- */
-static inline struct sem_array *sem_lock_check_down(struct ipc_namespace *ns,
- int id)
-{
- struct kern_ipc_perm *ipcp = ipc_lock_check_down(&sem_ids(ns), id);
-
- if (IS_ERR(ipcp))
- return (struct sem_array *)ipcp;
-
- return container_of(ipcp, struct sem_array, sem_perm);
-}
-
/*
* sem_lock_(check_) routines are called in the paths where the rw_mutex
* is not held.
if (copy_semid_from_user(&semid64, arg.buf, version))
return -EFAULT;
}
- down_write(&sem_ids(ns).rw_mutex);
- sma = sem_lock_check_down(ns, semid);
- if (IS_ERR(sma)) {
- err = PTR_ERR(sma);
- goto out_up;
- }
-
- ipcp = &sma->sem_perm;
- err = audit_ipc_obj(ipcp);
- if (err)
- goto out_unlock;
+ ipcp = ipcctl_pre_down(&sem_ids(ns), semid, cmd, &semid64.sem_perm, 0);
+ if (IS_ERR(ipcp))
+ return PTR_ERR(ipcp);
- if (cmd == IPC_SET) {
- err = audit_ipc_set_perm(0, semid64.sem_perm.uid,
- semid64.sem_perm.gid,
- semid64.sem_perm.mode);
- if (err)
- goto out_unlock;
- }
- if (current->euid != ipcp->cuid &&
- current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
- err=-EPERM;
- goto out_unlock;
- }
+ sma = container_of(ipcp, struct sem_array, sem_perm);
err = security_sem_semctl(sma, cmd);
if (err)
freeary(ns, ipcp);
goto out_up;
case IPC_SET:
- ipcp->uid = semid64.sem_perm.uid;
- ipcp->gid = semid64.sem_perm.gid;
- ipcp->mode = (ipcp->mode & ~S_IRWXUGO)
- | (semid64.sem_perm.mode & S_IRWXUGO);
+ ipc_update_perm(&semid64.sem_perm, ipcp);
sma->sem_ctime = get_seconds();
break;
default:
undo_list = tsk->sysvsem.undo_list;
if (!undo_list)
return;
+ tsk->sysvsem.undo_list = NULL;
if (!atomic_dec_and_test(&undo_list->refcnt))
return;