Skip to content

Commit

Permalink
Merge branch 'for-next/hardening' into for-next/kspp
Browse files Browse the repository at this point in the history
  • Loading branch information
kees committed Mar 7, 2025
2 parents d985e43 + 6c2c858 commit cb17a46
Show file tree
Hide file tree
Showing 26 changed files with 191 additions and 128 deletions.
4 changes: 3 additions & 1 deletion Documentation/admin-guide/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1785,7 +1785,9 @@
allocation boundaries as a proactive defense
against bounds-checking flaws in the kernel's
copy_to_user()/copy_from_user() interface.
on Perform hardened usercopy checks (default).
The default is determined by
CONFIG_HARDENED_USERCOPY_DEFAULT_ON.
on Perform hardened usercopy checks.
off Disable hardened usercopy checks.

hardlockup_all_cpu_backtrace=
Expand Down
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -12586,6 +12586,7 @@ F: Documentation/ABI/testing/sysfs-kernel-warn_count
F: arch/*/configs/hardening.config
F: include/linux/overflow.h
F: include/linux/randomize_kstack.h
F: include/linux/ucopysize.h
F: kernel/configs/hardening.config
F: lib/tests/usercopy_kunit.c
F: mm/usercopy.c
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/coco/tdx/tdx.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,11 +167,11 @@ static void __noreturn tdx_panic(const char *msg)
/* Define register order according to the GHCI */
struct { u64 r14, r15, rbx, rdi, rsi, r8, r9, rdx; };

char str[64];
char bytes[64] __nonstring;
} message;

/* VMM assumes '\0' in byte 65, if the message took all 64 bytes */
strtomem_pad(message.str, msg, '\0');
strtomem_pad(message.bytes, msg, '\0');

