diff options
| author | Kees Cook <keescook@chromium.org> | 2021-06-19 02:14:18 -0700 |
|---|---|---|
| committer | Kees Cook <keescook@chromium.org> | 2021-08-11 08:48:51 -0700 |
| commit | 0faff4e74f49485683ea9757f2e49fdab41c7f20 (patch) | |
| tree | 91886422cc2e5e70c364974cd8350ca118b06f48 | |
| parent | 17ef8a79b6633b2d52bd136f9a4563e9233684bb (diff) | |
| download | linux-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.h | 1 | ||||
| -rw-r--r-- | net/netlink/af_netlink.c | 6 |
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) { |
