From 414c0708d0d60eccf8345c405ac81cf32c43e901 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 14 Nov 2008 10:39:06 +1100 Subject: CRED: Wrap task credential accesses in the SYSV IPC subsystem Wrap access to task credentials so that they can be separated more easily from the task_struct during the introduction of COW creds. Change most current->(|e|s|fs)[ug]id to current_(|e|s|fs)[ug]id(). Change some task->e?[ug]id to task_e?[ug]id(). In some places it makes more sense to use RCU directly rather than a convenient wrapper; these will be addressed by later patches. Signed-off-by: David Howells Reviewed-by: James Morris Acked-by: Serge Hallyn Signed-off-by: James Morris --- ipc/mqueue.c | 6 +++--- ipc/shm.c | 5 +++-- ipc/util.c | 18 +++++++++++++----- 3 files changed, 19 insertions(+), 10 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 68eb857cfde..abda5991d7e 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -117,8 +117,8 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, inode = new_inode(sb); if (inode) { inode->i_mode = mode; - inode->i_uid = current->fsuid; - inode->i_gid = current->fsgid; + inode->i_uid = current_fsuid(); + inode->i_gid = current_fsgid(); inode->i_blocks = 0; inode->i_mtime = inode->i_ctime = inode->i_atime = CURRENT_TIME; @@ -507,7 +507,7 @@ static void __do_notify(struct mqueue_inode_info *info) sig_i.si_code = SI_MESGQ; sig_i.si_value = info->notify.sigev_value; sig_i.si_pid = task_tgid_vnr(current); - sig_i.si_uid = current->uid; + sig_i.si_uid = current_uid(); kill_pid_info(info->notify.sigev_signo, &sig_i, info->notify_owner); diff --git a/ipc/shm.c b/ipc/shm.c index 867e5d6a55c..0c3debbe32d 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -752,9 +752,10 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) goto out_unlock; if (!capable(CAP_IPC_LOCK)) { + uid_t euid = current_euid(); err = -EPERM; - if (current->euid != shp->shm_perm.uid && - current->euid != shp->shm_perm.cuid) + if (euid != shp->shm_perm.uid && + euid != shp->shm_perm.cuid) goto out_unlock; if (cmd == SHM_LOCK && !current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur) diff --git a/ipc/util.c b/ipc/util.c index 49b3ea615dc..c8a76701b6c 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -258,6 +258,8 @@ int ipc_get_maxid(struct ipc_ids *ids) int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) { + uid_t euid; + gid_t egid; int id, err; if (size > IPCMNI) @@ -272,8 +274,9 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) ids->in_use++; - new->cuid = new->uid = current->euid; - new->gid = new->cgid = current->egid; + current_euid_egid(&euid, &egid); + new->cuid = new->uid = euid; + new->gid = new->cgid = egid; new->seq = ids->seq++; if(ids->seq > ids->seq_max) @@ -616,13 +619,15 @@ void ipc_rcu_putref(void *ptr) int ipcperms (struct kern_ipc_perm *ipcp, short flag) { /* flag will most probably be 0 or S_...UGO from */ + uid_t euid = current_euid(); int requested_mode, granted_mode, err; if (unlikely((err = audit_ipc_obj(ipcp)))) return err; requested_mode = (flag >> 6) | (flag >> 3) | flag; granted_mode = ipcp->mode; - if (current->euid == ipcp->cuid || current->euid == ipcp->uid) + if (euid == ipcp->cuid || + euid == ipcp->uid) granted_mode >>= 6; else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid)) granted_mode >>= 3; @@ -784,6 +789,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, struct ipc64_perm *perm, int extra_perm) { struct kern_ipc_perm *ipcp; + uid_t euid; int err; down_write(&ids->rw_mutex); @@ -803,8 +809,10 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, if (err) goto out_unlock; } - if (current->euid == ipcp->cuid || - current->euid == ipcp->uid || capable(CAP_SYS_ADMIN)) + + euid = current_euid(); + if (euid == ipcp->cuid || + euid == ipcp->uid || capable(CAP_SYS_ADMIN)) return ipcp; err = -EPERM; -- cgit v1.2.3 From b6dff3ec5e116e3af6f537d4caedcad6b9e5082a Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 14 Nov 2008 10:39:16 +1100 Subject: CRED: Separate task security context from task_struct Separate the task security context from task_struct. At this point, the security data is temporarily embedded in the task_struct with two pointers pointing to it. Note that the Alpha arch is altered as it refers to (E)UID and (E)GID in entry.S via asm-offsets. With comment fixes Signed-off-by: Marc Dionne Signed-off-by: David Howells Acked-by: James Morris Acked-by: Serge Hallyn Signed-off-by: James Morris --- ipc/mqueue.c | 2 +- ipc/shm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index abda5991d7e..e1885b494ba 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -126,7 +126,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, if (S_ISREG(mode)) { struct mqueue_inode_info *info; struct task_struct *p = current; - struct user_struct *u = p->user; + struct user_struct *u = p->cred->user; unsigned long mq_bytes, mq_msg_tblsz; inode->i_fop = &mqueue_file_operations; diff --git a/ipc/shm.c b/ipc/shm.c index 0c3debbe32d..264a9d33c5d 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -366,7 +366,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) if (shmflg & SHM_HUGETLB) { /* hugetlb_file_setup takes care of mlock user accounting */ file = hugetlb_file_setup(name, size); - shp->mlock_user = current->user; + shp->mlock_user = current->cred->user; } else { int acctflag = VM_ACCOUNT; /* @@ -767,7 +767,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) goto out_unlock; if(cmd==SHM_LOCK) { - struct user_struct * user = current->user; + struct user_struct *user = current->cred->user; if (!is_file_hugepages(shp->shm_file)) { err = shmem_lock(shp->shm_file, 1, user); if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ -- cgit v1.2.3 From 86a264abe542cfececb4df129bc45a0338d8cdb9 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 14 Nov 2008 10:39:18 +1100 Subject: CRED: Wrap current->cred and a few other accessors Wrap current->cred and a few other accessors to hide their actual implementation. Signed-off-by: David Howells Acked-by: James Morris Acked-by: Serge Hallyn Signed-off-by: James Morris --- ipc/mqueue.c | 2 +- ipc/shm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index e1885b494ba..1151881ccb9 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -112,6 +112,7 @@ static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode) static struct inode *mqueue_get_inode(struct super_block *sb, int mode, struct mq_attr *attr) { + struct user_struct *u = current_user(); struct inode *inode; inode = new_inode(sb); @@ -126,7 +127,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, if (S_ISREG(mode)) { struct mqueue_inode_info *info; struct task_struct *p = current; - struct user_struct *u = p->cred->user; unsigned long mq_bytes, mq_msg_tblsz; inode->i_fop = &mqueue_file_operations; diff --git a/ipc/shm.c b/ipc/shm.c index 264a9d33c5d..38a055758a9 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -366,7 +366,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) if (shmflg & SHM_HUGETLB) { /* hugetlb_file_setup takes care of mlock user accounting */ file = hugetlb_file_setup(name, size); - shp->mlock_user = current->cred->user; + shp->mlock_user = current_user(); } else { int acctflag = VM_ACCOUNT; /* @@ -767,7 +767,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) goto out_unlock; if(cmd==SHM_LOCK) { - struct user_struct *user = current->cred->user; + struct user_struct *user = current_user(); if (!is_file_hugepages(shp->shm_file)) { err = shmem_lock(shp->shm_file, 1, user); if (!err && !(shp->shm_perm.mode & SHM_LOCKED)){ -- cgit v1.2.3 From 745ca2475a6ac596e3d8d37c2759c0fbe2586227 Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 14 Nov 2008 10:39:22 +1100 Subject: CRED: Pass credentials through dentry_open() Pass credentials through dentry_open() so that the COW creds patch can have SELinux's flush_unauthorized_files() pass the appropriate creds back to itself when it opens its null chardev. The security_dentry_open() call also now takes a creds pointer, as does the dentry_open hook in struct security_operations. Signed-off-by: David Howells Acked-by: James Morris Signed-off-by: James Morris --- ipc/mqueue.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 1151881ccb9..d9393f8e4c3 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -594,6 +594,7 @@ static int mq_attr_ok(struct mq_attr *attr) static struct file *do_create(struct dentry *dir, struct dentry *dentry, int oflag, mode_t mode, struct mq_attr __user *u_attr) { + const struct cred *cred = current_cred(); struct mq_attr attr; struct file *result; int ret; @@ -618,7 +619,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, if (ret) goto out_drop_write; - result = dentry_open(dentry, mqueue_mnt, oflag); + result = dentry_open(dentry, mqueue_mnt, oflag, cred); /* * dentry_open() took a persistent mnt_want_write(), * so we can now drop this one. @@ -637,8 +638,10 @@ out: /* Opens existing queue */ static struct file *do_open(struct dentry *dentry, int oflag) { -static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, - MAY_READ | MAY_WRITE }; + const struct cred *cred = current_cred(); + + static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, + MAY_READ | MAY_WRITE }; if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { dput(dentry); @@ -652,7 +655,7 @@ static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, return ERR_PTR(-EACCES); } - return dentry_open(dentry, mqueue_mnt, oflag); + return dentry_open(dentry, mqueue_mnt, oflag, cred); } asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, -- cgit v1.2.3 From a33e6751003c5ade603737d828b1519d980ce392 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Dec 2008 03:40:06 -0500 Subject: sanitize audit_ipc_obj() * get rid of allocations * make it return void * simplify callers Signed-off-by: Al Viro --- ipc/shm.c | 4 +--- ipc/util.c | 9 +++------ 2 files changed, 4 insertions(+), 9 deletions(-) (limited to 'ipc') diff --git a/ipc/shm.c b/ipc/shm.c index 38a055758a9..57dd50046ce 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -747,9 +747,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) goto out; } - err = audit_ipc_obj(&(shp->shm_perm)); - if (err) - goto out_unlock; + audit_ipc_obj(&(shp->shm_perm)); if (!capable(CAP_IPC_LOCK)) { uid_t euid = current_euid(); diff --git a/ipc/util.c b/ipc/util.c index 5a1808c774a..579552abd50 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -624,10 +624,9 @@ void ipc_rcu_putref(void *ptr) int ipcperms (struct kern_ipc_perm *ipcp, short flag) { /* flag will most probably be 0 or S_...UGO from */ uid_t euid = current_euid(); - int requested_mode, granted_mode, err; + int requested_mode, granted_mode; - if (unlikely((err = audit_ipc_obj(ipcp)))) - return err; + audit_ipc_obj(ipcp); requested_mode = (flag >> 6) | (flag >> 3) | flag; granted_mode = ipcp->mode; if (euid == ipcp->cuid || @@ -803,9 +802,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, goto out_up; } - err = audit_ipc_obj(ipcp); - if (err) - goto out_unlock; + audit_ipc_obj(ipcp); if (cmd == IPC_SET) { err = audit_ipc_set_perm(extra_perm, perm->uid, -- cgit v1.2.3 From e816f370cbadd2afea9f1a42f232d0636137d563 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Dec 2008 03:47:15 -0500 Subject: sanitize audit_ipc_set_perm() * get rid of allocations * make it return void * simplify callers Signed-off-by: Al Viro --- ipc/util.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'ipc') diff --git a/ipc/util.c b/ipc/util.c index 579552abd50..7585a72e259 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -803,13 +803,9 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, } audit_ipc_obj(ipcp); - - if (cmd == IPC_SET) { - err = audit_ipc_set_perm(extra_perm, perm->uid, + if (cmd == IPC_SET) + audit_ipc_set_perm(extra_perm, perm->uid, perm->gid, perm->mode); - if (err) - goto out_unlock; - } euid = current_euid(); if (euid == ipcp->cuid || @@ -817,7 +813,6 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, return ipcp; err = -EPERM; -out_unlock: ipc_unlock(ipcp); out_up: up_write(&ids->rw_mutex); -- cgit v1.2.3 From 7392906ea915b9a2c14dea32b3604b4e178f82f7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Dec 2008 06:58:59 -0500 Subject: sanitize audit_mq_getsetattr() * get rid of allocations * make it return void * don't duplicate parts of audit_dummy_context() Signed-off-by: Al Viro --- ipc/mqueue.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index d9393f8e4c3..7563611c661 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1150,11 +1150,7 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, omqstat = info->attr; omqstat.mq_flags = filp->f_flags & O_NONBLOCK; if (u_mqstat) { - ret = audit_mq_getsetattr(mqdes, &mqstat); - if (ret != 0) { - spin_unlock(&info->lock); - goto out_fput; - } + audit_mq_getsetattr(mqdes, &mqstat); if (mqstat.mq_flags & O_NONBLOCK) filp->f_flags |= O_NONBLOCK; else -- cgit v1.2.3 From 20114f71b27cafeb7c7e41d2b0f0b68c3fbb022b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 10 Dec 2008 07:16:12 -0500 Subject: sanitize audit_mq_notify() * don't copy_from_user() twice * don't bother with allocations * don't duplicate parts of audit_dummy_context() * make it return void Signed-off-by: Al Viro --- ipc/mqueue.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 7563611c661..e7b2f68f8d7 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1003,17 +1003,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes, struct mqueue_inode_info *info; struct sk_buff *nc; - ret = audit_mq_notify(mqdes, u_notification); - if (ret != 0) - return ret; - - nc = NULL; - sock = NULL; - if (u_notification != NULL) { + if (u_notification) { if (copy_from_user(¬ification, u_notification, sizeof(struct sigevent))) return -EFAULT; + } + + audit_mq_notify(mqdes, u_notification ? ¬ification : NULL); + nc = NULL; + sock = NULL; + if (u_notification != NULL) { if (unlikely(notification.sigev_notify != SIGEV_NONE && notification.sigev_notify != SIGEV_SIGNAL && notification.sigev_notify != SIGEV_THREAD)) -- cgit v1.2.3 From c32c8af43b9adde8d6f938d8e6328c13b8de79ac Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Dec 2008 03:46:48 -0500 Subject: sanitize AUDIT_MQ_SENDRECV * logging the original value of *msg_prio in mq_timedreceive(2) is insane - the argument is write-only (i.e. syscall always ignores the original value and only overwrites it). * merge __audit_mq_timed{send,receive} * don't do copy_from_user() twice * don't mess with allocations in auditsc part * ... and don't bother checking !audit_enabled and !context in there - we'd already checked for audit_dummy_context(). Signed-off-by: Al Viro --- ipc/mqueue.c | 54 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 24 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index e7b2f68f8d7..192da806c28 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -524,31 +524,27 @@ static void __do_notify(struct mqueue_inode_info *info) wake_up(&info->wait_q); } -static long prepare_timeout(const struct timespec __user *u_arg) +static long prepare_timeout(struct timespec *p) { - struct timespec ts, nowts; + struct timespec nowts; long timeout; - if (u_arg) { - if (unlikely(copy_from_user(&ts, u_arg, - sizeof(struct timespec)))) - return -EFAULT; - - if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0 - || ts.tv_nsec >= NSEC_PER_SEC)) + if (p) { + if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0 + || p->tv_nsec >= NSEC_PER_SEC)) return -EINVAL; nowts = CURRENT_TIME; /* first subtract as jiffies can't be too big */ - ts.tv_sec -= nowts.tv_sec; - if (ts.tv_nsec < nowts.tv_nsec) { - ts.tv_nsec += NSEC_PER_SEC; - ts.tv_sec--; + p->tv_sec -= nowts.tv_sec; + if (p->tv_nsec < nowts.tv_nsec) { + p->tv_nsec += NSEC_PER_SEC; + p->tv_sec--; } - ts.tv_nsec -= nowts.tv_nsec; - if (ts.tv_sec < 0) + p->tv_nsec -= nowts.tv_nsec; + if (p->tv_sec < 0) return 0; - timeout = timespec_to_jiffies(&ts) + 1; + timeout = timespec_to_jiffies(p) + 1; } else return MAX_SCHEDULE_TIMEOUT; @@ -829,17 +825,22 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, struct ext_wait_queue *receiver; struct msg_msg *msg_ptr; struct mqueue_inode_info *info; + struct timespec ts, *p = NULL; long timeout; int ret; - ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); - if (ret != 0) - return ret; + if (u_abs_timeout) { + if (copy_from_user(&ts, u_abs_timeout, + sizeof(struct timespec))) + return -EFAULT; + p = &ts; + } if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) return -EINVAL; - timeout = prepare_timeout(u_abs_timeout); + audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); + timeout = prepare_timeout(p); ret = -EBADF; filp = fget(mqdes); @@ -918,12 +919,17 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, struct inode *inode; struct mqueue_inode_info *info; struct ext_wait_queue wait; + struct timespec ts, *p = NULL; - ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); - if (ret != 0) - return ret; + if (u_abs_timeout) { + if (copy_from_user(&ts, u_abs_timeout, + sizeof(struct timespec))) + return -EFAULT; + p = &ts; + } - timeout = prepare_timeout(u_abs_timeout); + audit_mq_sendrecv(mqdes, msg_len, 0, p); + timeout = prepare_timeout(p); ret = -EBADF; filp = fget(mqdes); -- cgit v1.2.3 From 564f6993ffef656aebaf46cf2f1f6cb4f5c97207 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 14 Dec 2008 04:02:26 -0500 Subject: sanitize audit_mq_open() * don't bother with allocations * don't do double copy_from_user() * don't duplicate parts of check for audit_dummy_context() Signed-off-by: Al Viro --- ipc/mqueue.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 192da806c28..d448b69672b 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -588,22 +588,18 @@ static int mq_attr_ok(struct mq_attr *attr) * Invoked when creating a new queue via sys_mq_open */ static struct file *do_create(struct dentry *dir, struct dentry *dentry, - int oflag, mode_t mode, struct mq_attr __user *u_attr) + int oflag, mode_t mode, struct mq_attr *attr) { const struct cred *cred = current_cred(); - struct mq_attr attr; struct file *result; int ret; - if (u_attr) { - ret = -EFAULT; - if (copy_from_user(&attr, u_attr, sizeof(attr))) - goto out; + if (attr) { ret = -EINVAL; - if (!mq_attr_ok(&attr)) + if (!mq_attr_ok(attr)) goto out; /* store for use during create */ - dentry->d_fsdata = &attr; + dentry->d_fsdata = attr; } mode &= ~current->fs->umask; @@ -660,11 +656,13 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, struct dentry *dentry; struct file *filp; char *name; + struct mq_attr attr; int fd, error; - error = audit_mq_open(oflag, mode, u_attr); - if (error != 0) - return error; + if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) + return -EFAULT; + + audit_mq_open(oflag, mode, u_attr ? &attr : NULL); if (IS_ERR(name = getname(u_name))) return PTR_ERR(name); @@ -690,7 +688,8 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, filp = do_open(dentry, oflag); } else { filp = do_create(mqueue_mnt->mnt_root, dentry, - oflag, mode, u_attr); + oflag, mode, + u_attr ? &attr : NULL); } } else { error = -ENOENT; -- cgit v1.2.3 From 56ff5efad96182f4d3cb3dc6b07396762c658f16 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 9 Dec 2008 09:34:39 -0500 Subject: zero i_uid/i_gid on inode allocation ... and don't bother in callers. Don't bother with zeroing i_blocks, while we are at it - it's already been zeroed. i_mode is not worth the effort; it has no common default value. Signed-off-by: Al Viro --- ipc/mqueue.c | 1 - 1 file changed, 1 deletion(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index d9393f8e4c3..41b72f02fa7 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -120,7 +120,6 @@ static struct inode *mqueue_get_inode(struct super_block *sb, int mode, inode->i_mode = mode; inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); - inode->i_blocks = 0; inode->i_mtime = inode->i_ctime = inode->i_atime = CURRENT_TIME; -- cgit v1.2.3 From 046c68842bce6b77509cf56e94a561029124b0ce Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 5 Jan 2009 14:06:29 +0000 Subject: mm: update my address Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- ipc/sem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ipc') diff --git a/ipc/sem.c b/ipc/sem.c index 082122469b1..fea0ad3aed7 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -58,7 +58,7 @@ * SMP-threaded, sysctl's added * (c) 1999 Manfred Spraul * Enforced range limit on SEM_UNDO - * (c) 2001 Red Hat Inc + * (c) 2001 Red Hat Inc * Lockless wakeup * (c) 2003 Manfred Spraul * -- cgit v1.2.3 From e8148f7588064e45080bf1120883380a2efe5c9b Mon Sep 17 00:00:00 2001 From: WANG Cong Date: Tue, 6 Jan 2009 14:42:49 -0800 Subject: ipc: clean up ipc/shm.c Use the macro shm_ids(). Remove useless check for a userspace pointer, because copy_to_user() will check it. Some style cleanups. Signed-off-by: WANG Cong Cc: Nadia Derbey Cc: Pierre Peiffer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/shm.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'ipc') diff --git a/ipc/shm.c b/ipc/shm.c index 57dd50046ce..b125b560240 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -75,7 +75,7 @@ void shm_init_ns(struct ipc_namespace *ns) ns->shm_ctlall = SHMALL; ns->shm_ctlmni = SHMMNI; ns->shm_tot = 0; - ipc_init_ids(&ns->ids[IPC_SHM_IDS]); + ipc_init_ids(&shm_ids(ns)); } /* @@ -644,7 +644,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) if (err) return err; - memset(&shminfo,0,sizeof(shminfo)); + memset(&shminfo, 0, sizeof(shminfo)); shminfo.shmmni = shminfo.shmseg = ns->shm_ctlmni; shminfo.shmmax = ns->shm_ctlmax; shminfo.shmall = ns->shm_ctlall; @@ -669,7 +669,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) if (err) return err; - memset(&shm_info,0,sizeof(shm_info)); + memset(&shm_info, 0, sizeof(shm_info)); down_read(&shm_ids(ns).rw_mutex); shm_info.used_ids = shm_ids(ns).in_use; shm_get_stat (ns, &shm_info.shm_rss, &shm_info.shm_swp); @@ -678,7 +678,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) shm_info.swap_successes = 0; err = ipc_get_maxid(&shm_ids(ns)); up_read(&shm_ids(ns).rw_mutex); - if(copy_to_user (buf, &shm_info, sizeof(shm_info))) { + if (copy_to_user(buf, &shm_info, sizeof(shm_info))) { err = -EFAULT; goto out; } @@ -692,11 +692,6 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) struct shmid64_ds tbuf; int result; - if (!buf) { - err = -EFAULT; - goto out; - } - if (cmd == SHM_STAT) { shp = shm_lock(ns, shmid); if (IS_ERR(shp)) { @@ -712,7 +707,7 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) } result = 0; } - err=-EACCES; + err = -EACCES; if (ipcperms (&shp->shm_perm, S_IRUGO)) goto out_unlock; err = security_shm_shmctl(shp, cmd); -- cgit v1.2.3 From e953ac2195659940d0d042f7ac962700a6a0f0e3 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Tue, 6 Jan 2009 14:42:50 -0800 Subject: ipc: do not goto to the next line Signed-off-by: Denis V. Lunev Reviewed-by: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/sem.c | 1 - 1 file changed, 1 deletion(-) (limited to 'ipc') diff --git a/ipc/sem.c b/ipc/sem.c index fea0ad3aed7..c68cd3f8f0c 100644 --- a/ipc/sem.c +++ b/ipc/sem.c @@ -1216,7 +1216,6 @@ asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops, if (timeout && jiffies_left == 0) error = -EAGAIN; list_del(&queue.list); - goto out_unlock_free; out_unlock_free: sem_unlock(sma); -- cgit v1.2.3 From 4c2c3b4aaf3c10a636490438e9648a314ce414f9 Mon Sep 17 00:00:00 2001 From: "akpm@linux-foundation.org" Date: Tue, 6 Jan 2009 14:42:51 -0800 Subject: ipc/ipc_sysctl.c: move the definition of ipc_auto_callback() proc_ipcauto_dointvec_minmax() is the only user of ipc_auto_callback(), since the former function is protected by CONFIG_PROC_FS, so should be the latter one. Just move its definition down. Signed-off-by: WANG Cong Cc: Eric Biederman Cc: Nadia Derbey Cc: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/ipc_sysctl.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'ipc') diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 0dfebc50942..4a7a12c95ab 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -26,29 +26,6 @@ static void *get_ipc(ctl_table *table) return which; } -/* - * Routine that is called when the file "auto_msgmni" has successfully been - * written. - * Two values are allowed: - * 0: unregister msgmni's callback routine from the ipc namespace notifier - * chain. This means that msgmni won't be recomputed anymore upon memory - * add/remove or ipc namespace creation/removal. - * 1: register back the callback routine. - */ -static void ipc_auto_callback(int val) -{ - if (!val) - unregister_ipcns_notifier(current->nsproxy->ipc_ns); - else { - /* - * Re-enable automatic recomputing only if not already - * enabled. - */ - recompute_msgmni(current->nsproxy->ipc_ns); - cond_register_ipcns_notifier(current->nsproxy->ipc_ns); - } -} - #ifdef CONFIG_PROC_FS static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) @@ -94,6 +71,29 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, lenp, ppos); } +/* + * Routine that is called when the file "auto_msgmni" has successfully been + * written. + * Two values are allowed: + * 0: unregister msgmni's callback routine from the ipc namespace notifier + * chain. This means that msgmni won't be recomputed anymore upon memory + * add/remove or ipc namespace creation/removal. + * 1: register back the callback routine. + */ +static void ipc_auto_callback(int val) +{ + if (!val) + unregister_ipcns_notifier(current->nsproxy->ipc_ns); + else { + /* + * Re-enable automatic recomputing only if not already + * enabled. + */ + recompute_msgmni(current->nsproxy->ipc_ns); + cond_register_ipcns_notifier(current->nsproxy->ipc_ns); + } +} + static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { -- cgit v1.2.3 From a6684999f7c6bddd75cf9755ad7ff44435f72fff Mon Sep 17 00:00:00 2001 From: Sukadev Bhattiprolu Date: Wed, 7 Jan 2009 18:08:50 -0800 Subject: mqueue: fix si_pid value in mqueue do_notify() If a process registers for asynchronous notification on a POSIX message queue, it gets a signal and a siginfo_t structure when a message arrives on the message queue. The si_pid in the siginfo_t structure is set to the PID of the process that sent the message to the message queue. The principle is the following: . when mq_notify(SIGEV_SIGNAL) is called, the caller registers for notification when a msg arrives. The associated pid structure is stroed into inode_info->notify_owner. Let's call this process P1. . when mq_send() is called by say P2, P2 sends a signal to P1 to notify him about msg arrival. The way .si_pid is set today is not correct, since it doesn't take into account the fact that the process that is sending the message might not be in the same namespace as the notified one. This patch proposes to set si_pid to the sender's pid into the notify_owner namespace. Signed-off-by: Nadia Derbey Signed-off-by: Sukadev Bhattiprolu Acked-by: Oleg Nesterov Cc: Roland McGrath Cc: Bastian Blank Cc: Pavel Emelyanov Cc: Eric W. Biederman Acked-by: Serge Hallyn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/mqueue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'ipc') diff --git a/ipc/mqueue.c b/ipc/mqueue.c index eddb6247a55..23fdb8492b8 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -505,7 +505,8 @@ static void __do_notify(struct mqueue_inode_info *info) sig_i.si_errno = 0; sig_i.si_code = SI_MESGQ; sig_i.si_value = info->notify.sigev_value; - sig_i.si_pid = task_tgid_vnr(current); + sig_i.si_pid = task_tgid_nr_ns(current, + ns_of_pid(info->notify_owner)); sig_i.si_uid = current_uid(); kill_pid_info(info->notify.sigev_signo, -- cgit v1.2.3