diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/mqueue.c | 15 | ||||
-rw-r--r-- | ipc/msg.c | 7 | ||||
-rw-r--r-- | ipc/msgutil.c | 3 | ||||
-rw-r--r-- | ipc/util.c | 15 |
4 files changed, 25 insertions, 15 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index e5c4f609f22c..e4e47f647446 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -330,8 +330,16 @@ static struct dentry *mqueue_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { - if (!(flags & MS_KERNMOUNT)) - data = current->nsproxy->ipc_ns; + if (!(flags & MS_KERNMOUNT)) { + struct ipc_namespace *ns = current->nsproxy->ipc_ns; + /* Don't allow mounting unless the caller has CAP_SYS_ADMIN + * over the ipc namespace. + */ + if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN)) + return ERR_PTR(-EPERM); + + data = ns; + } return mount_ns(fs_type, flags, data, mqueue_fill_super); } @@ -840,7 +848,8 @@ out_putfd: fd = error; } mutex_unlock(&root->d_inode->i_mutex); - mnt_drop_write(mnt); + if (!ro) + mnt_drop_write(mnt); out_putname: putname(name); return fd; diff --git a/ipc/msg.c b/ipc/msg.c index 950572f9d796..fede1d06ef30 100644 --- a/ipc/msg.c +++ b/ipc/msg.c @@ -820,15 +820,17 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, struct msg_msg *copy = NULL; unsigned long copy_number = 0; + ns = current->nsproxy->ipc_ns; + if (msqid < 0 || (long) bufsz < 0) return -EINVAL; if (msgflg & MSG_COPY) { - copy = prepare_copy(buf, bufsz, msgflg, &msgtyp, ©_number); + copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax), + msgflg, &msgtyp, ©_number); if (IS_ERR(copy)) return PTR_ERR(copy); } mode = convert_mode(&msgtyp, msgflg); - ns = current->nsproxy->ipc_ns; msq = msg_lock_check(ns, msqid); if (IS_ERR(msq)) { @@ -870,6 +872,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, goto out_unlock; break; } + msg = ERR_PTR(-EAGAIN); } else break; msg_counter++; diff --git a/ipc/msgutil.c b/ipc/msgutil.c index ebfcbfa8b7f2..5df8e4bf1db0 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -117,9 +117,6 @@ struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst) if (alen > DATALEN_MSG) alen = DATALEN_MSG; - dst->next = NULL; - dst->security = NULL; - memcpy(dst + 1, src + 1, alen); len -= alen; diff --git a/ipc/util.c b/ipc/util.c index 464a8abd779f..03eadd8fb0fd 100644 --- a/ipc/util.c +++ b/ipc/util.c @@ -23,6 +23,7 @@ #include <linux/msg.h> #include <linux/vmalloc.h> #include <linux/slab.h> +#include <linux/notifier.h> #include <linux/capability.h> #include <linux/highuid.h> #include <linux/security.h> @@ -47,19 +48,16 @@ struct ipc_proc_iface { int (*show)(struct seq_file *, void *); }; -#ifdef CONFIG_MEMORY_HOTPLUG - static void ipc_memory_notifier(struct work_struct *work) { ipcns_notify(IPCNS_MEMCHANGED); } -static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier); - - static int ipc_memory_callback(struct notifier_block *self, unsigned long action, void *arg) { + static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier); + switch (action) { case MEM_ONLINE: /* memory successfully brought online */ case MEM_OFFLINE: /* or offline: it's time to recompute msgmni */ @@ -85,7 +83,10 @@ static int ipc_memory_callback(struct notifier_block *self, return NOTIFY_OK; } -#endif /* CONFIG_MEMORY_HOTPLUG */ +static struct notifier_block ipc_memory_nb = { + .notifier_call = ipc_memory_callback, + .priority = IPC_CALLBACK_PRI, +}; /** * ipc_init - initialise IPC subsystem @@ -102,7 +103,7 @@ static int __init ipc_init(void) sem_init(); msg_init(); shm_init(); - hotplug_memory_notifier(ipc_memory_callback, IPC_CALLBACK_PRI); + register_hotmemory_notifier(&ipc_memory_nb); register_ipcns_notifier(&init_ipc_ns); return 0; } |