git://ftp.safe.ca
/
safe
/
jmp
/
linux-2.6
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Pidns: fix badly converted mqueues pid handling
[safe/jmp/linux-2.6]
/
ipc
/
mqueue.c
diff --git
a/ipc/mqueue.c
b/ipc/mqueue.c
index
f8381f0
..
60f7a27
100644
(file)
--- a/
ipc/mqueue.c
+++ b/
ipc/mqueue.c
@@
-2,7
+2,7
@@
* 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 (
Michal.Wronski@motorola
.com)
+ * Michal Wronski (
michal.wronski@gmail
.com)
*
* Spinlocks: Mohamed Abbas (abbas.mohamed@intel.com)
* Lockless receive & send, fd based notify:
*
* Spinlocks: Mohamed Abbas (abbas.mohamed@intel.com)
* Lockless receive & send, fd based notify:
@@
-29,6
+29,8
@@
#include <linux/audit.h>
#include <linux/signal.h>
#include <linux/mutex.h>
#include <linux/audit.h>
#include <linux/signal.h>
#include <linux/mutex.h>
+#include <linux/nsproxy.h>
+#include <linux/pid.h>
#include <net/sock.h>
#include "util.h"
#include <net/sock.h>
#include "util.h"
@@
-44,12
+46,6
@@
#define STATE_PENDING 1
#define STATE_READY 2
#define STATE_PENDING 1
#define STATE_READY 2
-/* used by sysctl */
-#define FS_MQUEUE 1
-#define CTL_QUEUESMAX 2
-#define CTL_MSGMAX 3
-#define CTL_MSGSIZEMAX 4
-
/* default values */
#define DFLT_QUEUESMAX 256 /* max number of message queues */
#define DFLT_MSGMAX 10 /* max number of messages in each queue */
/* default values */
#define DFLT_QUEUESMAX 256 /* max number of message queues */
#define DFLT_MSGMAX 10 /* max number of messages in each queue */
@@
-73,7
+69,7
@@
struct mqueue_inode_info {
struct mq_attr attr;
struct sigevent notify;
struct mq_attr attr;
struct sigevent notify;
-
pid_t
notify_owner;
+
struct pid*
notify_owner;
struct user_struct *user; /* user who created, for accounting */
struct sock *notify_sock;
struct sk_buff *notify_cookie;
struct user_struct *user; /* user who created, for accounting */
struct sock *notify_sock;
struct sk_buff *notify_cookie;
@@
-84,13
+80,13
@@
struct mqueue_inode_info {
unsigned long qsize; /* size of queue in memory (sum of all msgs) */
};
unsigned long qsize; /* size of queue in memory (sum of all msgs) */
};
-static struct inode_operations mqueue_dir_inode_operations;
-static struct file_operations mqueue_file_operations;
+static
const
struct inode_operations mqueue_dir_inode_operations;
+static
const
struct file_operations mqueue_file_operations;
static struct super_operations mqueue_super_ops;
static void remove_notification(struct mqueue_inode_info *info);
static spinlock_t mq_lock;
static struct super_operations mqueue_super_ops;
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;
@@
-115,7
+111,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;
@@
-135,7
+130,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));
@@
-169,7
+164,7
@@
static struct inode *mqueue_get_inode(struct super_block *sb, int mode,
/* all is ok */
info->user = get_uid(u);
} else if (S_ISDIR(mode)) {
/* 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;
@@
-212,20
+207,18
@@
static int mqueue_get_sb(struct file_system_type *fs_type,
return get_sb_single(fs_type, flags, data, mqueue_fill_super, mnt);
}
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(
struct kmem_cache *cachep, void *foo
)
{
struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
{
struct mqueue_inode_info *p = (struct mqueue_inode_info *) foo;
- if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) ==
- SLAB_CTOR_CONSTRUCTOR)
- inode_init_once(&p->vfs_inode);
+ inode_init_once(&p->vfs_inode);
}
static struct inode *mqueue_alloc_inode(struct super_block *sb)
{
struct mqueue_inode_info *ei;
}
static struct inode *mqueue_alloc_inode(struct super_block *sb)
{
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;
@@
-308,7
+301,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;
}
@@
-323,7
+316,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;
@@
-339,7
+332,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_vnr(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;
@@
-355,16
+348,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;
}
static int mqueue_flush_file(struct file *filp, fl_owner_t id)
{
return count;
}
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);
@@
-373,7
+366,7
@@
static int mqueue_flush_file(struct file *filp, fl_owner_t id)
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);
@@
-516,20
+509,20
@@
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_errno = 0;
sig_i.si_code = SI_MESGQ;
sig_i.si_value = info->notify.sigev_value;
- sig_i.si_pid =
current->tgid
;
+ sig_i.si_pid =
task_tgid_vnr(current)
;
sig_i.si_uid = current->uid;
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);
- netlink_sendskb(info->notify_sock,
- info->notify_cookie, 0);
+ netlink_sendskb(info->notify_sock, info->notify_cookie);
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);
}
@@
-567,12
+560,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);
info->notify.sigev_notify == SIGEV_THREAD) {
set_cookie(info->notify_cookie, NOTIFY_REMOVED);
- netlink_sendskb(info->notify_sock, info->notify_cookie
, 0
);
+ netlink_sendskb(info->notify_sock, info->notify_cookie);
}
}
- 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)
@@
-681,6
+675,7
@@
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 */
+ audit_inode(name, dentry);
error = -EEXIST;
if (oflag & O_EXCL)
goto out;
error = -EEXIST;
if (oflag & O_EXCL)
goto out;
@@
-693,6
+688,7
@@
asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode,
error = -ENOENT;
if (!dentry->d_inode)
goto out;
error = -ENOENT;
if (!dentry->d_inode)
goto out;
+ audit_inode(name, dentry);
filp = do_open(dentry, oflag);
}
filp = do_open(dentry, oflag);
}
@@
-730,7
+726,8
@@
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);
- mutex_lock(&mqueue_mnt->mnt_root->d_inode->i_mutex);
+ mutex_lock_nested(&mqueue_mnt->mnt_root->d_inode->i_mutex,
+ I_MUTEX_PARENT);
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);
@@
-835,10
+832,11
@@
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);
+ audit_inode(NULL, filp->f_path.dentry);
if (unlikely(!(filp->f_mode & FMODE_WRITE)))
goto out_fput;
if (unlikely(!(filp->f_mode & FMODE_WRITE)))
goto out_fput;
@@
-918,10
+916,11
@@
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);
+ audit_inode(NULL, filp->f_path.dentry);
if (unlikely(!(filp->f_mode & FMODE_READ)))
goto out_fput;
if (unlikely(!(filp->f_mode & FMODE_READ)))
goto out_fput;
@@
-1010,6
+1009,8
@@
asmlinkage long sys_mq_notify(mqd_t mqdes,
return -EINVAL;
}
if (notification.sigev_notify == SIGEV_THREAD) {
return -EINVAL;
}
if (notification.sigev_notify == SIGEV_THREAD) {
+ long timeo;
+
/* create the notify skb */
nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
ret = -ENOMEM;
/* create the notify skb */
nc = alloc_skb(NOTIFY_COOKIE_LEN, GFP_KERNEL);
ret = -ENOMEM;
@@
-1038,8
+1039,8
@@
retry:
goto out;
}
goto out;
}
- ret = netlink_attachskb(sock, nc, 0,
-
MAX_SCHEDULE_TIMEOUT
, NULL);
+ timeo = MAX_SCHEDULE_TIMEOUT;
+
ret = netlink_attachskb(sock, nc, 0, &timeo
, NULL);
if (ret == 1)
goto retry;
if (ret) {
if (ret == 1)
goto retry;
if (ret) {
@@
-1055,7
+1056,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);
@@
-1063,11
+1064,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) {
@@
-1087,7
+1088,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);
@@
-1124,7
+1126,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);
@@
-1135,8
+1137,10
@@
asmlinkage long sys_mq_getsetattr(mqd_t mqdes,
omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
if (u_mqstat) {
ret = audit_mq_getsetattr(mqdes, &mqstat);
omqstat.mq_flags = filp->f_flags & O_NONBLOCK;
if (u_mqstat) {
ret = audit_mq_getsetattr(mqdes, &mqstat);
- if (ret != 0)
- goto out;
+ if (ret != 0) {
+ spin_unlock(&info->lock);
+ goto out_fput;
+ }
if (mqstat.mq_flags & O_NONBLOCK)
filp->f_flags |= O_NONBLOCK;
else
if (mqstat.mq_flags & O_NONBLOCK)
filp->f_flags |= O_NONBLOCK;
else
@@
-1158,13
+1162,13
@@
out:
return ret;
}
return ret;
}
-static struct inode_operations mqueue_dir_inode_operations = {
+static
const
struct inode_operations mqueue_dir_inode_operations = {
.lookup = simple_lookup,
.create = mqueue_create,
.unlink = mqueue_unlink,
};
.lookup = simple_lookup,
.create = mqueue_create,
.unlink = mqueue_unlink,
};
-static struct file_operations mqueue_file_operations = {
+static
const
struct file_operations mqueue_file_operations = {
.flush = mqueue_flush_file,
.poll = mqueue_poll_file,
.read = mqueue_read_file,
.flush = mqueue_flush_file,
.poll = mqueue_poll_file,
.read = mqueue_read_file,
@@
-1192,7
+1196,6
@@
static int msg_maxsize_limit_max = INT_MAX;
static ctl_table mq_sysctls[] = {
{
static ctl_table mq_sysctls[] = {
{
- .ctl_name = CTL_QUEUESMAX,
.procname = "queues_max",
.data = &queues_max,
.maxlen = sizeof(int),
.procname = "queues_max",
.data = &queues_max,
.maxlen = sizeof(int),
@@
-1200,7
+1203,6
@@
static ctl_table mq_sysctls[] = {
.proc_handler = &proc_dointvec,
},
{
.proc_handler = &proc_dointvec,
},
{
- .ctl_name = CTL_MSGMAX,
.procname = "msg_max",
.data = &msg_max,
.maxlen = sizeof(int),
.procname = "msg_max",
.data = &msg_max,
.maxlen = sizeof(int),
@@
-1210,7
+1212,6
@@
static ctl_table mq_sysctls[] = {
.extra2 = &msg_max_limit_max,
},
{
.extra2 = &msg_max_limit_max,
},
{
- .ctl_name = CTL_MSGSIZEMAX,
.procname = "msgsize_max",
.data = &msgsize_max,
.maxlen = sizeof(int),
.procname = "msgsize_max",
.data = &msgsize_max,
.maxlen = sizeof(int),
@@
-1224,7
+1225,6
@@
static ctl_table mq_sysctls[] = {
static ctl_table mq_sysctl_dir[] = {
{
static ctl_table mq_sysctl_dir[] = {
{
- .ctl_name = FS_MQUEUE,
.procname = "mqueue",
.mode = 0555,
.child = mq_sysctls,
.procname = "mqueue",
.mode = 0555,
.child = mq_sysctls,
@@
-1248,12
+1248,12
@@
static int __init init_mqueue_fs(void)
mqueue_inode_cachep = kmem_cache_create("mqueue_inode_cache",
sizeof(struct mqueue_inode_info), 0,
mqueue_inode_cachep = kmem_cache_create("mqueue_inode_cache",
sizeof(struct mqueue_inode_info), 0,
- SLAB_HWCACHE_ALIGN, init_once
, NULL
);
+ SLAB_HWCACHE_ALIGN, init_once);
if (mqueue_inode_cachep == NULL)
return -ENOMEM;
/* ignore failues - they are not fatal */
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);
error = register_filesystem(&mqueue_fs_type);
if (error)
error = register_filesystem(&mqueue_fs_type);
if (error)