Message ID | 20220504014440.3697851-2-keescook@chromium.org (mailing list archive) |
---|---|
State | Handled Elsewhere |
Headers | show |
Series | Introduce flexible array struct memcpy() helpers | expand |
This is automated email and please do not reply to this email! Dear submitter, Thank you for submitting the patches to the linux bluetooth mailing list. This is a CI test results with your patch series: PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=638153 ---Test result--- Test Summary: CheckPatch FAIL 15.45 seconds GitLint FAIL 7.70 seconds SubjectPrefix FAIL 28.23 seconds BuildKernel PASS 36.05 seconds BuildKernel32 PASS 34.02 seconds Incremental Build with patchesPASS 324.75 seconds TestRunner: Setup PASS 541.23 seconds TestRunner: l2cap-tester PASS 19.53 seconds TestRunner: bnep-tester PASS 7.22 seconds TestRunner: mgmt-tester PASS 110.30 seconds TestRunner: rfcomm-tester PASS 10.98 seconds TestRunner: sco-tester PASS 10.26 seconds TestRunner: smp-tester PASS 10.29 seconds TestRunner: userchan-tester PASS 7.09 seconds Details ############################## Test: CheckPatch - FAIL - 15.45 seconds Run checkpatch.pl script with rule in .checkpatch.conf [01/32] netlink: Avoid memcpy() across flexible array boundary\WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line) #172: memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16) WARNING:BAD_SIGN_OFF: Non-standard signature: Fixed-by: #179: Fixed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> total: 0 errors, 2 warnings, 0 checks, 18 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12836836.patch has style problems, please review. NOTE: Ignored message types: UNKNOWN_COMMIT_ID NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. [02/32] Introduce flexible array struct memcpy() helpers\Traceback (most recent call last): File "scripts/spdxcheck.py", line 6, in <module> from ply import lex, yacc ModuleNotFoundError: No module named 'ply' WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating? #300: new file mode 100644 ERROR:SPACING: need consistent spacing around '*' (ctx:WxV) #523: FILE: include/linux/flex_array.h:219: + typeof(*(src)) *__fc_src = (src); \ ^ ERROR:SPACING: need consistent spacing around '*' (ctx:WxV) #576: FILE: include/linux/flex_array.h:272: + typeof(**(alloc)) *__fd_alloc; \ ^ ERROR:SPACING: need consistent spacing around '*' (ctx:WxV) #754: FILE: include/linux/flex_array.h:450: + typeof((*__mtfd_alloc)dot_fas_member) *__mtfd_fas; \ ^ ERROR:SPACING: need consistent spacing around '*' (ctx:WxV) #861: FILE: include/linux/flex_array.h:557: + typeof(*(bytes_written)) *__ftm_written = (bytes_written); \ ^ ERROR:SPACING: need consistent spacing around '*' (ctx:WxV) #910: FILE: include/linux/flex_array.h:606: + typeof(*(alloc_size)) *__ftmd_alloc_size = (alloc_size); \ ^ total: 5 errors, 1 warnings, 662 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12836837.patch has style problems, please review. NOTE: Ignored message types: UNKNOWN_COMMIT_ID NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. [03/32] flex_array: Add Kunit tests\Traceback (most recent call last): File "scripts/spdxcheck.py", line 6, in <module> from ply import lex, yacc ModuleNotFoundError: No module named 'ply' WARNING:CONFIG_DESCRIPTION: please write a paragraph that describes the config symbol fully #205: FILE: lib/Kconfig.debug:2565: +config FLEX_ARRAY_KUNIT_TEST WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating? #228: new file mode 100644 total: 0 errors, 2 warnings, 554 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12836839.patch has style problems, please review. NOTE: Ignored message types: UNKNOWN_COMMIT_ID NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. [04/32] fortify: Add run-time WARN for cross-field memcpy()\WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line) #178: memcpy: detected field-spanning write (size N) of single field "var->dest" (size M) total: 0 errors, 1 warnings, 96 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12836838.patch has style problems, please review. NOTE: Ignored message types: UNKNOWN_COMMIT_ID NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. [07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result\WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line) #176: memcpy: detected field-spanning write (size 8) of single field "&res->hdr" (size 4) total: 0 errors, 1 warnings, 0 checks, 29 lines checked NOTE: For some of the reported defects, checkpatch may be able to mechanically convert to the typical style using --fix or --fix-inplace. /github/workspace/src/12836846.patch has style problems, please review. NOTE: Ignored message types: UNKNOWN_COMMIT_ID NOTE: If any of the errors are false positives, please report them to the maintainer, see CHECKPATCH in MAINTAINERS. ############################## Test: GitLint - FAIL - 7.70 seconds Run gitlint with rule in .gitlint [01/32] netlink: Avoid memcpy() across flexible array boundary 7: B1 Line exceeds max length (88>80): "memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16)" 15: B1 Line exceeds max length (90>80): "Link: https://lore.kernel.org/lkml/d7251d92-150b-5346-6237-52afc154bb00@rasmusvillemoes.dk" [02/32] Introduce flexible array struct memcpy() helpers 39: B3 Line contains hard tab characters (\t): " ... /* arbitrary members */" 40: B3 Line contains hard tab characters (\t): " u16 part_count; /* count of elements stored in "parts" below. */" 41: B3 Line contains hard tab characters (\t): " ... /* arbitrary members */" 42: B3 Line contains hard tab characters (\t): " u32 parts[]; /* flexible array with elements of type u32. */" 49: B3 Line contains hard tab characters (\t): " ... /* arbitrary members */" 57: B3 Line contains hard tab characters (\t): " ... /* arbitrary members */" 58: B3 Line contains hard tab characters (\t): " u16 part_count; /* count of elements stored in "parts" below. */" 59: B3 Line contains hard tab characters (\t): " ... /* arbitrary members */" 61: B3 Line contains hard tab characters (\t): " ... /* other blob members */" [04/32] fortify: Add run-time WARN for cross-field memcpy() 14: B1 Line exceeds max length (85>80): " memcpy: detected field-spanning write (size N) of single field "var->dest" (size M)" 38: B3 Line contains hard tab characters (\t): " void *a;" 39: B3 Line contains hard tab characters (\t): " int b;" 40: B3 Line contains hard tab characters (\t): " size_t array_size;" 41: B3 Line contains hard tab characters (\t): " u32 c;" 42: B3 Line contains hard tab characters (\t): " u8 flex_array[];" 60: B3 Line contains hard tab characters (\t): " int foo;" 61: B3 Line contains hard tab characters (\t): " char bar;" 62: B3 Line contains hard tab characters (\t): " struct normal_flex_array embedded;" [07/32] iwlwifi: calib: Use mem_to_flex_dup() with struct iwl_calib_result 11: B1 Line exceeds max length (83>80): "memcpy: detected field-spanning write (size 8) of single field "&res->hdr" (size 4)" ############################## Test: SubjectPrefix - FAIL - 28.23 seconds Check subject contains "Bluetooth" prefix "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject "Bluetooth: " is not specified in the subject --- Regards, Linux Bluetooth
On Tue, May 03, 2022 at 06:44:10PM -0700, Kees Cook wrote: > In preparation for run-time memcpy() bounds checking, split the nlmsg > copying for error messages (which crosses a previous unspecified flexible > array boundary) in half. Avoids the future run-time warning: > > memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16) > > Creates an explicit flexible array at the end of nlmsghdr for the payload, > named "nlmsg_payload". There is no impact on UAPI; the sizeof(struct > nlmsghdr) does not change, but now the compiler can better reason about > where things are being copied. > > Fixed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> > Link: https://lore.kernel.org/lkml/d7251d92-150b-5346-6237-52afc154bb00@rasmusvillemoes.dk > Cc: "David S. Miller" <davem@davemloft.net> > Cc: Jakub Kicinski <kuba@kernel.org> > Cc: Rich Felker <dalias@aerifal.cx> > Cc: Eric Dumazet <edumazet@google.com> > Cc: netdev@vger.kernel.org > Signed-off-by: Kees Cook <keescook@chromium.org> > --- > include/uapi/linux/netlink.h | 1 + > net/netlink/af_netlink.c | 5 ++++- > 2 files changed, 5 insertions(+), 1 deletion(-) > > diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h > index 855dffb4c1c3..47f9342d51bc 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_payload[];/* Contents of message */ > }; > > /* Flags values */ > diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c > index 1b5a9c2e1c29..09346aee1022 100644 > --- a/net/netlink/af_netlink.c > +++ b/net/netlink/af_netlink.c > @@ -2445,7 +2445,10 @@ 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)); > + errmsg->msg = *nlh; > + if (payload > sizeof(*errmsg)) > + memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, > + nlh->nlmsg_len - sizeof(*nlh)); They have nlmsg_len()[1] for the length of the payload without the header: /** * nlmsg_len - length of message payload * @nlh: netlink message header */ static inline int nlmsg_len(const struct nlmsghdr *nlh) { return nlh->nlmsg_len - NLMSG_HDRLEN; } (would that function use some sanitization, though? what if nlmsg_len is somehow manipulated to be less than NLMSG_HDRLEN?...) Also, it seems there is at least one more instance of this same issue: diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 16ae92054baa..d06184b94af5 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -1723,7 +1723,8 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb, nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); errmsg = nlmsg_data(rep); errmsg->error = ret; - memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); + errmsg->msg = *nlh; + memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, nlmsg_len(nlh)); cmdattr = (void *)&errmsg->msg + min_len; ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr, -- Gustavo [1] https://elixir.bootlin.com/linux/v5.18-rc5/source/include/net/netlink.h#L577
On Tue, May 03, 2022 at 10:31:05PM -0500, Gustavo A. R. Silva wrote: > On Tue, May 03, 2022 at 06:44:10PM -0700, Kees Cook wrote: > [...] > > diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c > > index 1b5a9c2e1c29..09346aee1022 100644 > > --- a/net/netlink/af_netlink.c > > +++ b/net/netlink/af_netlink.c > > @@ -2445,7 +2445,10 @@ 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)); > > + errmsg->msg = *nlh; > > + if (payload > sizeof(*errmsg)) > > + memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, > > + nlh->nlmsg_len - sizeof(*nlh)); > > They have nlmsg_len()[1] for the length of the payload without the header: > > /** > * nlmsg_len - length of message payload > * @nlh: netlink message header > */ > static inline int nlmsg_len(const struct nlmsghdr *nlh) > { > return nlh->nlmsg_len - NLMSG_HDRLEN; > } Oh, hm, yeah, that would be much cleaner. The relationship between "payload" and nlmsg_len is confusing in here. :) So, this should be simpler: - memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh)); + errmsg->msg = *nlh; + memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, nlmsg_len(nlh)); It's actually this case that triggered my investigation in __bos(1)'s misbehavior around sub-structs, since this case wasn't getting silenced: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101832 It still feels like it should be possible to get this right without splitting the memcpy, though. Hmpf. > (would that function use some sanitization, though? what if nlmsg_len is > somehow manipulated to be less than NLMSG_HDRLEN?...) Maybe something like: static inline int nlmsg_len(const struct nlmsghdr *nlh) { if (WARN_ON(nlh->nlmsg_len < NLMSG_HDRLEN)) return 0; return nlh->nlmsg_len - NLMSG_HDRLEN; } > Also, it seems there is at least one more instance of this same issue: > > diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c > index 16ae92054baa..d06184b94af5 100644 > --- a/net/netfilter/ipset/ip_set_core.c > +++ b/net/netfilter/ipset/ip_set_core.c > @@ -1723,7 +1723,8 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb, > nlh->nlmsg_seq, NLMSG_ERROR, payload, 0); > errmsg = nlmsg_data(rep); > errmsg->error = ret; > - memcpy(&errmsg->msg, nlh, nlh->nlmsg_len); > + errmsg->msg = *nlh; > + memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, nlmsg_len(nlh)); Ah, yes, nice catch! > cmdattr = (void *)&errmsg->msg + min_len; > > ret = nla_parse(cda, IPSET_ATTR_CMD_MAX, cmdattr, > > -- > Gustavo > > [1] https://elixir.bootlin.com/linux/v5.18-rc5/source/include/net/netlink.h#L577
diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h index 855dffb4c1c3..47f9342d51bc 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_payload[];/* Contents of message */ }; /* Flags values */ diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 1b5a9c2e1c29..09346aee1022 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -2445,7 +2445,10 @@ 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)); + errmsg->msg = *nlh; + if (payload > sizeof(*errmsg)) + memcpy(errmsg->msg.nlmsg_payload, nlh->nlmsg_payload, + nlh->nlmsg_len - sizeof(*nlh)); if (nlk_has_extack && extack) { if (extack->_msg) {
In preparation for run-time memcpy() bounds checking, split the nlmsg copying for error messages (which crosses a previous unspecified flexible array boundary) in half. Avoids the future run-time warning: memcpy: detected field-spanning write (size 32) of single field "&errmsg->msg" (size 16) Creates an explicit flexible array at the end of nlmsghdr for the payload, named "nlmsg_payload". There is no impact on UAPI; the sizeof(struct nlmsghdr) does not change, but now the compiler can better reason about where things are being copied. Fixed-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Link: https://lore.kernel.org/lkml/d7251d92-150b-5346-6237-52afc154bb00@rasmusvillemoes.dk Cc: "David S. Miller" <davem@davemloft.net> Cc: Jakub Kicinski <kuba@kernel.org> Cc: Rich Felker <dalias@aerifal.cx> Cc: Eric Dumazet <edumazet@google.com> Cc: netdev@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org> --- include/uapi/linux/netlink.h | 1 + net/netlink/af_netlink.c | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-)