diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/mqueue.c | 68 | ||||
-rw-r--r-- | ipc/msg.c | 3 | ||||
-rw-r--r-- | ipc/sem.c | 5 | ||||
-rw-r--r-- | ipc/shm.c | 41 | ||||
-rw-r--r-- | ipc/util.c | 3 | ||||
-rw-r--r-- | ipc/util.h | 2 |
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 |