summaryrefslogtreecommitdiff
path: root/net/core/scm.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/scm.c')
-rw-r--r--net/core/scm.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/net/core/scm.c b/net/core/scm.c
index 8156d4fb8a39..ae3085d9aae8 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -228,14 +228,16 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
if (msg->msg_control_is_user) {
struct cmsghdr __user *cm = msg->msg_control_user;
- struct cmsghdr cmhdr;
-
- cmhdr.cmsg_level = level;
- cmhdr.cmsg_type = type;
- cmhdr.cmsg_len = cmlen;
- if (copy_to_user(cm, &cmhdr, sizeof cmhdr) ||
- copy_to_user(CMSG_USER_DATA(cm), data, cmlen - sizeof(*cm)))
- return -EFAULT;
+
+ if (!user_write_access_begin(cm, cmlen))
+ goto efault;
+
+ unsafe_put_user(cmlen, &cm->cmsg_len, efault_end);
+ unsafe_put_user(level, &cm->cmsg_level, efault_end);
+ unsafe_put_user(type, &cm->cmsg_type, efault_end);
+ unsafe_copy_to_user(CMSG_USER_DATA(cm), data,
+ cmlen - sizeof(*cm), efault_end);
+ user_write_access_end();
} else {
struct cmsghdr *cm = msg->msg_control;
@@ -249,6 +251,11 @@ int put_cmsg(struct msghdr * msg, int level, int type, int len, void *data)
msg->msg_control += cmlen;
msg->msg_controllen -= cmlen;
return 0;
+
+efault_end:
+ user_write_access_end();
+efault:
+ return -EFAULT;
}
EXPORT_SYMBOL(put_cmsg);