hardening updates for v6.12-rc1

- lib/string_choices: Add str_up_down() helper (Michal Wajdeczko)
 
 - lib/string_choices: Add str_true_false()/str_false_true() helper
   (Hongbo Li)
 
 - lib/string_choices: Introduce several opposite string choice helpers
   (Hongbo Li)
 
 - lib/string_helpers: rework overflow-dependent code (Justin Stitt)
 
 - fortify: refactor test_fortify Makefile to fix some build problems
   (Masahiro Yamada)
 
 - string: Check for "nonstring" attribute on strscpy() arguments
 
 - virt: vbox: Replace 1-element arrays with flexible arrays
 
 - media: venus: hfi_cmds: Replace 1-element arrays with flexible arrays
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCZufwawAKCRA2KwveOeQk
 u3n9AQCI8G1FSMFSa8MKSSwTo600dHbZGavJd33fl2VrV7KCvQD8CMPRC/itOIVI
 PXcGo9tekW+zAOOw+v47QorpxHGd1w4=
 =jSSr
 -----END PGP SIGNATURE-----

Merge tag 'hardening-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull hardening updates from Kees Cook:

 - lib/string_choices:
    - Add str_up_down() helper (Michal Wajdeczko)
    - Add str_true_false()/str_false_true() helper  (Hongbo Li)
    - Introduce several opposite string choice helpers  (Hongbo Li)

 - lib/string_helpers:
    - rework overflow-dependent code (Justin Stitt)

 - fortify: refactor test_fortify Makefile to fix some build problems
   (Masahiro Yamada)

 - string: Check for "nonstring" attribute on strscpy() arguments

 - virt: vbox: Replace 1-element arrays with flexible arrays

 - media: venus: hfi_cmds: Replace 1-element arrays with flexible arrays

* tag 'hardening-v6.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  lib/string_choices: Add some comments to make more clear for string choices helpers.
  lib/string_choices: Introduce several opposite string choice helpers
  lib/string_choices: Add str_true_false()/str_false_true() helper
  string: Check for "nonstring" attribute on strscpy() arguments
  media: venus: hfi_cmds: struct hfi_session_release_buffer_pkt: Add __counted_by annotation
  media: venus: hfi_cmds: struct hfi_session_release_buffer_pkt: Replace 1-element array with flexible array
  virt: vbox: struct vmmdev_hgcm_pagelist: Replace 1-element array with flexible array
  lib/string_helpers: rework overflow-dependent code
  coccinelle: Add rules to find str_down_up() replacements
  string_choices: Add wrapper for str_down_up()
  coccinelle: Add rules to find str_up_down() replacements
  lib/string_choices: Add str_up_down() helper
  fortify: use if_changed_dep to record header dependency in *.cmd files
  fortify: move test_fortify.sh to lib/test_fortify/
  fortify: refactor test_fortify Makefile to fix some build problems
This commit is contained in:
Linus Torvalds 2024-09-18 12:12:41 +02:00
commit 39b3f4e0db
15 changed files with 134 additions and 46 deletions

View File

