Message ID | 20230811-strncpy-arch-arm64-v2-1-ba84eabffadb@google.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [v2] arm64/sysreg: refactor deprecated strncpy | expand |
On Fri, 11 Aug 2023 16:33:51 +0000, Justin Stitt wrote: > `strncpy` is deprecated for use on NUL-terminated destination strings > [1]. Which seems to be the case here due to the forceful setting of `buf`'s > tail to 0. > > A suitable replacement is `strscpy` [2] due to the fact that it > guarantees NUL-termination on its destination buffer argument which is > _not_ the case for `strncpy`! > > [...] Applied to arm64 (for-next/misc), thanks! [1/1] arm64/sysreg: refactor deprecated strncpy https://git.kernel.org/arm64/c/d232606773a0 Cheers,
On Fri, Aug 11, 2023 at 04:33:51PM +0000, Justin Stitt wrote: > `strncpy` is deprecated for use on NUL-terminated destination strings > [1]. Which seems to be the case here due to the forceful setting of `buf`'s > tail to 0. > > A suitable replacement is `strscpy` [2] due to the fact that it > guarantees NUL-termination on its destination buffer argument which is > _not_ the case for `strncpy`! > > In this case, we can simplify the logic and also check for any silent > truncation by using `strscpy`'s return value. > > This should have no functional change and yet uses a more robust and > less ambiguous interface whilst reducing code complexity. > I'm sorry, but this patch is wrong. __parse_cmdline() is supposed to match the command line against a set of keywords, one word at a time. The new implementation ignores the word-boundaries and matches the whole command line once and then breaks the loop, typically without having found a match. (See below) Can we please have this patch dropped, Will? Also, the commit message is a blanket statement about why strscpy is better than stncpy, but I don't see how this is applicable to the code it attempts to "fix". Afaict the code already handled these cases. > Link: www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings[1] > Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] > Link: https://github.com/KSPP/linux/issues/90 > Suggested-by: Kees Cook <keescook@chromium.org> > Cc: linux-hardening@vger.kernel.org > Signed-off-by: Justin Stitt <justinstitt@google.com> > --- > Changes in v2: > - Utilize return value from strscpy and check for truncation (thanks Kees) > - Link to v1: https://lore.kernel.org/r/20230810-strncpy-arch-arm64-v1-1-f67f3685cd64@google.com > --- > For reference, see a part of `strscpy`'s implementation here: > > | /* Hit buffer length without finding a NUL; force NUL-termination. */ > | if (res) > | dest[res-1] = '\0'; > > Note: compile tested > --- > arch/arm64/kernel/idreg-override.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c > index 2fe2491b692c..aee12c75b738 100644 > --- a/arch/arm64/kernel/idreg-override.c > +++ b/arch/arm64/kernel/idreg-override.c > @@ -262,9 +262,9 @@ static __init void __parse_cmdline(const char *cmdline, bool parse_aliases) > if (!len) > return; > > - len = min(len, ARRAY_SIZE(buf) - 1); Here "len" was either the number of bytes to the first space, the end of the string, or the last byte in "buf". > - strncpy(buf, cmdline, len); So this will copy one word, or the rest of the string. > - buf[len] = 0; And it will NUL-terminate the word, which is then matched upon below. > + len = strscpy(buf, cmdline, ARRAY_SIZE(buf)); In this new implementation, the code copies the rest of the command line to "buf", makes an attempt to match with with the keywords, and then breaks the loop (as cmdline + len is the end of the string). Regards, Bjorn
On Thu, Sep 7, 2023 at 2:23 PM Bjorn Andersson <andersson@kernel.org> wrote: > > On Fri, Aug 11, 2023 at 04:33:51PM +0000, Justin Stitt wrote: > > `strncpy` is deprecated for use on NUL-terminated destination strings > > [1]. Which seems to be the case here due to the forceful setting of `buf`'s > > tail to 0. > > > > A suitable replacement is `strscpy` [2] due to the fact that it > > guarantees NUL-termination on its destination buffer argument which is > > _not_ the case for `strncpy`! > > > > In this case, we can simplify the logic and also check for any silent > > truncation by using `strscpy`'s return value. > > > > This should have no functional change and yet uses a more robust and > > less ambiguous interface whilst reducing code complexity. > > > > I'm sorry, but this patch is wrong. > > __parse_cmdline() is supposed to match the command line against a set of > keywords, one word at a time. The new implementation ignores the > word-boundaries and matches the whole command line once and then breaks > the loop, typically without having found a match. (See below) > > Can we please have this patch dropped, Will? It has been, I believe. At any rate, a v4 is up [1] which prefers memcpy over strncpy. > > > > Also, the commit message is a blanket statement about why strscpy is > better than stncpy, but I don't see how this is applicable to the code > it attempts to "fix". Afaict the code already handled these cases. > > > Link: www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings[1] > > Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] > > Link: https://github.com/KSPP/linux/issues/90 > > Suggested-by: Kees Cook <keescook@chromium.org> > > Cc: linux-hardening@vger.kernel.org > > Signed-off-by: Justin Stitt <justinstitt@google.com> > > --- > > Changes in v2: > > - Utilize return value from strscpy and check for truncation (thanks Kees) > > - Link to v1: https://lore.kernel.org/r/20230810-strncpy-arch-arm64-v1-1-f67f3685cd64@google.com > > --- > > For reference, see a part of `strscpy`'s implementation here: > > > > | /* Hit buffer length without finding a NUL; force NUL-termination. */ > > | if (res) > > | dest[res-1] = '\0'; > > > > Note: compile tested > > --- > > arch/arm64/kernel/idreg-override.c | 6 +++--- > > 1 file changed, 3 insertions(+), 3 deletions(-) > > > > diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c > > index 2fe2491b692c..aee12c75b738 100644 > > --- a/arch/arm64/kernel/idreg-override.c > > +++ b/arch/arm64/kernel/idreg-override.c > > @@ -262,9 +262,9 @@ static __init void __parse_cmdline(const char *cmdline, bool parse_aliases) > > if (!len) > > return; > > > > - len = min(len, ARRAY_SIZE(buf) - 1); > > Here "len" was either the number of bytes to the first space, the end of > the string, or the last byte in "buf". > > > - strncpy(buf, cmdline, len); > > So this will copy one word, or the rest of the string. > > > - buf[len] = 0; > > And it will NUL-terminate the word, which is then matched upon below. > > > + len = strscpy(buf, cmdline, ARRAY_SIZE(buf)); > > In this new implementation, the code copies the rest of the command line > to "buf", makes an attempt to match with with the keywords, and then > breaks the loop (as cmdline + len is the end of the string). > > Regards, > Bjorn [1]: https://lore.kernel.org/all/20230905-strncpy-arch-arm64-v4-1-bc4b14ddfaef@google.com/
On Thu, Sep 07, 2023 at 02:28:05PM -0700, Bjorn Andersson wrote: > On Fri, Aug 11, 2023 at 04:33:51PM +0000, Justin Stitt wrote: > > `strncpy` is deprecated for use on NUL-terminated destination strings > > [1]. Which seems to be the case here due to the forceful setting of `buf`'s > > tail to 0. > > > > A suitable replacement is `strscpy` [2] due to the fact that it > > guarantees NUL-termination on its destination buffer argument which is > > _not_ the case for `strncpy`! > > > > In this case, we can simplify the logic and also check for any silent > > truncation by using `strscpy`'s return value. > > > > This should have no functional change and yet uses a more robust and > > less ambiguous interface whilst reducing code complexity. > > > > I'm sorry, but this patch is wrong. > > __parse_cmdline() is supposed to match the command line against a set of > keywords, one word at a time. The new implementation ignores the > word-boundaries and matches the whole command line once and then breaks > the loop, typically without having found a match. (See below) > > Can we please have this patch dropped, Will? Yup, this was fixed yesterday so please take linux-next 20230908 for a spin and let us know how you get on. Cheers, Will
diff --git a/arch/arm64/kernel/idreg-override.c b/arch/arm64/kernel/idreg-override.c index 2fe2491b692c..aee12c75b738 100644 --- a/arch/arm64/kernel/idreg-override.c +++ b/arch/arm64/kernel/idreg-override.c @@ -262,9 +262,9 @@ static __init void __parse_cmdline(const char *cmdline, bool parse_aliases) if (!len) return; - len = min(len, ARRAY_SIZE(buf) - 1); - strncpy(buf, cmdline, len); - buf[len] = 0; + len = strscpy(buf, cmdline, ARRAY_SIZE(buf)); + if (len == -E2BIG) + len = ARRAY_SIZE(buf) - 1; if (strcmp(buf, "--") == 0) return;
`strncpy` is deprecated for use on NUL-terminated destination strings [1]. Which seems to be the case here due to the forceful setting of `buf`'s tail to 0. A suitable replacement is `strscpy` [2] due to the fact that it guarantees NUL-termination on its destination buffer argument which is _not_ the case for `strncpy`! In this case, we can simplify the logic and also check for any silent truncation by using `strscpy`'s return value. This should have no functional change and yet uses a more robust and less ambiguous interface whilst reducing code complexity. Link: www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings[1] Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2] Link: https://github.com/KSPP/linux/issues/90 Suggested-by: Kees Cook <keescook@chromium.org> Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt <justinstitt@google.com> --- Changes in v2: - Utilize return value from strscpy and check for truncation (thanks Kees) - Link to v1: https://lore.kernel.org/r/20230810-strncpy-arch-arm64-v1-1-f67f3685cd64@google.com --- For reference, see a part of `strscpy`'s implementation here: | /* Hit buffer length without finding a NUL; force NUL-termination. */ | if (res) | dest[res-1] = '\0'; Note: compile tested --- arch/arm64/kernel/idreg-override.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- base-commit: 52a93d39b17dc7eb98b6aa3edb93943248e03b2f change-id: 20230810-strncpy-arch-arm64-1f3d328bd9b8 Best regards, -- Justin Stitt <justinstitt@google.com>