diff options
author | Mark Brown <broonie@kernel.org> | 2021-05-18 17:24:52 +0100 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2021-05-18 17:24:52 +0100 |
commit | c37fe6aff89cb0d842993fe2f69e48bf3ebe0ab0 (patch) | |
tree | 2a322c48218f7006bab789b7bf16ec58b129a096 /net/core/scm.c | |
parent | d7aed20d446d8c87f5e13adf73281056b0064a45 (diff) | |
parent | d07f6ca923ea0927a1024dfccafc5b53b61cfecc (diff) |
Merge tag 'v5.13-rc2' into spi-5.13
Linux 5.13-rc2
Diffstat (limited to 'net/core/scm.c')
-rw-r--r-- | net/core/scm.c | 23 |
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); |