@ -8834,7 +8834,6 @@ F: include/linux/fortify-string.h
F: lib/fortify_kunit.c
F: lib/memcpy_kunit.c
F: lib/test_fortify/*
F: scripts/test_fortify.sh
K: \b__NO_FORTIFY\b
FPGA DFL DRIVERS

View File

@ -227,7 +227,7 @@ struct hfi_session_release_buffer_pkt {
u32 extradata_size;
u32 response_req;
u32 num_buffers;
u32 buffer_info[1];
u32 buffer_info[] __counted_by(num_buffers);
};
struct hfi_session_release_resources_pkt {

View File

@ -242,6 +242,9 @@ static inline void *offset_to_ptr(const int *off)
/* &a[0] degrades to a pointer: a different type from an array */
#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
/* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
#define __must_be_cstr(p) BUILD_BUG_ON_ZERO(__annotated(p, nonstring))
/*
* This returns a constant expression while determining if an argument is
* a constant expression, most importantly without evaluating the argument.

View File

@ -421,6 +421,13 @@ struct ftrace_likely_data {
#define __member_size(p) __builtin_object_size(p, 1)
#endif
/* Determine if an attribute has been applied to a variable. */
#if __has_builtin(__builtin_has_attribute)
#define __annotated(var, attr) __builtin_has_attribute(var, attr)
#else
#define __annotated(var, attr) (false)
#endif
/*
* Some versions of gcc do not mark 'asm goto' volatile:
*

View File

@ -76,12 +76,16 @@ ssize_t sized_strscpy(char *, const char *, size_t);
* known size.
*/
#define __strscpy0(dst, src, ...) \
sized_strscpy(dst, src, sizeof(dst) + __must_be_array(dst))
#define __strscpy1(dst, src, size) sized_strscpy(dst, src, size)
sized_strscpy(dst, src, sizeof(dst) + __must_be_array(dst) + \
__must_be_cstr(dst) + __must_be_cstr(src))
#define __strscpy1(dst, src, size) \
sized_strscpy(dst, src, size + __must_be_cstr(dst) + __must_be_cstr(src))
#define __strscpy_pad0(dst, src, ...) \
sized_strscpy_pad(dst, src, sizeof(dst) + __must_be_array(dst))
#define __strscpy_pad1(dst, src, size) sized_strscpy_pad(dst, src, size)
sized_strscpy_pad(dst, src, sizeof(dst) + __must_be_array(dst) + \
__must_be_cstr(dst) + __must_be_cstr(src))
#define __strscpy_pad1(dst, src, size) \
sized_strscpy_pad(dst, src, size + __must_be_cstr(dst) + __must_be_cstr(src))
/**
* strscpy - Copy a C-string into a sized buffer

View File

@ -2,17 +2,32 @@
#ifndef _LINUX_STRING_CHOICES_H_
#define _LINUX_STRING_CHOICES_H_
/*
* Here provide a series of helpers in the str_$TRUE_$FALSE format (you can
* also expand some helpers as needed), where $TRUE and $FALSE are their
* corresponding literal strings. These helpers can be used in the printing
* and also in other places where constant strings are required. Using these
* helpers offers the following benefits:
* 1) Reducing the hardcoding of strings, which makes the code more elegant
* through these simple literal-meaning helpers.
* 2) Unifying the output, which prevents the same string from being printed
* in various forms, such as enable/disable, enabled/disabled, en/dis.
* 3) Deduping by the linker, which results in a smaller binary file.
*/
#include <linux/types.h>
static inline const char *str_enable_disable(bool v)
{
return v ? "enable" : "disable";
}
#define str_disable_enable(v) str_enable_disable(!(v))
static inline const char *str_enabled_disabled(bool v)
{
return v ? "enabled" : "disabled";
}
#define str_disabled_enabled(v) str_enabled_disabled(!(v))
static inline const char *str_hi_lo(bool v)
{
@ -36,11 +51,25 @@ static inline const char *str_on_off(bool v)
{
return v ? "on" : "off";
}
#define str_off_on(v) str_on_off(!(v))
static inline const char *str_yes_no(bool v)
{
return v ? "yes" : "no";
}
#define str_no_yes(v) str_yes_no(!(v))
static inline const char *str_up_down(bool v)
{
return v ? "up" : "down";
}
#define str_down_up(v) str_up_down(!(v))
static inline const char *str_true_false(bool v)
{
return v ? "true" : "false";
}
#define str_false_true(v) str_true_false(!(v))
/**
* str_plural - Return the simple pluralization based on English counts

View File

@ -282,7 +282,10 @@ struct vmmdev_hgcm_pagelist {
__u32 flags; /** VMMDEV_HGCM_F_PARM_*. */
__u16 offset_first_page; /** Data offset in the first page. */
__u16 page_count; /** Number of pages. */
__u64 pages[1]; /** Page addresses. */
union {
__u64 unused; /** Deprecated place-holder for first "pages" entry. */
__DECLARE_FLEX_ARRAY(__u64, pages); /** Page addresses. */
};
};
VMMDEV_ASSERT_SIZE(vmmdev_hgcm_pagelist, 4 + 2 + 2 + 8);

2
lib/.gitignore vendored
View File

