git://git.onelab.eu
/
linux-2.6.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git]
/
ipc
/
mqueue.c
diff --git
a/ipc/mqueue.c
b/ipc/mqueue.c
index
aee2696
..
44da667
100644
(file)
--- a/
ipc/mqueue.c
+++ b/
ipc/mqueue.c
@@
-2,15
+2,18
@@
* POSIX message queues filesystem for Linux.
*
* Copyright (C) 2003,2004 Krzysztof Benedyczak (golbi@mat.uni.torun.pl)
* POSIX message queues filesystem for Linux.
*
* Copyright (C) 2003,2004 Krzysztof Benedyczak (golbi@mat.uni.torun.pl)
- * Michal Wronski (
wrona@mat.uni.torun.pl
)
+ * Michal Wronski (
michal.wronski@gmail.com
)
*
* Spinlocks: Mohamed Abbas (abbas.mohamed@intel.com)
* Lockless receive & send, fd based notify:
* Manfred Spraul (manfred@colorfullife.com)
*
*
* Spinlocks: Mohamed Abbas (abbas.mohamed@intel.com)
* Lockless receive & send, fd based notify:
* Manfred Spraul (manfred@colorfullife.com)
*
+ * Audit: George Wilson (ltcgcw@us.ibm.com)
+ *
* This file is released under the GPL.
*/
* This file is released under the GPL.
*/
+#include <linux/capability.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/file.h>
#include <linux/init.h>
#include <linux/pagemap.h>
#include <linux/file.h>
@@
-22,6
+25,13
@@
#include <linux/msg.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/msg.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
+#include <linux/syscalls.h>
+#include <linux/audit.h>
+#include <linux/signal.h>
+#include <linux/mutex.h>
+#include <linux/vs_context.h>
+#include <linux/vs_limit.h>
+
#include <net/sock.h>
#include "util.h"
#include <net/sock.h>
#include "util.h"
@@
-48,7
+58,6
@@
#define HARD_MSGMAX (131072/sizeof(void*))
#define DFLT_MSGSIZEMAX 8192 /* max message size */
#define HARD_MSGMAX (131072/sizeof(void*))
#define DFLT_MSGSIZEMAX 8192 /* max message size */
-#define NOTIFY_COOKIE_LEN 32
struct ext_wait_queue { /* queue of sleeping tasks */
struct task_struct *task;
struct ext_wait_queue { /* queue of sleeping tasks */
struct task_struct *task;
@@
-66,8
+75,8
@@
struct mqueue_inode_info {
struct mq_attr attr;
struct sigevent notify;
struct mq_attr attr;
struct sigevent notify;
-
pid_t
notify_owner;
- struct user_struct *user; /* user who created, for accouting */
+
struct pid*
notify_owner;
+ struct user_struct *user; /* user who created, for accou
n
ting */
struct sock *notify_sock;
struct sk_buff *notify_cookie;
struct sock *notify_sock;
struct sk_buff *notify_cookie;
@@
-83,7
+92,7
@@
static struct super_operations mqueue_super_ops;
static void remove_notification(struct mqueue_inode_info *info);
static spinlock_t mq_lock;
static void remove_notification(struct mqueue_inode_info *info);
static spinlock_t mq_lock;
-static
kmem_cache_t
*mqueue_inode_cachep;
+static
struct kmem_cache
*mqueue_inode_cachep;
static struct vfsmount *mqueue_mnt;
static unsigned int queues_count;
static struct vfsmount *mqueue_mnt;
static unsigned int queues_count;
@@
-108,7
+117,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_mode = mode;
inode->i_uid = current->fsuid;
inode->i_gid = current->fsgid;
- inode->i_blksize = PAGE_CACHE_SIZE;
inode->i_blocks = 0;
inode->i_mtime = inode->i_ctime = inode->i_atime =
CURRENT_TIME;
inode->i_blocks = 0;
inode->i_mtime = inode->i_ctime = inode->i_atime =
CURRENT_TIME;
@@
-128,7
+136,7
@@
static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
INIT_LIST_HEAD(&info->e_wait_q[0].list);
INIT_LIST_HEAD(&info->e_wait_q[1].list);
info->messages = NULL;
INIT_LIST_HEAD(&info->e_wait_q[0].list);
INIT_LIST_HEAD(&info->e_wait_q[1].list);
info->messages = NULL;
- info->notify_owner =
0
;
+ info->notify_owner =
NULL
;
info->qsize = 0;
info->user = NULL; /* set when all is ok */
memset(&info->attr, 0, sizeof(info->attr));
info->qsize = 0;
info->user = NULL; /* set when all is ok */
memset(&info->attr, 0, sizeof(info->attr));
@@
-145,24
+153,27
@@
static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
spin_lock(&mq_lock);
if (u->mq_bytes + mq_bytes < u->mq_bytes ||
u->mq_bytes + mq_bytes >
spin_lock(&mq_lock);
if (u->mq_bytes + mq_bytes < u->mq_bytes ||
u->mq_bytes + mq_bytes >
- p->rlim[RLIMIT_MSGQUEUE].rlim_cur) {
+ p->signal->rlim[RLIMIT_MSGQUEUE].rlim_cur ||
+ !vx_ipcmsg_avail(p->vx_info, mq_bytes)) {
spin_unlock(&mq_lock);
goto out_inode;
}
u->mq_bytes += mq_bytes;
spin_unlock(&mq_lock);
goto out_inode;
}
u->mq_bytes += mq_bytes;
+ vx_ipcmsg_add(p->vx_info, u, mq_bytes);
spin_unlock(&mq_lock);
info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
if (!info->messages) {
spin_lock(&mq_lock);
u->mq_bytes -= mq_bytes;
spin_unlock(&mq_lock);
info->messages = kmalloc(mq_msg_tblsz, GFP_KERNEL);
if (!info->messages) {
spin_lock(&mq_lock);
u->mq_bytes -= mq_bytes;
+ vx_ipcmsg_sub(p->vx_info, u, mq_bytes);
spin_unlock(&mq_lock);
goto out_inode;
}
/* all is ok */
info->user = get_uid(u);
} else if (S_ISDIR(mode)) {
spin_unlock(&mq_lock);
goto out_inode;
}
/* all is ok */
info->user = get_uid(u);
} else if (S_ISDIR(mode)) {
- in
ode->i_nlink++
;
+ in
c_nlink(inode)
;
/* Some things misbehave if size == 0 on a directory */
inode->i_size = 2 * DIRENT_SIZE;
inode->i_op = &mqueue_dir_inode_operations;
/* Some things misbehave if size == 0 on a directory */
inode->i_size = 2 * DIRENT_SIZE;
inode->i_op = &mqueue_dir_inode_operations;
@@
-198,14
+209,14
@@
static int mqueue_fill_super(struct super_block *sb, void *data, int silent)
return 0;
}
return 0;
}
-static
struct super_block *
mqueue_get_sb(struct file_system_type *fs_type,
-
int flags, const char *dev_name,
-
void *data
)
+static
int
mqueue_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name,
+
void *data, struct vfsmount *mnt
)
{
{
- return get_sb_single(fs_type, flags, data, mqueue_fill_super);
+ return get_sb_single(fs_type, flags, data, mqueue_fill_super
, mnt
);
}
}
-static void init_once(void *foo,
kmem_cache_t
* cachep, unsigned long flags)
+static void init_once(void *foo,
struct kmem_cache
* cachep, unsigned long flags)
{
struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
{
struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
@@
-218,7
+229,7
@@
static struct inode *mqueue_alloc_inode(struct super_block *sb)
{
struct mqueue_inode_info *ei;
{
struct mqueue_inode_info *ei;
- ei = kmem_cache_alloc(mqueue_inode_cachep,
SLAB
_KERNEL);
+ ei = kmem_cache_alloc(mqueue_inode_cachep,
GFP
_KERNEL);
if (!ei)
return NULL;
return &ei->vfs_inode;
if (!ei)
return NULL;
return &ei->vfs_inode;
@@
-253,10
+264,14
@@
static void mqueue_delete_inode(struct inode *inode)
(info->attr.mq_maxmsg * info->attr.mq_msgsize));
user = info->user;
if (user) {
(info->attr.mq_maxmsg * info->attr.mq_msgsize));
user = info->user;
if (user) {
+ struct vx_info *vxi = lookup_vx_info(user->xid);
+
spin_lock(&mq_lock);
user->mq_bytes -= mq_bytes;
spin_lock(&mq_lock);
user->mq_bytes -= mq_bytes;
+ vx_ipcmsg_sub(vxi, user, mq_bytes);
queues_count--;
spin_unlock(&mq_lock);
queues_count--;
spin_unlock(&mq_lock);
+ put_vx_info(vxi);
free_uid(user);
}
}
free_uid(user);
}
}
@@
-301,7
+316,7
@@
static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
dir->i_size -= DIRENT_SIZE;
dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;
dir->i_size -= DIRENT_SIZE;
-
inode->i_nlink--
;
+
drop_nlink(inode)
;
dput(dentry);
return 0;
}
dput(dentry);
return 0;
}
@@
-316,7
+331,7
@@
static int mqueue_unlink(struct inode *dir, struct dentry *dentry)
static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
size_t count, loff_t * off)
{
static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
size_t count, loff_t * off)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_
path.
dentry->d_inode);
char buffer[FILENT_SIZE];
size_t slen;
loff_t o;
char buffer[FILENT_SIZE];
size_t slen;
loff_t o;
@@
-332,7
+347,7
@@
static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
(info->notify_owner &&
info->notify.sigev_notify == SIGEV_SIGNAL) ?
info->notify.sigev_signo : 0,
(info->notify_owner &&
info->notify.sigev_notify == SIGEV_SIGNAL) ?
info->notify.sigev_signo : 0,
-
info->notify_owner
);
+
pid_nr(info->notify_owner)
);
spin_unlock(&info->lock);
buffer[sizeof(buffer)-1] = '\0';
slen = strlen(buffer)+1;
spin_unlock(&info->lock);
buffer[sizeof(buffer)-1] = '\0';
slen = strlen(buffer)+1;
@@
-348,16
+363,16
@@
static ssize_t mqueue_read_file(struct file *filp, char __user *u_data,
return -EFAULT;
*off = o + count;
return -EFAULT;
*off = o + count;
- filp->f_
dentry->d_inode->i_atime = filp->f_
dentry->d_inode->i_ctime = CURRENT_TIME;
+ filp->f_
path.dentry->d_inode->i_atime = filp->f_path.
dentry->d_inode->i_ctime = CURRENT_TIME;
return count;
}
return count;
}
-static int mqueue_flush_file(struct file *filp)
+static int mqueue_flush_file(struct file *filp
, fl_owner_t id
)
{
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_
path.
dentry->d_inode);
spin_lock(&info->lock);
spin_lock(&info->lock);
- if (
current->tgid
== info->notify_owner)
+ if (
task_tgid(current)
== info->notify_owner)
remove_notification(info);
spin_unlock(&info->lock);
remove_notification(info);
spin_unlock(&info->lock);
@@
-366,7
+381,7
@@
static int mqueue_flush_file(struct file *filp)
static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab)
{
static unsigned int mqueue_poll_file(struct file *filp, struct poll_table_struct *poll_tab)
{
- struct mqueue_inode_info *info = MQUEUE_I(filp->f_dentry->d_inode);
+ struct mqueue_inode_info *info = MQUEUE_I(filp->f_
path.
dentry->d_inode);
int retval = 0;
poll_wait(filp, &info->wait_q, poll_tab);
int retval = 0;
poll_wait(filp, &info->wait_q, poll_tab);
@@
-512,8
+527,8
@@
static void __do_notify(struct mqueue_inode_info *info)
sig_i.si_pid = current->tgid;
sig_i.si_uid = current->uid;
sig_i.si_pid = current->tgid;
sig_i.si_uid = current->uid;
- kill_p
roc
_info(info->notify.sigev_signo,
-
&sig_i, info->notify_owner);
+ kill_p
id
_info(info->notify.sigev_signo,
+ &sig_i, info->notify_owner);
break;
case SIGEV_THREAD:
set_cookie(info->notify_cookie, NOTIFY_WOKENUP);
break;
case SIGEV_THREAD:
set_cookie(info->notify_cookie, NOTIFY_WOKENUP);
@@
-522,7
+537,8
@@
static void __do_notify(struct mqueue_inode_info *info)
break;
}
/* after notification unregisters process */
break;
}
/* after notification unregisters process */
- info->notify_owner = 0;
+ put_pid(info->notify_owner);
+ info->notify_owner = NULL;
}
wake_up(&info->wait_q);
}
}
wake_up(&info->wait_q);
}
@@
-560,12
+576,13
@@
static long prepare_timeout(const struct timespec __user *u_arg)
static void remove_notification(struct mqueue_inode_info *info)
{
static void remove_notification(struct mqueue_inode_info *info)
{
- if (info->notify_owner !=
0
&&
+ if (info->notify_owner !=
NULL
&&
info->notify.sigev_notify == SIGEV_THREAD) {
set_cookie(info->notify_cookie, NOTIFY_REMOVED);
netlink_sendskb(info->notify_sock, info->notify_cookie, 0);
}
info->notify.sigev_notify == SIGEV_THREAD) {
set_cookie(info->notify_cookie, NOTIFY_REMOVED);
netlink_sendskb(info->notify_sock, info->notify_cookie, 0);
}
- info->notify_owner = 0;
+ put_pid(info->notify_owner);
+ info->notify_owner = NULL;
}
static int mq_attr_ok(struct mq_attr *attr)
}
static int mq_attr_ok(struct mq_attr *attr)
@@
-596,29
+613,32
@@
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)
{
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;
struct mq_attr attr;
int ret;
- if (u_attr != NULL) {
+ if (u_attr) {
+ ret = -EFAULT;
if (copy_from_user(&attr, u_attr, sizeof(attr)))
if (copy_from_user(&attr, u_attr, sizeof(attr)))
- return ERR_PTR(-EFAULT);
+ goto out;
+ ret = -EINVAL;
if (!mq_attr_ok(&attr))
if (!mq_attr_ok(&attr))
-
return ERR_PTR(-EINVAL)
;
+
goto out
;
/* store for use during create */
dentry->d_fsdata = &attr;
}
/* store for use during create */
dentry->d_fsdata = &attr;
}
+ mode &= ~current->fs->umask;
ret = vfs_create(dir->d_inode, dentry, mode, NULL);
dentry->d_fsdata = NULL;
if (ret)
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 */
}
/* Opens existing queue */
@@
-626,20
+646,20
@@
static struct file *do_open(struct dentry *dentry, int oflag)
{
static int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
MAY_READ | MAY_WRITE };
{
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);
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);
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,
}
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
@@
-650,6
+670,10
@@
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
char *name;
int fd, error;
char *name;
int fd, error;
+ error = audit_mq_open(oflag, mode, u_attr);
+ if (error != 0)
+ return error;
+
if (IS_ERR(name = getname(u_name)))
return PTR_ERR(name);
if (IS_ERR(name = getname(u_name)))
return PTR_ERR(name);
@@
-657,7
+681,7
@@
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
if (fd < 0)
goto out_putname;
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);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) {
error = PTR_ERR(dentry);
@@
-667,17
+691,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 */
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 = 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);
if (IS_ERR(filp)) {
error = PTR_ERR(filp);
@@
-688,13
+715,15
@@
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
fd_install(fd, filp);
goto out_upsem;
fd_install(fd, filp);
goto out_upsem;
-out_putfd:
+out:
+ dput(dentry);
mntput(mqueue_mnt);
mntput(mqueue_mnt);
+out_putfd:
put_unused_fd(fd);
out_err:
fd = error;
out_upsem:
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;
out_putname:
putname(name);
return fd;
@@
-711,7
+740,7
@@
asmlinkage long sys_mq_unlink(const char __user *u_name)
if (IS_ERR(name))
return PTR_ERR(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);
dentry = lookup_one_len(name, mqueue_mnt->mnt_root, strlen(name));
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
@@
-727,12
+756,12
@@
asmlinkage long sys_mq_unlink(const char __user *u_name)
if (inode)
atomic_inc(&inode->i_count);
if (inode)
atomic_inc(&inode->i_count);
- err = vfs_unlink(dentry->d_parent->d_inode, dentry);
+ err = vfs_unlink(dentry->d_parent->d_inode, dentry
, NULL
);
out_err:
dput(dentry);
out_unlock:
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);
putname(name);
if (inode)
iput(inode);
@@
-750,7
+779,7
@@
out_unlock:
* The receiver accepts the message and returns without grabbing the queue
* spinlock. Therefore an intermediate STATE_PENDING state and memory barriers
* are necessary. The same algorithm is used for sysv semaphores, see
* The receiver accepts the message and returns without grabbing the queue
* spinlock. Therefore an intermediate STATE_PENDING state and memory barriers
* are necessary. The same algorithm is used for sysv semaphores, see
- * ipc/sem.c for
e
more details.
+ * ipc/sem.c for more details.
*
* The same algorithm is used for senders.
*/
*
* The same algorithm is used for senders.
*/
@@
-766,7
+795,7
@@
static inline void pipelined_send(struct mqueue_inode_info *info,
list_del(&receiver->list);
receiver->state = STATE_PENDING;
wake_up_process(receiver->task);
list_del(&receiver->list);
receiver->state = STATE_PENDING;
wake_up_process(receiver->task);
- wmb();
+
smp_
wmb();
receiver->state = STATE_READY;
}
receiver->state = STATE_READY;
}
@@
-785,7
+814,7
@@
static inline void pipelined_receive(struct mqueue_inode_info *info)
list_del(&sender->list);
sender->state = STATE_PENDING;
wake_up_process(sender->task);
list_del(&sender->list);
sender->state = STATE_PENDING;
wake_up_process(sender->task);
- wmb();
+
smp_
wmb();
sender->state = STATE_READY;
}
sender->state = STATE_READY;
}
@@
-802,6
+831,10
@@
asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
long timeout;
int ret;
long timeout;
int ret;
+ ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout);
+ if (ret != 0)
+ return ret;
+
if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
return -EINVAL;
if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX))
return -EINVAL;
@@
-812,7
+845,7
@@
asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr,
if (unlikely(!filp))
goto out;
if (unlikely(!filp))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_
path.
dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@
-884,6
+917,10
@@
asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
struct mqueue_inode_info *info;
struct ext_wait_queue wait;
struct mqueue_inode_info *info;
struct ext_wait_queue wait;
+ ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout);
+ if (ret != 0)
+ return ret;
+
timeout = prepare_timeout(u_abs_timeout);
ret = -EBADF;
timeout = prepare_timeout(u_abs_timeout);
ret = -EBADF;
@@
-891,7
+928,7
@@
asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr,
if (unlikely(!filp))
goto out;
if (unlikely(!filp))
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_
path.
dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@
-963,6
+1000,10
@@
asmlinkage long sys_mq_notify(mqd_t mqdes,
struct mqueue_inode_info *info;
struct sk_buff *nc;
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) {
nc = NULL;
sock = NULL;
if (u_notification != NULL) {
@@
-975,8
+1016,7
@@
asmlinkage long sys_mq_notify(mqd_t mqdes,
notification.sigev_notify != SIGEV_THREAD))
return -EINVAL;
if (notification.sigev_notify == SIGEV_SIGNAL &&
notification.sigev_notify != SIGEV_THREAD))
return -EINVAL;
if (notification.sigev_notify == SIGEV_SIGNAL &&
- (notification.sigev_signo < 0 ||
- notification.sigev_signo > _NSIG)) {
+ !valid_signal(notification.sigev_signo)) {
return -EINVAL;
}
if (notification.sigev_notify == SIGEV_THREAD) {
return -EINVAL;
}
if (notification.sigev_notify == SIGEV_THREAD) {
@@
-1008,7
+1048,8
@@
retry:
goto out;
}
goto out;
}
- ret = netlink_attachskb(sock, nc, 0, MAX_SCHEDULE_TIMEOUT);
+ ret = netlink_attachskb(sock, nc, 0,
+ MAX_SCHEDULE_TIMEOUT, NULL);
if (ret == 1)
goto retry;
if (ret) {
if (ret == 1)
goto retry;
if (ret) {
@@
-1024,7
+1065,7
@@
retry:
if (!filp)
goto out;
if (!filp)
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_
path.
dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@
-1032,11
+1073,11
@@
retry:
ret = 0;
spin_lock(&info->lock);
if (u_notification == NULL) {
ret = 0;
spin_lock(&info->lock);
if (u_notification == NULL) {
- if (info->notify_owner ==
current->tgid
) {
+ if (info->notify_owner ==
task_tgid(current)
) {
remove_notification(info);
inode->i_atime = inode->i_ctime = CURRENT_TIME;
}
remove_notification(info);
inode->i_atime = inode->i_ctime = CURRENT_TIME;
}
- } else if (info->notify_owner !=
0
) {
+ } else if (info->notify_owner !=
NULL
) {
ret = -EBUSY;
} else {
switch (notification.sigev_notify) {
ret = -EBUSY;
} else {
switch (notification.sigev_notify) {
@@
-1056,7
+1097,8
@@
retry:
info->notify.sigev_notify = SIGEV_SIGNAL;
break;
}
info->notify.sigev_notify = SIGEV_SIGNAL;
break;
}
- info->notify_owner = current->tgid;
+
+ info->notify_owner = get_pid(task_tgid(current));
inode->i_atime = inode->i_ctime = CURRENT_TIME;
}
spin_unlock(&info->lock);
inode->i_atime = inode->i_ctime = CURRENT_TIME;
}
spin_unlock(&info->lock);
@@
-1093,7
+1135,7
@@
asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
if (!filp)
goto out;
if (!filp)
goto out;
- inode = filp->f_dentry->d_inode;
+ inode = filp->f_
path.
dentry->d_inode;
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
if (unlikely(filp->f_op != &mqueue_file_operations))
goto out_fput;
info = MQUEUE_I(inode);
@@
-1103,6
+1145,9
@@
asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
omqstat = info->attr;
omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
if (u_mqstat) {
omqstat = info->attr;
omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
if (u_mqstat) {
+ ret = audit_mq_getsetattr(mqdes, &mqstat);
+ if (ret != 0)
+ goto out;
if (mqstat.mq_flags & O_NONBLOCK)
filp->f_flags |= O_NONBLOCK;
else
if (mqstat.mq_flags & O_NONBLOCK)
filp->f_flags |= O_NONBLOCK;
else
@@
-1218,11
+1263,8
@@
static int __init init_mqueue_fs(void)
if (mqueue_inode_cachep == NULL)
return -ENOMEM;
if (mqueue_inode_cachep == NULL)
return -ENOMEM;
+ /* ignore failues - they are not fatal */
mq_sysctl_table = register_sysctl_table(mq_sysctl_root, 0);
mq_sysctl_table = register_sysctl_table(mq_sysctl_root, 0);
- if (!mq_sysctl_table) {
- error = -ENOMEM;
- goto out_cache;
- }
error = register_filesystem(&mqueue_fs_type);
if (error)
error = register_filesystem(&mqueue_fs_type);
if (error)
@@
-1242,12
+1284,9
@@
static int __init init_mqueue_fs(void)
out_filesystem:
unregister_filesystem(&mqueue_fs_type);
out_sysctl:
out_filesystem:
unregister_filesystem(&mqueue_fs_type);
out_sysctl:
- unregister_sysctl_table(mq_sysctl_table);
-out_cache:
- if (kmem_cache_destroy(mqueue_inode_cachep)) {
- printk(KERN_INFO
- "mqueue_inode_cache: not all structures were freed\n");
- }
+ if (mq_sysctl_table)
+ unregister_sysctl_table(mq_sysctl_table);
+ kmem_cache_destroy(mqueue_inode_cachep);
return error;
}
return error;
}