Linux Audio

Check our new training course

Loading...
v3.5.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 <asm/uaccess.h>
 
 20
 21#include "util.h"
 22
 23DEFINE_SPINLOCK(mq_lock);
 24
 25/*
 26 * The next 2 defines are here bc this is the only file
 27 * compiled when either CONFIG_SYSVIPC and CONFIG_POSIX_MQUEUE
 28 * and not CONFIG_IPC_NS.
 29 */
 30struct ipc_namespace init_ipc_ns = {
 31	.count		= ATOMIC_INIT(1),
 32	.user_ns = &init_user_ns,
 
 33};
 34
 35atomic_t nr_ipc_ns = ATOMIC_INIT(1);
 36
 37struct msg_msgseg {
 38	struct msg_msgseg* next;
 39	/* the next part of the message follows immediately */
 40};
 41
 42#define DATALEN_MSG	(PAGE_SIZE-sizeof(struct msg_msg))
 43#define DATALEN_SEG	(PAGE_SIZE-sizeof(struct msg_msgseg))
 44
 45struct msg_msg *load_msg(const void __user *src, int len)
 
 46{
 47	struct msg_msg *msg;
 48	struct msg_msgseg **pseg;
 49	int err;
 50	int alen;
 51
 52	alen = len;
 53	if (alen > DATALEN_MSG)
 54		alen = DATALEN_MSG;
 55
 
 56	msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
 57	if (msg == NULL)
 58		return ERR_PTR(-ENOMEM);
 59
 60	msg->next = NULL;
 61	msg->security = NULL;
 62
 63	if (copy_from_user(msg + 1, src, alen)) {
 64		err = -EFAULT;
 65		goto out_err;
 66	}
 67
 68	len -= alen;
 69	src = ((char __user *)src) + alen;
 70	pseg = &msg->next;
 71	while (len > 0) {
 72		struct msg_msgseg *seg;
 73		alen = len;
 74		if (alen > DATALEN_SEG)
 75			alen = DATALEN_SEG;
 76		seg = kmalloc(sizeof(*seg) + alen,
 77						 GFP_KERNEL);
 78		if (seg == NULL) {
 79			err = -ENOMEM;
 80			goto out_err;
 81		}
 82		*pseg = seg;
 83		seg->next = NULL;
 84		if (copy_from_user(seg + 1, src, alen)) {
 85			err = -EFAULT;
 86			goto out_err;
 87		}
 88		pseg = &seg->next;
 89		len -= alen;
 90		src = ((char __user *)src) + alen;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 91	}
 92
 93	err = security_msg_msg_alloc(msg);
 94	if (err)
 95		goto out_err;
 96
 97	return msg;
 98
 99out_err:
100	free_msg(msg);
101	return ERR_PTR(err);
102}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
104int store_msg(void __user *dest, struct msg_msg *msg, int len)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105{
106	int alen;
107	struct msg_msgseg *seg;
108
109	alen = len;
110	if (alen > DATALEN_MSG)
111		alen = DATALEN_MSG;
112	if (copy_to_user(dest, msg + 1, alen))
113		return -1;
114
115	len -= alen;
116	dest = ((char __user *)dest) + alen;
117	seg = msg->next;
118	while (len > 0) {
119		alen = len;
120		if (alen > DATALEN_SEG)
121			alen = DATALEN_SEG;
122		if (copy_to_user(dest, seg + 1, alen))
123			return -1;
124		len -= alen;
125		dest = ((char __user *)dest) + alen;
126		seg = seg->next;
127	}
128	return 0;
129}
130
131void free_msg(struct msg_msg *msg)
132{
133	struct msg_msgseg *seg;
134
135	security_msg_msg_free(msg);
136
137	seg = msg->next;
138	kfree(msg);
139	while (seg != NULL) {
140		struct msg_msgseg *tmp = seg->next;
141		kfree(seg);
142		seg = tmp;
143	}
144}
v3.15
  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	.proc_inum = PROC_IPC_INIT_INO,
 35};
 36
 37atomic_t nr_ipc_ns = ATOMIC_INIT(1);
 38
 39struct msg_msgseg {
 40	struct msg_msgseg *next;
 41	/* the next part of the message follows immediately */
 42};
 43
 44#define DATALEN_MSG	((size_t)PAGE_SIZE-sizeof(struct msg_msg))
 45#define DATALEN_SEG	((size_t)PAGE_SIZE-sizeof(struct msg_msgseg))
 46
 47
 48static struct msg_msg *alloc_msg(size_t len)
 49{
 50	struct msg_msg *msg;
 51	struct msg_msgseg **pseg;
 52	size_t alen;
 
 
 
 
 
 53
 54	alen = min(len, DATALEN_MSG);
 55	msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
 56	if (msg == NULL)
 57		return NULL;
 58
 59	msg->next = NULL;
 60	msg->security = NULL;
 61
 
 
 
 
 
 62	len -= alen;
 
 63	pseg = &msg->next;
 64	while (len > 0) {
 65		struct msg_msgseg *seg;
 66		alen = min(len, DATALEN_SEG);
 67		seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL);
 68		if (seg == NULL)
 
 
 
 
 69			goto out_err;
 
 70		*pseg = seg;
 71		seg->next = NULL;
 
 
 
 
 72		pseg = &seg->next;
 73		len -= alen;
 74	}
 75
 76	return msg;
 77
 78out_err:
 79	free_msg(msg);
 80	return NULL;
 81}
 82
 83struct msg_msg *load_msg(const void __user *src, size_t len)
 84{
 85	struct msg_msg *msg;
 86	struct msg_msgseg *seg;
 87	int err = -EFAULT;
 88	size_t alen;
 89
 90	msg = alloc_msg(len);
 91	if (msg == NULL)
 92		return ERR_PTR(-ENOMEM);
 93
 94	alen = min(len, DATALEN_MSG);
 95	if (copy_from_user(msg + 1, src, alen))
 96		goto out_err;
 97
 98	for (seg = msg->next; seg != NULL; seg = seg->next) {
 99		len -= alen;
100		src = (char __user *)src + alen;
101		alen = min(len, DATALEN_SEG);
102		if (copy_from_user(seg + 1, src, alen))
103			goto out_err;
104	}
105
106	err = security_msg_msg_alloc(msg);
107	if (err)
108		goto out_err;
109
110	return msg;
111
112out_err:
113	free_msg(msg);
114	return ERR_PTR(err);
115}
116#ifdef CONFIG_CHECKPOINT_RESTORE
117struct msg_msg *copy_msg(struct msg_msg *src, struct msg_msg *dst)
118{
119	struct msg_msgseg *dst_pseg, *src_pseg;
120	size_t len = src->m_ts;
121	size_t alen;
122
123	BUG_ON(dst == NULL);
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}