diff options
Diffstat (limited to 'ipc/util.c')
| -rw-r--r-- | ipc/util.c | 36 |
1 files changed, 18 insertions, 18 deletions
diff --git a/ipc/util.c b/ipc/util.c index 361fd1c96fcf..7585a72e259b 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
| @@ -258,6 +258,8 @@ int ipc_get_maxid(struct ipc_ids *ids) | |||
| 258 | 258 | ||
| 259 | int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | 259 | int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) |
| 260 | { | 260 | { |
| 261 | uid_t euid; | ||
| 262 | gid_t egid; | ||
| 261 | int id, err; | 263 | int id, err; |
| 262 | 264 | ||
| 263 | if (size > IPCMNI) | 265 | if (size > IPCMNI) |
| @@ -280,8 +282,9 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
| 280 | 282 | ||
| 281 | ids->in_use++; | 283 | ids->in_use++; |
| 282 | 284 | ||
| 283 | new->cuid = new->uid = current->euid; | 285 | current_euid_egid(&euid, &egid); |
| 284 | new->gid = new->cgid = current->egid; | 286 | new->cuid = new->uid = euid; |
| 287 | new->gid = new->cgid = egid; | ||
| 285 | 288 | ||
| 286 | new->seq = ids->seq++; | 289 | new->seq = ids->seq++; |
| 287 | if(ids->seq > ids->seq_max) | 290 | if(ids->seq > ids->seq_max) |
| @@ -620,13 +623,14 @@ void ipc_rcu_putref(void *ptr) | |||
| 620 | 623 | ||
| 621 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) | 624 | int ipcperms (struct kern_ipc_perm *ipcp, short flag) |
| 622 | { /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ | 625 | { /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */ |
| 623 | int requested_mode, granted_mode, err; | 626 | uid_t euid = current_euid(); |
| 627 | int requested_mode, granted_mode; | ||
| 624 | 628 | ||
| 625 | if (unlikely((err = audit_ipc_obj(ipcp)))) | 629 | audit_ipc_obj(ipcp); |
| 626 | return err; | ||
| 627 | requested_mode = (flag >> 6) | (flag >> 3) | flag; | 630 | requested_mode = (flag >> 6) | (flag >> 3) | flag; |
| 628 | granted_mode = ipcp->mode; | 631 | granted_mode = ipcp->mode; |
| 629 | if (current->euid == ipcp->cuid || current->euid == ipcp->uid) | 632 | if (euid == ipcp->cuid || |
| 633 | euid == ipcp->uid) | ||
| 630 | granted_mode >>= 6; | 634 | granted_mode >>= 6; |
| 631 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) | 635 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) |
| 632 | granted_mode >>= 3; | 636 | granted_mode >>= 3; |
| @@ -788,6 +792,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
| 788 | struct ipc64_perm *perm, int extra_perm) | 792 | struct ipc64_perm *perm, int extra_perm) |
| 789 | { | 793 | { |
| 790 | struct kern_ipc_perm *ipcp; | 794 | struct kern_ipc_perm *ipcp; |
| 795 | uid_t euid; | ||
| 791 | int err; | 796 | int err; |
| 792 | 797 | ||
| 793 | down_write(&ids->rw_mutex); | 798 | down_write(&ids->rw_mutex); |
| @@ -797,22 +802,17 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
| 797 | goto out_up; | 802 | goto out_up; |
| 798 | } | 803 | } |
| 799 | 804 | ||
| 800 | err = audit_ipc_obj(ipcp); | 805 | audit_ipc_obj(ipcp); |
| 801 | if (err) | 806 | if (cmd == IPC_SET) |
| 802 | goto out_unlock; | 807 | audit_ipc_set_perm(extra_perm, perm->uid, |
| 803 | |||
| 804 | if (cmd == IPC_SET) { | ||
| 805 | err = audit_ipc_set_perm(extra_perm, perm->uid, | ||
| 806 | perm->gid, perm->mode); | 808 | perm->gid, perm->mode); |
| 807 | if (err) | 809 | |
| 808 | goto out_unlock; | 810 | euid = current_euid(); |
| 809 | } | 811 | if (euid == ipcp->cuid || |
| 810 | if (current->euid == ipcp->cuid || | 812 | euid == ipcp->uid || capable(CAP_SYS_ADMIN)) |
| 811 | current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) | ||
| 812 | return ipcp; | 813 | return ipcp; |
| 813 | 814 | ||
| 814 | err = -EPERM; | 815 | err = -EPERM; |
| 815 | out_unlock: | ||
| 816 | ipc_unlock(ipcp); | 816 | ipc_unlock(ipcp); |
| 817 | out_up: | 817 | out_up: |
| 818 | up_write(&ids->rw_mutex); | 818 | up_write(&ids->rw_mutex); |
