diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/mqueue.c | 19 | ||||
-rw-r--r-- | ipc/shm.c | 9 | ||||
-rw-r--r-- | ipc/util.c | 18 |
3 files changed, 29 insertions, 17 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 68eb857cfdea..d9393f8e4c3e 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -112,13 +112,14 @@ static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode) | |||
112 | static struct inode *mqueue_get_inode(struct super_block *sb, int mode, | 112 | static struct inode *mqueue_get_inode(struct super_block *sb, int mode, |
113 | struct mq_attr *attr) | 113 | struct mq_attr *attr) |
114 | { | 114 | { |
115 | struct user_struct *u = current_user(); | ||
115 | struct inode *inode; | 116 | struct inode *inode; |
116 | 117 | ||
117 | inode = new_inode(sb); | 118 | inode = new_inode(sb); |
118 | if (inode) { | 119 | if (inode) { |
119 | inode->i_mode = mode; | 120 | inode->i_mode = mode; |
120 | inode->i_uid = current->fsuid; | 121 | inode->i_uid = current_fsuid(); |
121 | inode->i_gid = current->fsgid; | 122 | inode->i_gid = current_fsgid(); |
122 | inode->i_blocks = 0; | 123 | inode->i_blocks = 0; |
123 | inode->i_mtime = inode->i_ctime = inode->i_atime = | 124 | inode->i_mtime = inode->i_ctime = inode->i_atime = |
124 | CURRENT_TIME; | 125 | CURRENT_TIME; |
@@ -126,7 +127,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, | |||
126 | if (S_ISREG(mode)) { | 127 | if (S_ISREG(mode)) { |
127 | struct mqueue_inode_info *info; | 128 | struct mqueue_inode_info *info; |
128 | struct task_struct *p = current; | 129 | struct task_struct *p = current; |
129 | struct user_struct *u = p->user; | ||
130 | unsigned long mq_bytes, mq_msg_tblsz; | 130 | unsigned long mq_bytes, mq_msg_tblsz; |
131 | 131 | ||
132 | inode->i_fop = &mqueue_file_operations; | 132 | inode->i_fop = &mqueue_file_operations; |
@@ -507,7 +507,7 @@ static void __do_notify(struct mqueue_inode_info *info) | |||
507 | sig_i.si_code = SI_MESGQ; | 507 | sig_i.si_code = SI_MESGQ; |
508 | sig_i.si_value = info->notify.sigev_value; | 508 | sig_i.si_value = info->notify.sigev_value; |
509 | sig_i.si_pid = task_tgid_vnr(current); | 509 | sig_i.si_pid = task_tgid_vnr(current); |
510 | sig_i.si_uid = current->uid; | 510 | sig_i.si_uid = current_uid(); |
511 | 511 | ||
512 | kill_pid_info(info->notify.sigev_signo, | 512 | kill_pid_info(info->notify.sigev_signo, |
513 | &sig_i, info->notify_owner); | 513 | &sig_i, info->notify_owner); |
@@ -594,6 +594,7 @@ static int mq_attr_ok(struct mq_attr *attr) | |||
594 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, | 594 | static struct file *do_create(struct dentry *dir, struct dentry *dentry, |
595 | int oflag, mode_t mode, struct mq_attr __user *u_attr) | 595 | int oflag, mode_t mode, struct mq_attr __user *u_attr) |
596 | { | 596 | { |
597 | const struct cred *cred = current_cred(); | ||
597 | struct mq_attr attr; | 598 | struct mq_attr attr; |
598 | struct file *result; | 599 | struct file *result; |
599 | int ret; | 600 | int ret; |
@@ -618,7 +619,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, | |||
618 | if (ret) | 619 | if (ret) |
619 | goto out_drop_write; | 620 | goto out_drop_write; |
620 | 621 | ||
621 | result = dentry_open(dentry, mqueue_mnt, oflag); | 622 | result = dentry_open(dentry, mqueue_mnt, oflag, cred); |
622 | /* | 623 | /* |
623 | * dentry_open() took a persistent mnt_want_write(), | 624 | * dentry_open() took a persistent mnt_want_write(), |
624 | * so we can now drop this one. | 625 | * so we can now drop this one. |
@@ -637,8 +638,10 @@ out: | |||
637 | /* Opens existing queue */ | 638 | /* Opens existing queue */ |
638 | static struct file *do_open(struct dentry *dentry, int oflag) | 639 | static struct file *do_open(struct dentry *dentry, int oflag) |
639 | { | 640 | { |
640 | static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | 641 | const struct cred *cred = current_cred(); |
641 | MAY_READ | MAY_WRITE }; | 642 | |
643 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | ||
644 | MAY_READ | MAY_WRITE }; | ||
642 | 645 | ||
643 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { | 646 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { |
644 | dput(dentry); | 647 | dput(dentry); |
@@ -652,7 +655,7 @@ static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | |||
652 | return ERR_PTR(-EACCES); | 655 | return ERR_PTR(-EACCES); |
653 | } | 656 | } |
654 | 657 | ||
655 | return dentry_open(dentry, mqueue_mnt, oflag); | 658 | return dentry_open(dentry, mqueue_mnt, oflag, cred); |
656 | } | 659 | } |
657 | 660 | ||
658 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, | 661 | asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, |
@@ -366,7 +366,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) | |||
366 | if (shmflg & SHM_HUGETLB) { | 366 | if (shmflg & SHM_HUGETLB) { |
367 | /* hugetlb_file_setup takes care of mlock user accounting */ | 367 | /* hugetlb_file_setup takes care of mlock user accounting */ |
368 | file = hugetlb_file_setup(name, size); | 368 | file = hugetlb_file_setup(name, size); |
369 | shp->mlock_user = current->user; | 369 | shp->mlock_user = current_user(); |
370 | } else { | 370 | } else { |
371 | int acctflag = VM_ACCOUNT; | 371 | int acctflag = VM_ACCOUNT; |
372 | /* | 372 | /* |
@@ -752,9 +752,10 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
752 | goto out_unlock; | 752 | goto out_unlock; |
753 | 753 | ||
754 | if (!capable(CAP_IPC_LOCK)) { | 754 | if (!capable(CAP_IPC_LOCK)) { |
755 | uid_t euid = current_euid(); | ||
755 | err = -EPERM; | 756 | err = -EPERM; |
756 | if (current->euid != shp->shm_perm.uid && | 757 | if (euid != shp->shm_perm.uid && |
757 | current->euid != shp->shm_perm.cuid) | 758 | euid != shp->shm_perm.cuid) |
758 | goto out_unlock; | 759 | goto out_unlock; |
759 | if (cmd == SHM_LOCK && | 760 | if (cmd == SHM_LOCK && |
760 | !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) | 761 | !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) |
@@ -766,7 +767,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) | |||
766 | goto out_unlock; | 767 | goto out_unlock; |
767 | 768 | ||
768 | if(cmd==SHM_LOCK) { | 769 | if(cmd==SHM_LOCK) { |
769 | struct user_struct * user = current->user; | 770 | struct user_struct *user = current_user(); |
770 | if (!is_file_hugepages(shp->shm_file)) { | 771 | if (!is_file_hugepages(shp->shm_file)) { |
771 | err = shmem_lock(shp->shm_file, 1, user); | 772 | err = shmem_lock(shp->shm_file, 1, user); |
772 | if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ | 773 | if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ |
diff --git a/ipc/util.c b/ipc/util.c index 361fd1c96fcf..5a1808c774a2 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,15 @@ 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> */ |
626 | uid_t euid = current_euid(); | ||
623 | int requested_mode, granted_mode, err; | 627 | int requested_mode, granted_mode, err; |
624 | 628 | ||
625 | if (unlikely((err = audit_ipc_obj(ipcp)))) | 629 | if (unlikely((err = audit_ipc_obj(ipcp)))) |
626 | return err; | 630 | return err; |
627 | requested_mode = (flag >> 6) | (flag >> 3) | flag; | 631 | requested_mode = (flag >> 6) | (flag >> 3) | flag; |
628 | granted_mode = ipcp->mode; | 632 | granted_mode = ipcp->mode; |
629 | if (current->euid == ipcp->cuid || current->euid == ipcp->uid) | 633 | if (euid == ipcp->cuid || |
634 | euid == ipcp->uid) | ||
630 | granted_mode >>= 6; | 635 | granted_mode >>= 6; |
631 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) | 636 | else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) |
632 | granted_mode >>= 3; | 637 | granted_mode >>= 3; |
@@ -788,6 +793,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
788 | struct ipc64_perm *perm, int extra_perm) | 793 | struct ipc64_perm *perm, int extra_perm) |
789 | { | 794 | { |
790 | struct kern_ipc_perm *ipcp; | 795 | struct kern_ipc_perm *ipcp; |
796 | uid_t euid; | ||
791 | int err; | 797 | int err; |
792 | 798 | ||
793 | down_write(&ids->rw_mutex); | 799 | down_write(&ids->rw_mutex); |
@@ -807,8 +813,10 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, | |||
807 | if (err) | 813 | if (err) |
808 | goto out_unlock; | 814 | goto out_unlock; |
809 | } | 815 | } |
810 | if (current->euid == ipcp->cuid || | 816 | |
811 | current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) | 817 | euid = current_euid(); |
818 | if (euid == ipcp->cuid || | ||
819 | euid == ipcp->uid || capable(CAP_SYS_ADMIN)) | ||
812 | return ipcp; | 820 | return ipcp; |
813 | 821 | ||
814 | err = -EPERM; | 822 | err = -EPERM; |