args.r8 = message.r8;
args.r9 = message.r9;
Expand Down
8 changes: 4 additions & 4 deletions drivers/message/fusion/mptsas.c
Original file line number Diff line number Diff line change
Expand Up @@ -2834,10 +2834,10 @@ struct rep_manu_reply{
u8 sas_format:1;
u8 reserved1:7;
u8 reserved2[3];
u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] __nonstring;
u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN] __nonstring;
u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] __nonstring;
u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] __nonstring;
u16 component_id;
u8 component_revision_id;
u8 reserved3;
Expand Down
8 changes: 4 additions & 4 deletions drivers/scsi/mpi3mr/mpi3mr_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ struct rep_manu_reply {
u8 reserved0[2];
u8 sas_format;
u8 reserved2[3];
u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] __nonstring;
u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN] __nonstring;
u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] __nonstring;
u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] __nonstring;
u16 component_id;
u8 component_revision_id;
u8 reserved3;
Expand Down
2 changes: 1 addition & 1 deletion drivers/scsi/mpt3sas/mpi/mpi2_cnfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -606,7 +606,7 @@ typedef struct _MPI2_CONFIG_REPLY {

typedef struct _MPI2_CONFIG_PAGE_MAN_0 {
MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */
U8 ChipName[16]; /*0x04 */
U8 ChipName[16] __nonstring; /*0x04 */
U8 ChipRevision[8]; /*0x14 */
U8 BoardName[16]; /*0x1C */
U8 BoardAssembly[16]; /*0x2C */
Expand Down
8 changes: 4 additions & 4 deletions drivers/scsi/mpt3sas/mpt3sas_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,10 @@ struct rep_manu_reply {
u8 reserved0[2];
u8 sas_format;
u8 reserved2[3];
u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN] __nonstring;
u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN] __nonstring;
u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN] __nonstring;
u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN] __nonstring;
u16 component_id;
u8 component_revision_id;
u8 reserved3;
Expand Down
4 changes: 2 additions & 2 deletions drivers/scsi/qla2xxx/qla_mr.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,8 +282,8 @@ struct register_host_info {
#define QLAFX00_TGT_NODE_LIST_SIZE (sizeof(uint32_t) * 32)

struct config_info_data {
uint8_t model_num[16];
uint8_t model_description[80];
uint8_t model_num[16] __nonstring;
uint8_t model_description[80] __nonstring;
uint8_t reserved0[160];
uint8_t symbolic_name[64];
uint8_t serial_num[32];
Expand Down
18 changes: 17 additions & 1 deletion include/linux/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,25 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
#define __must_be_byte_array(a) __BUILD_BUG_ON_ZERO_MSG(!__is_byte_array(a), \
"must be byte array")

/*
* If the "nonstring" attribute isn't available, we have to return true
* so the __must_*() checks pass when "nonstring" isn't supported.
*/
#if __has_attribute(__nonstring__) && defined(__annotated)
#define __is_cstr(a) (!__annotated(a, nonstring))
#define __is_noncstr(a) (__annotated(a, nonstring))
#else
#define __is_cstr(a) (true)
#define __is_noncstr(a) (true)
#endif

/* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
#define __must_be_cstr(p) \
__BUILD_BUG_ON_ZERO_MSG(__annotated(p, nonstring), "must be cstr (NUL-terminated)")
__BUILD_BUG_ON_ZERO_MSG(!__is_cstr(p), \
"must be C-string (NUL-terminated)")
#define __must_be_noncstr(p) \
__BUILD_BUG_ON_ZERO_MSG(!__is_noncstr(p), \
"must be non-C-string (not NUL-terminated)")

#endif /* __KERNEL__ */

Expand Down
9 changes: 6 additions & 3 deletions include/linux/compiler_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -446,11 +446,14 @@ struct ftrace_likely_data {
#define __member_size(p) __builtin_object_size(p, 1)
#endif

/* Determine if an attribute has been applied to a variable. */
/*
* Determine if an attribute has been applied to a variable.
* Using __annotated needs to check for __annotated being available,
* or negative tests may fail when annotation cannot be checked. For
* example, see the definition of __is_cstr().
*/
#if __has_builtin(__builtin_has_attribute)
#define __annotated(var, attr) __builtin_has_attribute(var, attr)
#else
#define __annotated(var, attr) (false)
#endif

/*
Expand Down
16 changes: 12 additions & 4 deletions include/linux/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,10 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
*/
#define strtomem_pad(dest, src, pad) do { \
const size_t _dest_len = __must_be_byte_array(dest) + \
__must_be_noncstr(dest) + \
ARRAY_SIZE(dest); \
const size_t _src_len = __builtin_object_size(src, 1); \
const size_t _src_len = __must_be_cstr(src) + \
__builtin_object_size(src, 1); \
\
BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \
_dest_len == (size_t)-1); \
Expand All @@ -439,8 +441,10 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
*/
#define strtomem(dest, src) do { \
const size_t _dest_len = __must_be_byte_array(dest) + \
__must_be_noncstr(dest) + \
ARRAY_SIZE(dest); \
const size_t _src_len = __builtin_object_size(src, 1); \
const size_t _src_len = __must_be_cstr(src) + \
__builtin_object_size(src, 1); \
\
BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \
_dest_len == (size_t)-1); \
Expand All @@ -459,8 +463,10 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
*/
#define memtostr(dest, src) do { \
const size_t _dest_len = __must_be_byte_array(dest) + \
__must_be_cstr(dest) + \
ARRAY_SIZE(dest); \
const size_t _src_len = __builtin_object_size(src, 1); \
const size_t _src_len = __must_be_noncstr(src) + \
__builtin_object_size(src, 1); \
const size_t _src_chars = strnlen(src, _src_len); \
const size_t _copy_len = min(_dest_len - 1, _src_chars); \
\
Expand All @@ -485,8 +491,10 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
*/
#define memtostr_pad(dest, src) do { \
const size_t _dest_len = __must_be_byte_array(dest) + \
__must_be_cstr(dest) + \
ARRAY_SIZE(dest); \
const size_t _src_len = __builtin_object_size(src, 1); \
const size_t _src_len = __must_be_noncstr(src) + \
__builtin_object_size(src, 1); \
const size_t _src_chars = strnlen(src, _src_len); \
const size_t _copy_len = min(_dest_len - 1, _src_chars); \
\
Expand Down
24 changes: 12 additions & 12 deletions include/linux/string_choices.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,35 +41,35 @@ static inline const char *str_high_low(bool v)
}
#define str_low_high(v) str_high_low(!(v))

static inline const char *str_read_write(bool v)
{
return v ? "read" : "write";
}
#define str_write_read(v) str_read_write(!(v))

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)
static inline const char *str_read_write(bool v)
{
return v ? "yes" : "no";
return v ? "read" : "write";
}
#define str_no_yes(v) str_yes_no(!(v))
#define str_write_read(v) str_read_write(!(v))

static inline const char *str_true_false(bool v)
{
return v ? "true" : "false";
}
#define str_false_true(v) str_true_false(!(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)
static inline const char *str_yes_no(bool v)
{
return v ? "true" : "false";
return v ? "yes" : "no";
}
#define str_false_true(v) str_true_false(!(v))
#define str_no_yes(v) str_yes_no(!(v))

/**
* str_plural - Return the simple pluralization based on English counts
Expand Down
48 changes: 0 additions & 48 deletions include/linux/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,54 +217,6 @@ static inline int arch_within_stack_frames(const void * const stack,
}
#endif

#ifdef CONFIG_HARDENED_USERCOPY
extern void __check_object_size(const void *ptr, unsigned long n,
bool to_user);

static __always_inline void check_object_size(const void *ptr, unsigned long n,
bool to_user)
{
if (!__builtin_constant_p(n))
__check_object_size(ptr, n, to_user);
}
#else
static inline void check_object_size(const void *ptr, unsigned long n,
bool to_user)
{ }
#endif /* CONFIG_HARDENED_USERCOPY */

