summaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
Diffstat (limited to 'ipc')
-rw-r--r--ipc/mqueue.c15
-rw-r--r--ipc/msg.c7
-rw-r--r--ipc/msgutil.c3
-rw-r--r--ipc/util.c15
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, &copy_number);
+ copy = prepare_copy(buf, min_t(size_t, bufsz, ns->msg_ctlmax),
+ msgflg, &msgtyp, &copy_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;
}