diff options
Diffstat (limited to 'ipc/util.c')
-rw-r--r-- | ipc/util.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/ipc/util.c b/ipc/util.c index 813804ebdeba..3df0af3158a5 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -824,11 +824,28 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, | |||
824 | struct ipc64_perm *perm, int extra_perm) | 824 | struct ipc64_perm *perm, int extra_perm) |
825 | { | 825 | { |
826 | struct kern_ipc_perm *ipcp; | 826 | struct kern_ipc_perm *ipcp; |
827 | |||
828 | ipcp = ipcctl_pre_down_nolock(ns, ids, id, cmd, perm, extra_perm); | ||
829 | if (IS_ERR(ipcp)) | ||
830 | goto out; | ||
831 | |||
832 | spin_lock(&ipcp->lock); | ||
833 | out: | ||
834 | return ipcp; | ||
835 | } | ||
836 | |||
837 | struct kern_ipc_perm *ipcctl_pre_down_nolock(struct ipc_namespace *ns, | ||
838 | struct ipc_ids *ids, int id, int cmd, | ||
839 | struct ipc64_perm *perm, int extra_perm) | ||
840 | { | ||
827 | kuid_t euid; | 841 | kuid_t euid; |
828 | int err; | 842 | int err = -EPERM; |
843 | struct kern_ipc_perm *ipcp; | ||
829 | 844 | ||
830 | down_write(&ids->rw_mutex); | 845 | down_write(&ids->rw_mutex); |
831 | ipcp = ipc_lock_check(ids, id); | 846 | rcu_read_lock(); |
847 | |||
848 | ipcp = ipc_obtain_object_check(ids, id); | ||
832 | if (IS_ERR(ipcp)) { | 849 | if (IS_ERR(ipcp)) { |
833 | err = PTR_ERR(ipcp); | 850 | err = PTR_ERR(ipcp); |
834 | goto out_up; | 851 | goto out_up; |
@@ -837,17 +854,21 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, | |||
837 | audit_ipc_obj(ipcp); | 854 | audit_ipc_obj(ipcp); |
838 | if (cmd == IPC_SET) | 855 | if (cmd == IPC_SET) |
839 | audit_ipc_set_perm(extra_perm, perm->uid, | 856 | audit_ipc_set_perm(extra_perm, perm->uid, |
840 | perm->gid, perm->mode); | 857 | perm->gid, perm->mode); |
841 | 858 | ||
842 | euid = current_euid(); | 859 | euid = current_euid(); |
843 | if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid) || | 860 | if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid) || |
844 | ns_capable(ns->user_ns, CAP_SYS_ADMIN)) | 861 | ns_capable(ns->user_ns, CAP_SYS_ADMIN)) |
845 | return ipcp; | 862 | return ipcp; |
846 | 863 | ||
847 | err = -EPERM; | ||
848 | ipc_unlock(ipcp); | ||
849 | out_up: | 864 | out_up: |
865 | /* | ||
866 | * Unsuccessful lookup, unlock and return | ||
867 | * the corresponding error. | ||
868 | */ | ||
869 | rcu_read_unlock(); | ||
850 | up_write(&ids->rw_mutex); | 870 | up_write(&ids->rw_mutex); |
871 | |||
851 | return ERR_PTR(err); | 872 | return ERR_PTR(err); |
852 | } | 873 | } |
853 | 874 | ||