diff options
Diffstat (limited to 'ipc/util.c')
-rw-r--r-- | ipc/util.c | 35 |
1 files changed, 21 insertions, 14 deletions
diff --git a/ipc/util.c b/ipc/util.c index eb07fd356f27..72fd0785ac94 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -249,8 +249,8 @@ int ipc_get_maxid(struct ipc_ids *ids) | |||
249 | 249 | ||
250 | int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | 250 | int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) |
251 | { | 251 | { |
252 | uid_t euid; | 252 | kuid_t euid; |
253 | gid_t egid; | 253 | kgid_t egid; |
254 | int id, err; | 254 | int id, err; |
255 | 255 | ||
256 | if (size > IPCMNI) | 256 | if (size > IPCMNI) |
@@ -606,14 +606,14 @@ void ipc_rcu_putref(void *ptr) | |||
606 | 606 | ||
607 | int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag) | 607 | int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag) |
608 | { | 608 | { |
609 | uid_t euid = current_euid(); | 609 | kuid_t euid = current_euid(); |
610 | int requested_mode, granted_mode; | 610 | int requested_mode, granted_mode; |
611 | 611 | ||
612 | audit_ipc_obj(ipcp); | 612 | audit_ipc_obj(ipcp); |
613 | requested_mode = (flag >> 6) | (flag >> 3) | flag; | 613 | requested_mode = (flag >> 6) | (flag >> 3) | flag; |
614 | granted_mode = ipcp->mode; | 614 | granted_mode = ipcp->mode; |
615 | if (euid == ipcp->cuid || | 615 | if (uid_eq(euid, ipcp->cuid) || |
616 | euid == ipcp->uid) | 616 | uid_eq(euid, ipcp->uid)) |
617 | granted_mode >>= 6; | 617 | granted_mode >>= 6; |
618 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) | 618 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) |
619 | granted_mode >>= 3; | 619 | granted_mode >>= 3; |
@@ -643,10 +643,10 @@ int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag) | |||
643 | void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out) | 643 | void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out) |
644 | { | 644 | { |
645 | out->key = in->key; | 645 | out->key = in->key; |
646 | out->uid = in->uid; | 646 | out->uid = from_kuid_munged(current_user_ns(), in->uid); |
647 | out->gid = in->gid; | 647 | out->gid = from_kgid_munged(current_user_ns(), in->gid); |
648 | out->cuid = in->cuid; | 648 | out->cuid = from_kuid_munged(current_user_ns(), in->cuid); |
649 | out->cgid = in->cgid; | 649 | out->cgid = from_kgid_munged(current_user_ns(), in->cgid); |
650 | out->mode = in->mode; | 650 | out->mode = in->mode; |
651 | out->seq = in->seq; | 651 | out->seq = in->seq; |
652 | } | 652 | } |
@@ -747,12 +747,19 @@ int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, | |||
747 | * @in: the permission given as input. | 747 | * @in: the permission given as input. |
748 | * @out: the permission of the ipc to set. | 748 | * @out: the permission of the ipc to set. |
749 | */ | 749 | */ |
750 | void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out) | 750 | int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out) |
751 | { | 751 | { |
752 | out->uid = in->uid; | 752 | kuid_t uid = make_kuid(current_user_ns(), in->uid); |
753 | out->gid = in->gid; | 753 | kgid_t gid = make_kgid(current_user_ns(), in->gid); |
754 | if (!uid_valid(uid) || !gid_valid(gid)) | ||
755 | return -EINVAL; | ||
756 | |||
757 | out->uid = uid; | ||
758 | out->gid = gid; | ||
754 | out->mode = (out->mode & ~S_IRWXUGO) | 759 | out->mode = (out->mode & ~S_IRWXUGO) |
755 | | (in->mode & S_IRWXUGO); | 760 | | (in->mode & S_IRWXUGO); |
761 | |||
762 | return 0; | ||
756 | } | 763 | } |
757 | 764 | ||
758 | /** | 765 | /** |
@@ -777,7 +784,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, | |||
777 | struct ipc64_perm *perm, int extra_perm) | 784 | struct ipc64_perm *perm, int extra_perm) |
778 | { | 785 | { |
779 | struct kern_ipc_perm *ipcp; | 786 | struct kern_ipc_perm *ipcp; |
780 | uid_t euid; | 787 | kuid_t euid; |
781 | int err; | 788 | int err; |
782 | 789 | ||
783 | down_write(&ids->rw_mutex); | 790 | down_write(&ids->rw_mutex); |
@@ -793,7 +800,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns, | |||
793 | perm->gid, perm->mode); | 800 | perm->gid, perm->mode); |
794 | 801 | ||
795 | euid = current_euid(); | 802 | euid = current_euid(); |
796 | if (euid == ipcp->cuid || euid == ipcp->uid || | 803 | if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid) || |
797 | ns_capable(ns->user_ns, CAP_SYS_ADMIN)) | 804 | ns_capable(ns->user_ns, CAP_SYS_ADMIN)) |
798 | return ipcp; | 805 | return ipcp; |
799 | 806 | ||