From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- ipc/msgutil.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 ipc/msgutil.c (limited to 'ipc/msgutil.c') diff --git a/ipc/msgutil.c b/ipc/msgutil.c new file mode 100644 index 000000000000..66cfb87646eb --- /dev/null +++ b/ipc/msgutil.c @@ -0,0 +1,127 @@ +/* + * linux/ipc/util.c + * Copyright (C) 1999, 2004 Manfred Spraul + * + * This file is released under GNU General Public Licence version 2 or + * (at your option) any later version. + * + * See the file COPYING for more details. + */ + +#include +#include +#include +#include +#include +#include + +#include "util.h" + +struct msg_msgseg { + struct msg_msgseg* next; + /* the next part of the message follows immediately */ +}; + +#define DATALEN_MSG (PAGE_SIZE-sizeof(struct msg_msg)) +#define DATALEN_SEG (PAGE_SIZE-sizeof(struct msg_msgseg)) + +struct msg_msg *load_msg(const void __user *src, int len) +{ + struct msg_msg *msg; + struct msg_msgseg **pseg; + int err; + int alen; + + alen = len; + if (alen > DATALEN_MSG) + alen = DATALEN_MSG; + + msg = (struct msg_msg *)kmalloc(sizeof(*msg) + alen, GFP_KERNEL); + if (msg == NULL) + return ERR_PTR(-ENOMEM); + + msg->next = NULL; + msg->security = NULL; + + if (copy_from_user(msg + 1, src, alen)) { + err = -EFAULT; + goto out_err; + } + + len -= alen; + src = ((char __user *)src) + alen; + pseg = &msg->next; + while (len > 0) { + struct msg_msgseg *seg; + alen = len; + if (alen > DATALEN_SEG) + alen = DATALEN_SEG; + seg = (struct msg_msgseg *)kmalloc(sizeof(*seg) + alen, + GFP_KERNEL); + if (seg == NULL) { + err = -ENOMEM; + goto out_err; + } + *pseg = seg; + seg->next = NULL; + if (copy_from_user(seg + 1, src, alen)) { + err = -EFAULT; + goto out_err; + } + pseg = &seg->next; + len -= alen; + src = ((char __user *)src) + alen; + } + + err = security_msg_msg_alloc(msg); + if (err) + goto out_err; + + return msg; + +out_err: + free_msg(msg); + return ERR_PTR(err); +} + +int store_msg(void __user *dest, struct msg_msg *msg, int len) +{ + int alen; + struct msg_msgseg *seg; + + alen = len; + if (alen > DATALEN_MSG) + alen = DATALEN_MSG; + if (copy_to_user(dest, msg + 1, alen)) + return -1; + + len -= alen; + dest = ((char __user *)dest) + alen; + seg = msg->next; + while (len > 0) { + alen = len; + if (alen > DATALEN_SEG) + alen = DATALEN_SEG; + if (copy_to_user(dest, seg + 1, alen)) + return -1; + len -= alen; + dest = ((char __user *)dest) + alen; + seg = seg->next; + } + return 0; +} + +void free_msg(struct msg_msg *msg) +{ + struct msg_msgseg *seg; + + security_msg_msg_free(msg); + + seg = msg->next; + kfree(msg); + while (seg != NULL) { + struct msg_msgseg *tmp = seg->next; + kfree(seg); + seg = tmp; + } +} -- cgit v1.2.3-59-g8ed1b