@ -5,5 +5,3 @@
/gen_crc32table
/gen_crc64table
/oid_registry_data.c
/test_fortify.log
/test_fortify/*.log

View File

@ -393,40 +393,4 @@ obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
obj-$(CONFIG_FIRMWARE_TABLE) += fw_table.o
# FORTIFY_SOURCE compile-time behavior tests
TEST_FORTIFY_SRCS = $(wildcard $(src)/test_fortify/*-*.c)
TEST_FORTIFY_LOGS = $(patsubst $(src)/%.c, %.log, $(TEST_FORTIFY_SRCS))
TEST_FORTIFY_LOG = test_fortify.log
quiet_cmd_test_fortify = TEST $@
cmd_test_fortify = $(CONFIG_SHELL) $(srctree)/scripts/test_fortify.sh \
$< $@ "$(NM)" $(CC) $(c_flags) \
$(call cc-disable-warning,fortify-source) \
-DKBUILD_EXTRA_WARN1
targets += $(TEST_FORTIFY_LOGS)
clean-files += $(TEST_FORTIFY_LOGS)
clean-files += $(addsuffix .o, $(TEST_FORTIFY_LOGS))
$(obj)/test_fortify/%.log: $(src)/test_fortify/%.c \
$(src)/test_fortify/test_fortify.h \
$(srctree)/include/linux/fortify-string.h \
$(srctree)/scripts/test_fortify.sh \
FORCE
$(call if_changed,test_fortify)
quiet_cmd_gen_fortify_log = GEN $@
cmd_gen_fortify_log = cat </dev/null $(filter-out FORCE,$^) 2>/dev/null > $@ || true
targets += $(TEST_FORTIFY_LOG)
clean-files += $(TEST_FORTIFY_LOG)
$(obj)/$(TEST_FORTIFY_LOG): $(addprefix $(obj)/, $(TEST_FORTIFY_LOGS)) FORCE
$(call if_changed,gen_fortify_log)
# Fake dependency to trigger the fortify tests.
ifeq ($(CONFIG_FORTIFY_SOURCE),y)
$(obj)/string.o: $(obj)/$(TEST_FORTIFY_LOG)
endif
# Some architectures define __NO_FORTIFY if __SANITIZE_ADDRESS__ is undefined.
# Pass CFLAGS_KASAN to avoid warnings.
$(foreach x, $(patsubst %.log,%.o,$(TEST_FORTIFY_LOGS)), $(eval KASAN_SANITIZE_$(x) := y))
subdir-$(CONFIG_FORTIFY_SOURCE) += test_fortify

View File

@ -321,6 +321,9 @@ int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
{
char *out = dst;
if (!size)
size = SIZE_MAX;
while (*src && --size) {
if (src[0] == '\\' && src[1] != '\0' && size > 1) {
src++;

2
lib/test_fortify/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
# SPDX-License-Identifier: GPL-2.0-only
/*.log

28
lib/test_fortify/Makefile Normal file
View File

@ -0,0 +1,28 @@
# SPDX-License-Identifier: GPL-2.0
ccflags-y := $(call cc-disable-warning,fortify-source)
quiet_cmd_test_fortify = TEST $@
cmd_test_fortify = $(CONFIG_SHELL) $(src)/test_fortify.sh \
$< $@ "$(NM)" $(CC) $(c_flags) -DKBUILD_EXTRA_WARN1
$(obj)/%.log: $(src)/%.c $(src)/test_fortify.sh FORCE
$(call if_changed_dep,test_fortify)
logs = $(patsubst $(src)/%.c, %.log, $(wildcard $(src)/*-*.c))
targets += $(logs)
quiet_cmd_gen_fortify_log = CAT $@
cmd_gen_fortify_log = cat $(or $(real-prereqs),/dev/null) > $@
$(obj)/test_fortify.log: $(addprefix $(obj)/, $(logs)) FORCE
$(call if_changed,gen_fortify_log)
# GCC<=7 does not always produce *.d files.
# Run the tests only for GCC>=8 or Clang.
always-$(call gcc-min-version, 80000) += test_fortify.log
always-$(CONFIG_CC_IS_CLANG) += test_fortify.log
# Some architectures define __NO_FORTIFY if __SANITIZE_ADDRESS__ is undefined.
# Pass CFLAGS_KASAN to avoid warnings.
KASAN_SANITIZE := y

View File

@ -39,3 +39,49 @@ e << str_plural_r.E;
@@
coccilib.report.print_report(p[0], "opportunity for str_plural(%s)" % e)
@str_up_down depends on patch@
expression E;
@@
(
- ((E) ? "up" : "down")
+ str_up_down(E)
)
@str_up_down_r depends on !patch exists@
expression E;
position P;
@@
(
* ((E@P) ? "up" : "down")
)
@script:python depends on report@
p << str_up_down_r.P;
e << str_up_down_r.E;
@@
coccilib.report.print_report(p[0], "opportunity for str_up_down(%s)" % e)
@str_down_up depends on patch@
expression E;
@@
(
- ((E) ? "down" : "up")
+ str_down_up(E)
)
@str_down_up_r depends on !patch exists@
expression E;
position P;
@@
(
* ((E@P) ? "down" : "up")
)
@script:python depends on report@
p << str_down_up_r.P;
e << str_down_up_r.E;
@@
coccilib.report.print_report(p[0], "opportunity for str_down_up(%s)" % e)

View File

@ -21,3 +21,5 @@ set -e
# then will be really dead and removed from the code base entirely.
rm -f *.spec
rm -f lib/test_fortify.log