Linux Audio

Check our new training course

Loading...
v4.6
  1/*
  2 * linux/ipc/msgutil.c
  3 * Copyright (C) 1999, 2004 Manfred Spraul
  4 *
  5 * This file is released under GNU General Public Licence version 2 or
  6 * (at your option) any later version.
  7 *
  8 * See the file COPYING for more details.
  9 */
 10
 11#include <linux/spinlock.h>
 12#include <linux/init.h>
 13#include <linux/security.h>
 14#include <linux/slab.h>
 15#include <linux/ipc.h>
 16#include <linux/msg.h>
 17#include <linux/ipc_namespace.h>
 18#include <linux/utsname.h>
 19#include <linux/proc_ns.h>
 20#include <linux/uaccess.h>
 21
 22#include "util.h"
 23
 24DEFINE_SPINLOCK(mq_lock);
 25
 26/*
 27 * The next 2 defines are here bc this is the only file
 28 * compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
 29 * and not CONFIG_IPC_NS.
 30 */
 31struct ipc_namespace init_ipc_ns = {
 32	.count		= ATOMIC_INIT(1),
 33	.user_ns = &init_user_ns,
 34	.ns.inum = PROC_IPC_INIT_INO,
 35#ifdef CONFIG_IPC_NS
 36	.ns.ops = &ipcns_operations,
 37#endif
 38};
 39
 40atomic_t nr_ipc_ns = ATOMIC_INIT(1);
 41
 42struct msg_msgseg {
 43	struct msg_msgseg *next;
 44	/* the next part of the message follows immediately */
 45};
 46
 47#define DATALEN_MSG	((size_t)PAGE_SIZE-sizeof(struct msg_msg))
 48#define DATALEN_SEG	((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
 49
 50
 51static struct msg_msg *alloc_msg(size_t len)
 52{
 53	struct msg_msg *msg;
 54	struct msg_msgseg **pseg;
 55	size_t alen;
 56
 57	alen = min(len, DATALEN_MSG);
 58	msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
 59	if (msg == NULL)
 60		return NULL;
 61
 62	msg->next = NULL;
 63	msg->security = NULL;
 64
 65	len -= alen;
 66	pseg = &msg->next;
 67	while (len > 0) {
 68		struct msg_msgseg *seg;
 69		alen = min(len, DATALEN_SEG);
 70		seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL);
 71		if (seg == NULL)
 72			goto out_err;
 73		*pseg = seg;
 74		seg->next = NULL;
 75		pseg = &seg->next;
 76		len -= alen;
 77	}
 78
 79	return msg;
 80
 81out_err:
 82	free_msg(msg);
 83	return NULL;
 84}
 85
 86struct msg_msg *load_msg(const void __user *src, size_t len)
 87{
 88	struct msg_msg *msg;
 89	struct msg_msgseg *seg;
 90	int err = -EFAULT;
 91	size_t alen;
 92
 93	msg = alloc_msg(len);
 94	if (msg == NULL)
 95		return ERR_PTR(-ENOMEM);
 96
 97	alen = min(len, DATALEN_MSG);
 98	if (copy_from_user(msg + 1, src, alen))
 99		goto out_err;
100
101	for (seg = msg->next; seg != NULL; seg = seg->next) {
102		len -= alen;
103		src = (char __user *)src + alen;
104		alen = min(len, DATALEN_SEG);
105		if (copy_from_user(seg + 1, src, alen))
106			goto out_err;
107	}
108
109	err = security_msg_msg_alloc(msg);
110	if (err)
111		goto out_err;
112
113	return msg;
114
115out_err:
116	free_msg(msg);
117	return ERR_PTR(err);
118}
119#ifdef CONFIG_CHECKPOINT_RESTORE
120struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
121{
122	struct msg_msgseg *dst_pseg, *src_pseg;
123	size_t len = src->m_ts;
124	size_t alen;
125
126	if (src->m_ts > dst->m_ts)
127		return ERR_PTR(-EINVAL);
128
129	alen = min(len, DATALEN_MSG);
130	memcpy(dst + 1, src + 1, alen);
131
132	for (dst_pseg = dst->next, src_pseg = src->next;
133	     src_pseg != NULL;
134	     dst_pseg = dst_pseg->next, src_pseg = src_pseg->next) {
135
136		len -= alen;
137		alen = min(len, DATALEN_SEG);
138		memcpy(dst_pseg + 1, src_pseg + 1, alen);
139	}
140
141	dst->m_type = src->m_type;
142	dst->m_ts = src->m_ts;
143
144	return dst;
145}
146#else
147struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
148{
149	return ERR_PTR(-ENOSYS);
150}
151#endif
152int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
153{
154	size_t alen;
155	struct msg_msgseg *seg;
156
157	alen = min(len, DATALEN_MSG);
158	if (copy_to_user(dest, msg + 1, alen))
159		return -1;
160
161	for (seg = msg->next; seg != NULL; seg = seg->next) {
162		len -= alen;
163		dest = (char __user *)dest + alen;
164		alen = min(len, DATALEN_SEG);
165		if (copy_to_user(dest, seg + 1, alen))
166			return -1;
167	}
168	return 0;
169}
170
171void free_msg(struct msg_msg *msg)
172{
173	struct msg_msgseg *seg;
174
175	security_msg_msg_free(msg);
176
177	seg = msg->next;
178	kfree(msg);
179	while (seg != NULL) {
180		struct msg_msgseg *tmp = seg->next;
181		kfree(seg);
182		seg = tmp;
183	}
184}
v4.17
  1/*
  2 * linux/ipc/msgutil.c
  3 * Copyright (C) 1999, 2004 Manfred Spraul
  4 *
  5 * This file is released under GNU General Public Licence version 2 or
  6 * (at your option) any later version.
  7 *
  8 * See the file COPYING for more details.
  9 */
 10
 11#include <linux/spinlock.h>
 12#include <linux/init.h>
 13#include <linux/security.h>
 14#include <linux/slab.h>
 15#include <linux/ipc.h>
 16#include <linux/msg.h>
 17#include <linux/ipc_namespace.h>
 18#include <linux/utsname.h>
 19#include <linux/proc_ns.h>
 20#include <linux/uaccess.h>
 21
 22#include "util.h"
 23
 24DEFINE_SPINLOCK(mq_lock);
 25
 26/*
 27 * The next 2 defines are here bc this is the only file
 28 * compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
 29 * and not CONFIG_IPC_NS.
 30 */
 31struct ipc_namespace init_ipc_ns = {
 32	.count		= REFCOUNT_INIT(1),
 33	.user_ns = &init_user_ns,
 34	.ns.inum = PROC_IPC_INIT_INO,
 35#ifdef CONFIG_IPC_NS
 36	.ns.ops = &ipcns_operations,
 37#endif
 38};
 39
 
 
 40struct msg_msgseg {
 41	struct msg_msgseg *next;
 42	/* the next part of the message follows immediately */
 43};
 44
 45#define DATALEN_MSG	((size_t)PAGE_SIZE-sizeof(struct msg_msg))
 46#define DATALEN_SEG	((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
 47
 48
 49static struct msg_msg *alloc_msg(size_t len)
 50{
 51	struct msg_msg *msg;
 52	struct msg_msgseg **pseg;
 53	size_t alen;
 54
 55	alen = min(len, DATALEN_MSG);
 56	msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL_ACCOUNT);
 57	if (msg == NULL)
 58		return NULL;
 59
 60	msg->next = NULL;
 61	msg->security = NULL;
 62
 63	len -= alen;
 64	pseg = &msg->next;
 65	while (len > 0) {
 66		struct msg_msgseg *seg;
 67		alen = min(len, DATALEN_SEG);
 68		seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT);
 69		if (seg == NULL)
 70			goto out_err;
 71		*pseg = seg;
 72		seg->next = NULL;
 73		pseg = &seg->next;
 74		len -= alen;
 75	}
 76
 77	return msg;
 78
 79out_err:
 80	free_msg(msg);
 81	return NULL;
 82}
 83
 84struct msg_msg *load_msg(const void __user *src, size_t len)
 85{
 86	struct msg_msg *msg;
 87	struct msg_msgseg *seg;
 88	int err = -EFAULT;
 89	size_t alen;
 90
 91	msg = alloc_msg(len);
 92	if (msg == NULL)
 93		return ERR_PTR(-ENOMEM);
 94
 95	alen = min(len, DATALEN_MSG);
 96	if (copy_from_user(msg + 1, src, alen))
 97		goto out_err;
 98
 99	for (seg = msg->next; seg != NULL; seg = seg->next) {
100		len -= alen;
101		src = (char __user *)src + alen;
102		alen = min(len, DATALEN_SEG);
103		if (copy_from_user(seg + 1, src, alen))
104			goto out_err;
105	}
106
107	err = security_msg_msg_alloc(msg);
108	if (err)
109		goto out_err;
110
111	return msg;
112
113out_err:
114	free_msg(msg);
115	return ERR_PTR(err);
116}
117#ifdef CONFIG_CHECKPOINT_RESTORE
118struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
119{
120	struct msg_msgseg *dst_pseg, *src_pseg;
121	size_t len = src->m_ts;
122	size_t alen;
123
124	if (src->m_ts > dst->m_ts)
125		return ERR_PTR(-EINVAL);
126
127	alen = min(len, DATALEN_MSG);
128	memcpy(dst + 1, src + 1, alen);
129
130	for (dst_pseg = dst->next, src_pseg = src->next;
131	     src_pseg != NULL;
132	     dst_pseg = dst_pseg->next, src_pseg = src_pseg->next) {
133
134		len -= alen;
135		alen = min(len, DATALEN_SEG);
136		memcpy(dst_pseg + 1, src_pseg + 1, alen);
137	}
138
139	dst->m_type = src->m_type;
140	dst->m_ts = src->m_ts;
141
142	return dst;
143}
144#else
145struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
146{
147	return ERR_PTR(-ENOSYS);
148}
149#endif
150int store_msg(void __user *dest, struct msg_msg *msg, size_t len)
151{
152	size_t alen;
153	struct msg_msgseg *seg;
154
155	alen = min(len, DATALEN_MSG);
156	if (copy_to_user(dest, msg + 1, alen))
157		return -1;
158
159	for (seg = msg->next; seg != NULL; seg = seg->next) {
160		len -= alen;
161		dest = (char __user *)dest + alen;
162		alen = min(len, DATALEN_SEG);
163		if (copy_to_user(dest, seg + 1, alen))
164			return -1;
165	}
166	return 0;
167}
168
169void free_msg(struct msg_msg *msg)
170{
171	struct msg_msgseg *seg;
172
173	security_msg_msg_free(msg);
174
175	seg = msg->next;
176	kfree(msg);
177	while (seg != NULL) {
178		struct msg_msgseg *tmp = seg->next;
179		kfree(seg);
180		seg = tmp;
181	}
182}