extern void __compiletime_error("copy source size is too small")
__bad_copy_from(void);
extern void __compiletime_error("copy destination size is too small")
__bad_copy_to(void);

void __copy_overflow(int size, unsigned long count);

static inline void copy_overflow(int size, unsigned long count)
{
if (IS_ENABLED(CONFIG_BUG))
__copy_overflow(size, count);
}

static __always_inline __must_check bool
check_copy_size(const void *addr, size_t bytes, bool is_source)
{
int sz = __builtin_object_size(addr, 0);
if (unlikely(sz >= 0 && sz < bytes)) {
if (!__builtin_constant_p(bytes))
copy_overflow(sz, bytes);
else if (is_source)
__bad_copy_from();
else
__bad_copy_to();
return false;
}
if (WARN_ON_ONCE(bytes > INT_MAX))
return false;
check_object_size(addr, bytes, is_source);
return true;
}

#ifndef arch_setup_new_exec
static inline void arch_setup_new_exec(void) { }
#endif
Expand Down
2 changes: 1 addition & 1 deletion include/linux/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include <linux/minmax.h>
#include <linux/nospec.h>
#include <linux/sched.h>
#include <linux/thread_info.h>
#include <linux/ucopysize.h>

#include <asm/uaccess.h>

Expand Down
63 changes: 63 additions & 0 deletions include/linux/ucopysize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Perform sanity checking for object sizes for uaccess.h and uio.h. */
#ifndef __LINUX_UCOPYSIZE_H__
#define __LINUX_UCOPYSIZE_H__

#include <linux/bug.h>

#ifdef CONFIG_HARDENED_USERCOPY
#include <linux/jump_label.h>
extern void __check_object_size(const void *ptr, unsigned long n,
bool to_user);

DECLARE_STATIC_KEY_MAYBE(CONFIG_HARDENED_USERCOPY_DEFAULT_ON,
validate_usercopy_range);

static __always_inline void check_object_size(const void *ptr, unsigned long n,
bool to_user)
{
if (!__builtin_constant_p(n) &&
static_branch_maybe(CONFIG_HARDENED_USERCOPY_DEFAULT_ON,
&validate_usercopy_range)) {
__check_object_size(ptr, n, to_user);
}
}
#else
static inline void check_object_size(const void *ptr, unsigned long n,
bool to_user)
{ }
#endif /* CONFIG_HARDENED_USERCOPY */

extern void __compiletime_error("copy source size is too small")
__bad_copy_from(void);
extern void __compiletime_error("copy destination size is too small")
__bad_copy_to(void);

void __copy_overflow(int size, unsigned long count);

static inline void copy_overflow(int size, unsigned long count)
{
if (IS_ENABLED(CONFIG_BUG))
__copy_overflow(size, count);
}

static __always_inline __must_check bool
check_copy_size(const void *addr, size_t bytes, bool is_source)
{
int sz = __builtin_object_size(addr, 0);
if (unlikely(sz >= 0 && sz < bytes)) {
if (!__builtin_constant_p(bytes))
copy_overflow(sz, bytes);
else if (is_source)
__bad_copy_from();
else
__bad_copy_to();
return false;
}
if (WARN_ON_ONCE(bytes > INT_MAX))
return false;
check_object_size(addr, bytes, is_source);
return true;
}

#endif /* __LINUX_UCOPYSIZE_H__ */
2 changes: 1 addition & 1 deletion include/linux/uio.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#define __LINUX_UIO_H

#include <linux/kernel.h>
#include <linux/thread_info.h>
#include <linux/mm_types.h>
#include <linux/ucopysize.h>
#include <uapi/linux/uio.h>

struct page;
Expand Down
3 changes: 2 additions & 1 deletion include/uapi/linux/nilfs2_ondisk.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ struct nilfs_super_block {
__le16 s_segment_usage_size; /* Size of a segment usage */

/*98*/ __u8 s_uuid[16]; /* 128-bit uuid for volume */
/*A8*/ char s_volume_name[80]; /* volume name */
/*A8*/ char s_volume_name[80] /* volume name */
__kernel_nonstring;

/*F8*/ __le32 s_c_interval; /* Commit interval of segment */
__le32 s_c_block_max; /*
Expand Down
6 changes: 6 additions & 0 deletions include/uapi/linux/stddef.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,10 @@
#define __counted_by_be(m)
#endif

#ifdef __KERNEL__
#define __kernel_nonstring __nonstring
#else
#define __kernel_nonstring
#endif

#endif /* _UAPI_LINUX_STDDEF_H */
Loading

0 comments on commit cb17a46

Please sign in to comment.