aboutsummaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/mqueue.c68
-rw-r--r--ipc/msg.c3
-rw-r--r--ipc/sem.c5
-rw-r--r--ipc/shm.c41
-rw-r--r--ipc/util.c3
-rw-r--r--ipc/util.h2
6 files changed, 71 insertions, 51 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index c8943b53d8e..59302fc3643 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -11,6 +11,7 @@
* This file is released under the GPL.
*/
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/file.h>
@@ -598,15 +599,16 @@ 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)
{
- struct file *filp;
struct mq_attr attr;
int ret;
- if (u_attr != NULL) {
+ if (u_attr) {
+ ret = -EFAULT;
if (copy_from_user(&attr, u_attr, sizeof(attr)))
- return ERR_PTR(-EFAULT);
+ goto out;
+ ret = -EINVAL;
if (!mq_attr_ok(&attr))
- return ERR_PTR(-EINVAL);
+ goto out;
/* store for use during create */
dentry->d_fsdata = &attr;
}
@@ -615,13 +617,14 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry,
ret = vfs_create(dir->d_inode, dentry, mode, NULL);
dentry->d_fsdata = NULL;
if (ret)
- return ERR_PTR(ret);
+ goto out;
- filp = dentry_open(dentry, mqueue_mnt, oflag);
- if (!IS_ERR(filp))
- dget(dentry);
+ return dentry_open(dentry, mqueue_mnt, oflag);
- return filp;
+out:
+ dput(dentry);
+ mntput(mqueue_mnt);
+ return ERR_PTR(ret);
}
/* Opens existing queue */
@@ -629,20 +632,20 @@ static struct file *do_open(struct dentry *dentry, int oflag)
{
static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
MAY_READ | MAY_WRITE };
- struct file *filp;
- if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
+ if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
+ dput(dentry);
+ mntput(mqueue_mnt);
return ERR_PTR(-EINVAL);
+ }
- if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL))
+ if (permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE], NULL)) {
+ dput(dentry);
+ mntput(mqueue_mnt);
return ERR_PTR(-EACCES);
+ }
- filp = dentry_open(dentry, mqueue_mnt, oflag);
-
- if (!IS_ERR(filp))
- dget(dentry);
-
- return filp;
+ return dentry_open(dentry, mqueue_mnt, oflag);
}
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
@@ -660,7 +663,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
if (fd < 0)
goto out_putname;
- down(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) {
error = PTR_ERR(dentry);
@@ -670,17 +673,20 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
if (oflag & O_CREAT) {
if (dentry->d_inode) { /* entry already exists */
- filp = (oflag & O_EXCL) ? ERR_PTR(-EEXIST) :
- do_open(dentry, oflag);
+ error = -EEXIST;
+ if (oflag & O_EXCL)
+ goto out;
+ filp = do_open(dentry, oflag);
} else {
filp = do_create(mqueue_mnt->mnt_root, dentry,
oflag, mode, u_attr);
}
- } else
- filp = (dentry->d_inode) ? do_open(dentry, oflag) :
- ERR_PTR(-ENOENT);
-
- dput(dentry);
+ } else {
+ error = -ENOENT;
+ if (!dentry->d_inode)
+ goto out;
+ filp = do_open(dentry, oflag);
+ }
if (IS_ERR(filp)) {
error = PTR_ERR(filp);
@@ -691,13 +697,15 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
fd_install(fd, filp);
goto out_upsem;
-out_putfd:
+out:
+ dput(dentry);
mntput(mqueue_mnt);
+out_putfd:
put_unused_fd(fd);
out_err:
fd = error;
out_upsem:
- up(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
out_putname:
putname(name);
return fd;
@@ -714,7 +722,7 @@ asmlinkage long sys_mq_unlink(const char __user *u_name)
if (IS_ERR(name))
return PTR_ERR(name);
- down(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
@@ -735,7 +743,7 @@ out_err:
dput(dentry);
out_unlock:
- up(&mqueue_mnt->mnt_root->d_inode->i_sem);
+ mutex_unlock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
putname(name);
if (inode)
iput(inode);
diff --git a/ipc/msg.c b/ipc/msg.c
index d035bd2aba9..fbf757064a3 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -12,9 +12,10 @@
*
* mostly rewritten, threaded and wake-one semantics added
* MSGMAX limit removed, sysctl's added
- * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
*/
+#include <linux/capability.h>
#include <linux/config.h>
#include <linux/slab.h>
#include <linux/msg.h>
diff --git a/ipc/sem.c b/ipc/sem.c
index 19af028a3e3..31fd4027d2b 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -56,7 +56,7 @@
* /proc/sysvipc/sem support (c) 1999 Dragos Acostachioaie <dragos@iname.com>
*
* SMP-threaded, sysctl's added
- * (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * (c) 1999 Manfred Spraul <manfred@colorfullife.com>
* Enforced range limit on SEM_UNDO
* (c) 2001 Red Hat Inc <alan@redhat.com>
* Lockless wakeup
@@ -73,6 +73,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
+#include <linux/capability.h>
#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include "util.h"
@@ -381,6 +382,7 @@ static void update_queue (struct sem_array * sma)
/* hands-off: q will disappear immediately after
* writing q->status.
*/
+ smp_wmb();
q->status = error;
q = n;
} else {
@@ -461,6 +463,7 @@ static void freeary (struct sem_array *sma, int id)
n = q->next;
q->status = IN_WAKEUP;
wake_up_process(q->sleeper); /* doesn't sleep */
+ smp_wmb();
q->status = -EIDRM; /* hands-off q */
q = n;
}
diff --git a/ipc/shm.c b/ipc/shm.c
index 587d836d80d..4c28d2d8e30 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -27,6 +27,7 @@
#include <linux/security.h>
#include <linux/syscalls.h>
#include <linux/audit.h>
+#include <linux/capability.h>
#include <linux/ptrace.h>
#include <linux/seq_file.h>
@@ -34,8 +35,6 @@
#include "util.h"
-#define shm_flags shm_perm.mode
-
static struct file_operations shm_file_operations;
static struct vm_operations_struct shm_vm_ops;
@@ -148,7 +147,7 @@ static void shm_close (struct vm_area_struct *shmd)
shp->shm_dtim = get_seconds();
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
- shp->shm_flags & SHM_DEST)
+ shp->shm_perm.mode & SHM_DEST)
shm_destroy (shp);
else
shm_unlock(shp);
@@ -157,14 +156,22 @@ static void shm_close (struct vm_area_struct *shmd)
static int shm_mmap(struct file * file, struct vm_area_struct * vma)
{
- file_accessed(file);
- vma->vm_ops = &shm_vm_ops;
- shm_inc(file->f_dentry->d_inode->i_ino);
- return 0;
+ int ret;
+
+ ret = shmem_mmap(file, vma);
+ if (ret == 0) {
+ vma->vm_ops = &shm_vm_ops;
+ shm_inc(file->f_dentry->d_inode->i_ino);
+ }
+
+ return ret;
}
static struct file_operations shm_file_operations = {
- .mmap = shm_mmap
+ .mmap = shm_mmap,
+#ifndef CONFIG_MMU
+ .get_unmapped_area = shmem_get_unmapped_area,
+#endif
};
static struct vm_operations_struct shm_vm_ops = {
@@ -197,7 +204,7 @@ static int newseg (key_t key, int shmflg, size_t size)
return -ENOMEM;
shp->shm_perm.key = key;
- shp->shm_flags = (shmflg & S_IRWXUGO);
+ shp->shm_perm.mode = (shmflg & S_IRWXUGO);
shp->mlock_user = NULL;
shp->shm_perm.security = NULL;
@@ -337,7 +344,7 @@ static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __
out->uid = tbuf.shm_perm.uid;
out->gid = tbuf.shm_perm.gid;
- out->mode = tbuf.shm_flags;
+ out->mode = tbuf.shm_perm.mode;
return 0;
}
@@ -350,7 +357,7 @@ static inline unsigned long copy_shmid_from_user(struct shm_setbuf *out, void __
out->uid = tbuf_old.shm_perm.uid;
out->gid = tbuf_old.shm_perm.gid;
- out->mode = tbuf_old.shm_flags;
+ out->mode = tbuf_old.shm_perm.mode;
return 0;
}
@@ -552,13 +559,13 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
if (!is_file_hugepages(shp->shm_file)) {
err = shmem_lock(shp->shm_file, 1, user);
if (!err) {
- shp->shm_flags |= SHM_LOCKED;
+ shp->shm_perm.mode |= SHM_LOCKED;
shp->mlock_user = user;
}
}
} else if (!is_file_hugepages(shp->shm_file)) {
shmem_lock(shp->shm_file, 0, shp->mlock_user);
- shp->shm_flags &= ~SHM_LOCKED;
+ shp->shm_perm.mode &= ~SHM_LOCKED;
shp->mlock_user = NULL;
}
shm_unlock(shp);
@@ -597,7 +604,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
goto out_unlock_up;
if (shp->shm_nattch){
- shp->shm_flags |= SHM_DEST;
+ shp->shm_perm.mode |= SHM_DEST;
/* Do not find it any more */
shp->shm_perm.key = IPC_PRIVATE;
shm_unlock(shp);
@@ -636,7 +643,7 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
shp->shm_perm.uid = setbuf.uid;
shp->shm_perm.gid = setbuf.gid;
- shp->shm_flags = (shp->shm_flags & ~S_IRWXUGO)
+ shp->shm_perm.mode = (shp->shm_perm.mode & ~S_IRWXUGO)
| (setbuf.mode & S_IRWXUGO);
shp->shm_ctim = get_seconds();
break;
@@ -769,7 +776,7 @@ invalid:
BUG();
shp->shm_nattch--;
if(shp->shm_nattch == 0 &&
- shp->shm_flags & SHM_DEST)
+ shp->shm_perm.mode & SHM_DEST)
shm_destroy (shp);
else
shm_unlock(shp);
@@ -894,7 +901,7 @@ static int sysvipc_shm_proc_show(struct seq_file *s, void *it)
return seq_printf(s, format,
shp->shm_perm.key,
shp->id,
- shp->shm_flags,
+ shp->shm_perm.mode,
shp->shm_segsz,
shp->shm_cprid,
shp->shm_lprid,
diff --git a/ipc/util.c b/ipc/util.c
index 23f1cec150c..862621980b0 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -7,7 +7,7 @@
* Occurs in several places in the IPC code.
* Chris Evans, <chris@ferret.lmh.ox.ac.uk>
* Nov 1999 - ipc helper functions, unified SMP locking
- * Manfred Spraul <manfreds@colorfullife.com>
+ * Manfred Spraul <manfred@colorfullife.com>
* Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
* Mingming Cao <cmm@us.ibm.com>
*/
@@ -20,6 +20,7 @@
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/capability.h>
#include <linux/highuid.h>
#include <linux/security.h>
#include <linux/rcupdate.h>
diff --git a/ipc/util.h b/ipc/util.h
index fc9a28be079..efaff3ee7de 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -2,7 +2,7 @@
* linux/ipc/util.h
* Copyright (C) 1999 Christoph Rohland
*
- * ipc helper functions (c) 1999 Manfred Spraul <manfreds@colorfullife.com>
+ * ipc helper functions (c) 1999 Manfred Spraul <manfred@colorfullife.com>
*/
#ifndef _IPC_UTIL_H