|
@@ -44,21 +44,54 @@ struct msg_msgseg {
|
|
|
#define DATALEN_MSG (int)(PAGE_SIZE-sizeof(struct msg_msg))
|
|
|
#define DATALEN_SEG (int)(PAGE_SIZE-sizeof(struct msg_msgseg))
|
|
|
|
|
|
-struct msg_msg *load_msg(const void __user *src, int len)
|
|
|
+
|
|
|
+static struct msg_msg *alloc_msg(int len)
|
|
|
{
|
|
|
struct msg_msg *msg;
|
|
|
struct msg_msgseg **pseg;
|
|
|
- int err;
|
|
|
int alen;
|
|
|
|
|
|
alen = min(len, DATALEN_MSG);
|
|
|
msg = kmalloc(sizeof(*msg) + alen, GFP_KERNEL);
|
|
|
if (msg == NULL)
|
|
|
- return ERR_PTR(-ENOMEM);
|
|
|
+ return NULL;
|
|
|
|
|
|
msg->next = NULL;
|
|
|
msg->security = NULL;
|
|
|
|
|
|
+ len -= alen;
|
|
|
+ pseg = &msg->next;
|
|
|
+ while (len > 0) {
|
|
|
+ struct msg_msgseg *seg;
|
|
|
+ alen = min(len, DATALEN_SEG);
|
|
|
+ seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL);
|
|
|
+ if (seg == NULL)
|
|
|
+ goto out_err;
|
|
|
+ *pseg = seg;
|
|
|
+ seg->next = NULL;
|
|
|
+ pseg = &seg->next;
|
|
|
+ len -= alen;
|
|
|
+ }
|
|
|
+
|
|
|
+ return msg;
|
|
|
+
|
|
|
+out_err:
|
|
|
+ free_msg(msg);
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+struct msg_msg *load_msg(const void __user *src, int len)
|
|
|
+{
|
|
|
+ struct msg_msg *msg;
|
|
|
+ struct msg_msgseg *seg;
|
|
|
+ int err;
|
|
|
+ int alen;
|
|
|
+
|
|
|
+ msg = alloc_msg(len);
|
|
|
+ if (msg == NULL)
|
|
|
+ return ERR_PTR(-ENOMEM);
|
|
|
+
|
|
|
+ alen = min(len, DATALEN_MSG);
|
|
|
if (copy_from_user(msg + 1, src, alen)) {
|
|
|
err = -EFAULT;
|
|
|
goto out_err;
|
|
@@ -66,23 +99,14 @@ struct msg_msg *load_msg(const void __user *src, int len)
|
|
|
|
|
|
len -= alen;
|
|
|
src = ((char __user *)src) + alen;
|
|
|
- pseg = &msg->next;
|
|
|
+ seg = msg->next;
|
|
|
while (len > 0) {
|
|
|
- struct msg_msgseg *seg;
|
|
|
alen = min(len, DATALEN_SEG);
|
|
|
- seg = 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;
|
|
|
+ seg = seg->next;
|
|
|
len -= alen;
|
|
|
src = ((char __user *)src) + alen;
|
|
|
}
|