You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
ipc: move locking out of ipcctl_pre_down_nolock
This function currently acquires both the rw_mutex and the rcu lock on successful lookups, leaving the callers to explicitly unlock them, creating another two level locking situation. Make the callers (including those that still use ipcctl_pre_down()) explicitly lock and unlock the rwsem and rcu lock. Signed-off-by: Davidlohr Bueso <davidlohr.bueso@hp.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
committed by
Linus Torvalds
parent
cf9d5d78d0
commit
7b4cc5d841
+6
-15
@@ -746,8 +746,10 @@ int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
|
||||
* It must be called without any lock held and
|
||||
* - retrieves the ipc with the given id in the given table.
|
||||
* - performs some audit and permission check, depending on the given cmd
|
||||
* - returns the ipc with both ipc and rw_mutex locks held in case of success
|
||||
* - returns the ipc with the ipc lock held in case of success
|
||||
* or an err-code without any lock held otherwise.
|
||||
*
|
||||
* Call holding the both the rw_mutex and the rcu read lock.
|
||||
*/
|
||||
struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,
|
||||
struct ipc_ids *ids, int id, int cmd,
|
||||
@@ -772,13 +774,10 @@ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
|
||||
int err = -EPERM;
|
||||
struct kern_ipc_perm *ipcp;
|
||||
|
||||
down_write(&ids->rw_mutex);
|
||||
rcu_read_lock();
|
||||
|
||||
ipcp = ipc_obtain_object_check(ids, id);
|
||||
if (IS_ERR(ipcp)) {
|
||||
err = PTR_ERR(ipcp);
|
||||
goto out_up;
|
||||
goto err;
|
||||
}
|
||||
|
||||
audit_ipc_obj(ipcp);
|
||||
@@ -789,16 +788,8 @@ struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns,
|
||||
euid = current_euid();
|
||||
if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid) ||
|
||||
ns_capable(ns->user_ns, CAP_SYS_ADMIN))
|
||||
return ipcp;
|
||||
|
||||
out_up:
|
||||
/*
|
||||
* Unsuccessful lookup, unlock and return
|
||||
* the corresponding error.
|
||||
*/
|
||||
rcu_read_unlock();
|
||||
up_write(&ids->rw_mutex);
|
||||
|
||||
return ipcp; /* successful lookup */
|
||||
err:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user