diff options
Diffstat (limited to 'ipc/util.c')
-rw-r--r-- | ipc/util.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/ipc/util.c b/ipc/util.c index dc8943aa9719..c4f1d33b89e4 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -824,6 +824,57 @@ void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out) | |||
824 | | (in->mode & S_IRWXUGO); | 824 | | (in->mode & S_IRWXUGO); |
825 | } | 825 | } |
826 | 826 | ||
827 | /** | ||
828 | * ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd | ||
829 | * @ids: the table of ids where to look for the ipc | ||
830 | * @id: the id of the ipc to retrieve | ||
831 | * @cmd: the cmd to check | ||
832 | * @perm: the permission to set | ||
833 | * @extra_perm: one extra permission parameter used by msq | ||
834 | * | ||
835 | * This function does some common audit and permissions check for some IPC_XXX | ||
836 | * cmd and is called from semctl_down, shmctl_down and msgctl_down. | ||
837 | * It must be called without any lock held and | ||
838 | * - retrieves the ipc with the given id in the given table. | ||
839 | * - performs some audit and permission check, depending on the given cmd | ||
840 | * - returns the ipc with both ipc and rw_mutex locks held in case of success | ||
841 | * or an err-code without any lock held otherwise. | ||
842 | */ | ||
843 | struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | ||
844 | struct ipc64_perm *perm, int extra_perm) | ||
845 | { | ||
846 | struct kern_ipc_perm *ipcp; | ||
847 | int err; | ||
848 | |||
849 | down_write(&ids->rw_mutex); | ||
850 | ipcp = ipc_lock_check_down(ids, id); | ||
851 | if (IS_ERR(ipcp)) { | ||
852 | err = PTR_ERR(ipcp); | ||
853 | goto out_up; | ||
854 | } | ||
855 | |||
856 | err = audit_ipc_obj(ipcp); | ||
857 | if (err) | ||
858 | goto out_unlock; | ||
859 | |||
860 | if (cmd == IPC_SET) { | ||
861 | err = audit_ipc_set_perm(extra_perm, perm->uid, | ||
862 | perm->gid, perm->mode); | ||
863 | if (err) | ||
864 | goto out_unlock; | ||
865 | } | ||
866 | if (current->euid == ipcp->cuid || | ||
867 | current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) | ||
868 | return ipcp; | ||
869 | |||
870 | err = -EPERM; | ||
871 | out_unlock: | ||
872 | ipc_unlock(ipcp); | ||
873 | out_up: | ||
874 | up_write(&ids->rw_mutex); | ||
875 | return ERR_PTR(err); | ||
876 | } | ||
877 | |||
827 | #ifdef __ARCH_WANT_IPC_PARSE_VERSION | 878 | #ifdef __ARCH_WANT_IPC_PARSE_VERSION |
828 | 879 | ||
829 | 880 | ||