aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2021-06-19 02:14:18 -0700
committerKees Cook <keescook@chromium.org>2021-08-11 08:48:51 -0700
commit0faff4e74f49485683ea9757f2e49fdab41c7f20 (patch)
tree91886422cc2e5e70c364974cd8350ca118b06f48
parent17ef8a79b6633b2d52bd136f9a4563e9233684bb (diff)
downloadlinux-0faff4e74f49485683ea9757f2e49fdab41c7f20.tar.gz
netlink: Use flex_cpy() to avoid false-positive memcpy() warning
In preparation for FORTIFY_SOURCE performing compile-time and run-time field bounds checking for memcpy(), memmove(), and memset(), avoid intentionally writing across neighboring fields. Use the flex_cpy() helper with explicit bounds checking to avoid the future run-time warning: memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16) Cc: "David S. Miller" <davem@davemloft.net> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Rich Felker <dalias@aerifal.cx> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Petr Vorel <petr.vorel@gmail.com> Cc: Chen Li <chenli@uniontech.com> Cc: Johannes Berg <johannes.berg@intel.com> Cc: Alexei Starovoitov <ast@kernel.org> Cc: Florian Westphal <fw@strlen.de> Cc: Yonghong Song <yhs@fb.com> Cc: Dmitry Safonov <0x7f454c46@gmail.com> Cc: netdev@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org> Fixed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Link: https://lore.kernel.org/lkml/d7251d92-150b-5346-6237-52afc154bb00@rasmusvillemoes.dk
-rw-r--r--include/uapi/linux/netlink.h1
-rw-r--r--net/netlink/af_netlink.c6
2 files changed, 5 insertions, 2 deletions
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
index 4c0cde075c277..2ccaa2f0dc837 100644
--- a/include/uapi/linux/netlink.h
+++ b/include/uapi/linux/netlink.h
@@ -47,6 +47,7 @@ struct nlmsghdr {
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
__u32 nlmsg_pid; /* Sending process port ID */
+ __u8 nlmsg_content[];/* Content following header */
};
/* Flags values */
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 24b7cf447bc55..9616dc5b49bee 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2410,6 +2410,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
struct nlmsghdr *rep;
struct nlmsgerr *errmsg;
size_t payload = sizeof(*errmsg);
+ size_t errlen = 0;
size_t tlvlen = 0;
struct netlink_sock *nlk = nlk_sk(NETLINK_CB(in_skb).sk);
unsigned int flags = 0;
@@ -2423,7 +2424,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
tlvlen += nla_total_size(strlen(extack->_msg) + 1);
if (err && !(nlk->flags & NETLINK_F_CAP_ACK))
- payload += nlmsg_len(nlh);
+ errlen = nlmsg_len(nlh);
else
flags |= NLM_F_CAPPED;
if (err && nlk_has_extack && extack && extack->bad_attr)
@@ -2436,6 +2437,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
if (tlvlen)
flags |= NLM_F_ACK_TLVS;
+ payload += errlen;
skb = nlmsg_new(payload + tlvlen, GFP_KERNEL);
if (!skb) {
NETLINK_CB(in_skb).sk->sk_err = ENOBUFS;
@@ -2447,7 +2449,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
NLMSG_ERROR, payload, flags);
errmsg = nlmsg_data(rep);
errmsg->error = err;
- memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
+ flex_cpy(&errmsg->msg, errlen, nlh, errlen, nlmsg_content);
if (nlk_has_extack && extack) {
if (extack->_msg) {