hardening updates for v7.0-rc1
- Various missed __counted_by annotations (Thorsten Blum)
- Various missed -Wflex-array-member-not-at-end fixes (Gustavo A. R. Silva)
- Avoid leftover tempfiles for interrupted compile-time FORTIFY tests
(Nicolas Schier)
- Remove non-existant CONFIG_UBSAN_REPORT_FULL from docs (Stefan Wiehler)
- fortify: Use C arithmetic not FIELD_xxx() in FORTIFY_REASON defines
(David Laight)
- Add __counted_by_ptr attribute, tests, and first user (Bill Wendling,
Kees Cook)
- Update MAINTAINERS file to make hardening section not include pstore
-----BEGIN PGP SIGNATURE-----
iHUEABYKAB0WIQRSPkdeREjth1dHnSE2KwveOeQkuwUCaYopPQAKCRA2KwveOeQk
u5QDAQDj9ygsbzLj9EtXtU3T03GTvix4Rx7RkaBAMPSDEJGhNQD+M3dP6Z2ogEMz
1Km6dAC7nTEujsVFur9BVpyEgoBjjQM=
=G1gb
-----END PGP SIGNATURE-----
Merge tag 'hardening-v7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull hardening updates from Kees Cook:
"Mostly small cleanups and various scattered annotations and flex array
warning fixes that we reviewed by unlanded in other trees. Introduces
new annotation for expanding counted_by to pointer members, now that
compiler behavior between GCC and Clang has been normalized.
- Various missed __counted_by annotations (Thorsten Blum)
- Various missed -Wflex-array-member-not-at-end fixes (Gustavo A. R.
Silva)
- Avoid leftover tempfiles for interrupted compile-time FORTIFY tests
(Nicolas Schier)
- Remove non-existant CONFIG_UBSAN_REPORT_FULL from docs (Stefan
Wiehler)
- fortify: Use C arithmetic not FIELD_xxx() in FORTIFY_REASON defines
(David Laight)
- Add __counted_by_ptr attribute, tests, and first user (Bill
Wendling, Kees Cook)
- Update MAINTAINERS file to make hardening section not include
pstore"
* tag 'hardening-v7.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
MAINTAINERS: pstore: Remove L: entry
nfp: tls: Avoid -Wflex-array-member-not-at-end warnings
carl9170: Avoid -Wflex-array-member-not-at-end warning
coredump: Use __counted_by_ptr for struct core_name::corename
lkdtm/bugs: Add __counted_by_ptr() test PTR_BOUNDS
compiler_types.h: Attributes: Add __counted_by_ptr macro
fortify: Cleanup temp file also on non-successful exit
fortify: Rename temporary file to match ignore pattern
fortify: Use C arithmetic not FIELD_xxx() in FORTIFY_REASON defines
ecryptfs: Annotate struct ecryptfs_message with __counted_by
fs/xattr: Annotate struct simple_xattr with __counted_by
crypto: af_alg - Annotate struct af_alg_iv with __counted_by
Kconfig.ubsan: Remove CONFIG_UBSAN_REPORT_FULL from documentation
drm/nouveau: fifo: Avoid -Wflex-array-member-not-at-end warning
This commit is contained in:
commit
85f24b0ace
|
|
@ -20996,7 +20996,6 @@ PSTORE FILESYSTEM
|
|||
M: Kees Cook <kees@kernel.org>
|
||||
R: Tony Luck <tony.luck@intel.com>
|
||||
R: Guilherme G. Piccoli <gpiccoli@igalia.com>
|
||||
L: linux-hardening@vger.kernel.org
|
||||
S: Supported
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/pstore
|
||||
F: Documentation/admin-guide/pstore-blk.rst
|
||||
|
|
|
|||
6
Makefile
6
Makefile
|
|
@ -952,6 +952,12 @@ KBUILD_CFLAGS += $(CC_AUTO_VAR_INIT_ZERO_ENABLER)
|
|||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CC_IS_CLANG
|
||||
ifdef CONFIG_CC_HAS_COUNTED_BY_PTR
|
||||
KBUILD_CFLAGS += -fexperimental-late-parse-attributes
|
||||
endif
|
||||
endif
|
||||
|
||||
# Explicitly clear padding bits during variable initialization
|
||||
KBUILD_CFLAGS += $(call cc-option,-fzero-init-padding-bits=all)
|
||||
|
||||
|
|
|
|||
|
|
@ -25,13 +25,12 @@ static int
|
|||
nvif_fifo_runlists(struct nvif_device *device)
|
||||
{
|
||||
struct nvif_object *object = &device->object;
|
||||
struct {
|
||||
struct nv_device_info_v1 m;
|
||||
TRAILING_OVERLAP(struct nv_device_info_v1, m, data,
|
||||
struct {
|
||||
struct nv_device_info_v1_data runlists;
|
||||
struct nv_device_info_v1_data runlist[64];
|
||||
} v;
|
||||
} *a;
|
||||
) *a;
|
||||
int ret, i;
|
||||
|
||||
if (device->runlist)
|
||||
|
|
|
|||
|
|
@ -465,32 +465,32 @@ static void lkdtm_ARRAY_BOUNDS(void)
|
|||
pr_expected_config(CONFIG_UBSAN_BOUNDS);
|
||||
}
|
||||
|
||||
struct lkdtm_annotated {
|
||||
struct lkdtm_cb_fam {
|
||||
unsigned long flags;
|
||||
int count;
|
||||
int array[] __counted_by(count);
|
||||
};
|
||||
|
||||
static volatile int fam_count = 4;
|
||||
static volatile int element_count = 4;
|
||||
|
||||
static void lkdtm_FAM_BOUNDS(void)
|
||||
{
|
||||
struct lkdtm_annotated *inst;
|
||||
struct lkdtm_cb_fam *inst;
|
||||
|
||||
inst = kzalloc(struct_size(inst, array, fam_count + 1), GFP_KERNEL);
|
||||
inst = kzalloc(struct_size(inst, array, element_count + 1), GFP_KERNEL);
|
||||
if (!inst) {
|
||||
pr_err("FAIL: could not allocate test struct!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
inst->count = fam_count;
|
||||
inst->count = element_count;
|
||||
pr_info("Array access within bounds ...\n");
|
||||
inst->array[1] = fam_count;
|
||||
inst->array[1] = element_count;
|
||||
ignored = inst->array[1];
|
||||
|
||||
pr_info("Array access beyond bounds ...\n");
|
||||
inst->array[fam_count] = fam_count;
|
||||
ignored = inst->array[fam_count];
|
||||
inst->array[element_count] = element_count;
|
||||
ignored = inst->array[element_count];
|
||||
|
||||
kfree(inst);
|
||||
|
||||
|
|
@ -505,6 +505,79 @@ static void lkdtm_FAM_BOUNDS(void)
|
|||
pr_expected_config(CONFIG_UBSAN_BOUNDS);
|
||||
}
|
||||
|
||||
struct lkdtm_extra {
|
||||
short a, b;
|
||||
u16 sixteen;
|
||||
u32 bigger;
|
||||
u64 biggest;
|
||||
};
|
||||
|
||||
struct lkdtm_cb_ptr {
|
||||
int a, b, c;
|
||||
int nr_extra;
|
||||
char *buf __counted_by_ptr(len);
|
||||
size_t len;
|
||||
struct lkdtm_extra *extra __counted_by_ptr(nr_extra);
|
||||
};
|
||||
|
||||
static noinline void check_ptr_len(struct lkdtm_cb_ptr *p, size_t len)
|
||||
{
|
||||
if (__member_size(p->buf) != len)
|
||||
pr_err("FAIL: could not determine size of inst->buf: %zu\n",
|
||||
__member_size(p->buf));
|
||||
else
|
||||
pr_info("good: inst->buf length is %zu\n", len);
|
||||
}
|
||||
|
||||
static void lkdtm_PTR_BOUNDS(void)
|
||||
{
|
||||
struct lkdtm_cb_ptr *inst;
|
||||
|
||||
inst = kzalloc(sizeof(*inst), GFP_KERNEL);
|
||||
if (!inst) {
|
||||
pr_err("FAIL: could not allocate struct lkdtm_cb_ptr!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
inst->buf = kzalloc(element_count, GFP_KERNEL);
|
||||
if (!inst->buf) {
|
||||
pr_err("FAIL: could not allocate inst->buf!\n");
|
||||
return;
|
||||
}
|
||||
inst->len = element_count;
|
||||
|
||||
/* Double element_count */
|
||||
inst->extra = kcalloc(element_count * 2, sizeof(*inst->extra), GFP_KERNEL);
|
||||
inst->nr_extra = element_count * 2;
|
||||
|
||||
pr_info("Pointer access within bounds ...\n");
|
||||
check_ptr_len(inst, 4);
|
||||
/* All 4 bytes */
|
||||
inst->buf[0] = 'A';
|
||||
inst->buf[1] = 'B';
|
||||
inst->buf[2] = 'C';
|
||||
inst->buf[3] = 'D';
|
||||
/* Halfway into the array */
|
||||
inst->extra[element_count].biggest = 0x1000;
|
||||
|
||||
pr_info("Pointer access beyond bounds ...\n");
|
||||
ignored = inst->extra[inst->nr_extra].b;
|
||||
|
||||
kfree(inst->extra);
|
||||
kfree(inst->buf);
|
||||
kfree(inst);
|
||||
|
||||
pr_err("FAIL: survived access of invalid pointer member offset!\n");
|
||||
|
||||
if (!IS_ENABLED(CONFIG_CC_HAS_COUNTED_BY_PTR))
|
||||
pr_warn("This is expected since this %s was built with a compiler that does not support __counted_by_ptr\n",
|
||||
lkdtm_kernel_info);
|
||||
else if (IS_ENABLED(CONFIG_UBSAN_BOUNDS))
|
||||
pr_expected_config(CONFIG_UBSAN_TRAP);
|
||||
else
|
||||
pr_expected_config(CONFIG_UBSAN_BOUNDS);
|
||||
}
|
||||
|
||||
static void lkdtm_CORRUPT_LIST_ADD(void)
|
||||
{
|
||||
/*
|
||||
|
|
@ -769,6 +842,7 @@ static struct crashtype crashtypes[] = {
|
|||
CRASHTYPE(OVERFLOW_UNSIGNED),
|
||||
CRASHTYPE(ARRAY_BOUNDS),
|
||||
CRASHTYPE(FAM_BOUNDS),
|
||||
CRASHTYPE(PTR_BOUNDS),
|
||||
CRASHTYPE(CORRUPT_LIST_ADD),
|
||||
CRASHTYPE(CORRUPT_LIST_DEL),
|
||||
CRASHTYPE(STACK_GUARD_PAGE_LEADING),
|
||||
|
|
|
|||
|
|
@ -32,16 +32,22 @@ struct nfp_crypto_req_reset {
|
|||
#define NFP_NET_TLS_VLAN_UNUSED 4095
|
||||
|
||||
struct nfp_crypto_req_add_front {
|
||||
struct nfp_ccm_hdr hdr;
|
||||
__be32 ep_id;
|
||||
u8 resv[3];
|
||||
u8 opcode;
|
||||
u8 key_len;
|
||||
__be16 ipver_vlan __packed;
|
||||
u8 l4_proto;
|
||||
/* New members MUST be added within the struct_group() macro below. */
|
||||
struct_group_tagged(nfp_crypto_req_add_front_hdr, __hdr,
|
||||
struct nfp_ccm_hdr hdr;
|
||||
__be32 ep_id;
|
||||
u8 resv[3];
|
||||
u8 opcode;
|
||||
u8 key_len;
|
||||
__be16 ipver_vlan __packed;
|
||||
u8 l4_proto;
|
||||
);
|
||||
#define NFP_NET_TLS_NON_ADDR_KEY_LEN 8
|
||||
u8 l3_addrs[];
|
||||
};
|
||||
static_assert(offsetof(struct nfp_crypto_req_add_front, l3_addrs) ==
|
||||
sizeof(struct nfp_crypto_req_add_front_hdr),
|
||||
"struct member likely outside of struct_group_tagged()");
|
||||
|
||||
struct nfp_crypto_req_add_back {
|
||||
__be16 src_port;
|
||||
|
|
@ -55,14 +61,14 @@ struct nfp_crypto_req_add_back {
|
|||
};
|
||||
|
||||
struct nfp_crypto_req_add_v4 {
|
||||
struct nfp_crypto_req_add_front front;
|
||||
struct nfp_crypto_req_add_front_hdr front;
|
||||
__be32 src_ip;
|
||||
__be32 dst_ip;
|
||||
struct nfp_crypto_req_add_back back;
|
||||
};
|
||||
|
||||
struct nfp_crypto_req_add_v6 {
|
||||
struct nfp_crypto_req_add_front front;
|
||||
struct nfp_crypto_req_add_front_hdr front;
|
||||
__be32 src_ip[4];
|
||||
__be32 dst_ip[4];
|
||||
struct nfp_crypto_req_add_back back;
|
||||
|
|
|
|||
|
|
@ -180,7 +180,9 @@ nfp_net_tls_set_ipv4(struct nfp_net *nn, struct nfp_crypto_req_add_v4 *req,
|
|||
req->front.key_len += sizeof(__be32) * 2;
|
||||
|
||||
if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
|
||||
nfp_net_tls_assign_conn_id(nn, &req->front);
|
||||
nfp_net_tls_assign_conn_id(nn,
|
||||
container_of(&req->front,
|
||||
struct nfp_crypto_req_add_front, __hdr));
|
||||
} else {
|
||||
req->src_ip = inet->inet_daddr;
|
||||
req->dst_ip = inet->inet_saddr;
|
||||
|
|
@ -199,7 +201,9 @@ nfp_net_tls_set_ipv6(struct nfp_net *nn, struct nfp_crypto_req_add_v6 *req,
|
|||
req->front.key_len += sizeof(struct in6_addr) * 2;
|
||||
|
||||
if (direction == TLS_OFFLOAD_CTX_DIR_TX) {
|
||||
nfp_net_tls_assign_conn_id(nn, &req->front);
|
||||
nfp_net_tls_assign_conn_id(nn,
|
||||
container_of(&req->front,
|
||||
struct nfp_crypto_req_add_front, __hdr));
|
||||
} else {
|
||||
memcpy(req->src_ip, &sk->sk_v6_daddr, sizeof(req->src_ip));
|
||||
memcpy(req->dst_ip, &np->saddr, sizeof(req->dst_ip));
|
||||
|
|
|
|||
|
|
@ -375,11 +375,6 @@ struct ar9170 {
|
|||
u8 *readbuf;
|
||||
spinlock_t cmd_lock;
|
||||
struct completion cmd_wait;
|
||||
union {
|
||||
__le32 cmd_buf[PAYLOAD_MAX + 1];
|
||||
struct carl9170_cmd cmd;
|
||||
struct carl9170_rsp rsp;
|
||||
};
|
||||
|
||||
/* statistics */
|
||||
unsigned int tx_dropped;
|
||||
|
|
@ -463,6 +458,13 @@ struct ar9170 {
|
|||
unsigned int cache_idx;
|
||||
} rng;
|
||||
#endif /* CONFIG_CARL9170_HWRNG */
|
||||
|
||||
/* Must be last as it ends in a flexible-array member. */
|
||||
union {
|
||||
__le32 cmd_buf[PAYLOAD_MAX + 1];
|
||||
struct carl9170_cmd cmd;
|
||||
struct carl9170_rsp rsp;
|
||||
};
|
||||
};
|
||||
|
||||
enum carl9170_ps_off_override_reasons {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ enum coredump_type_t {
|
|||
};
|
||||
|
||||
struct core_name {
|
||||
char *corename;
|
||||
char *corename __counted_by_ptr(size);
|
||||
int used, size;
|
||||
unsigned int core_pipe_limit;
|
||||
bool core_dumped;
|
||||
|
|
@ -106,15 +106,15 @@ static int expand_corename(struct core_name *cn, int size)
|
|||
|
||||
size = kmalloc_size_roundup(size);
|
||||
corename = krealloc(cn->corename, size, GFP_KERNEL);
|
||||
|
||||
if (!corename)
|
||||
return -ENOMEM;
|
||||
|
||||
cn->corename = corename;
|
||||
cn->size = size;
|
||||
|
||||
if (size > core_name_size) /* racy but harmless */
|
||||
core_name_size = size;
|
||||
|
||||
cn->size = size;
|
||||
cn->corename = corename;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ struct ecryptfs_message {
|
|||
/* Inherits from msg_ctx->index */
|
||||
u32 index;
|
||||
u32 data_len;
|
||||
u8 data[];
|
||||
u8 data[] __counted_by(data_len);
|
||||
};
|
||||
|
||||
struct ecryptfs_msg_ctx {
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ struct ftrace_likely_data {
|
|||
* Optional: only supported since clang >= 18
|
||||
*
|
||||
* gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
|
||||
* clang: https://github.com/llvm/llvm-project/pull/76348
|
||||
* clang: https://clang.llvm.org/docs/AttributeReference.html#counted-by-counted-by-or-null-sized-by-sized-by-or-null
|
||||
*
|
||||
* __bdos on clang < 19.1.2 can erroneously return 0:
|
||||
* https://github.com/llvm/llvm-project/pull/110497
|
||||
|
|
@ -383,6 +383,22 @@ struct ftrace_likely_data {
|
|||
# define __counted_by(member)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Runtime track number of objects pointed to by a pointer member for use by
|
||||
* CONFIG_FORTIFY_SOURCE and CONFIG_UBSAN_BOUNDS.
|
||||
*
|
||||
* Optional: only supported since gcc >= 16
|
||||
* Optional: only supported since clang >= 22
|
||||
*
|
||||
* gcc: https://gcc.gnu.org/pipermail/gcc-patches/2025-April/681727.html
|
||||
* clang: https://clang.llvm.org/docs/AttributeReference.html#counted-by-counted-by-or-null-sized-by-sized-by-or-null
|
||||
*/
|
||||
#ifdef CONFIG_CC_HAS_COUNTED_BY_PTR
|
||||
#define __counted_by_ptr(member) __attribute__((__counted_by__(member)))
|
||||
#else
|
||||
#define __counted_by_ptr(member)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Optional: only supported since gcc >= 15
|
||||
* Optional: not supported by Clang
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
#ifndef _LINUX_FORTIFY_STRING_H_
|
||||
#define _LINUX_FORTIFY_STRING_H_
|
||||
|
||||
#include <linux/bitfield.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/const.h>
|
||||
#include <linux/limits.h>
|
||||
|
|
@ -10,10 +9,9 @@
|
|||
#define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
|
||||
#define __RENAME(x) __asm__(#x)
|
||||
|
||||
#define FORTIFY_REASON_DIR(r) FIELD_GET(BIT(0), r)
|
||||
#define FORTIFY_REASON_FUNC(r) FIELD_GET(GENMASK(7, 1), r)
|
||||
#define FORTIFY_REASON(func, write) (FIELD_PREP(BIT(0), write) | \
|
||||
FIELD_PREP(GENMASK(7, 1), func))
|
||||
#define FORTIFY_REASON_DIR(r) ((r) & 1)
|
||||
#define FORTIFY_REASON_FUNC(r) ((r) >> 1)
|
||||
#define FORTIFY_REASON(func, write) ((func) << 1 | (write))
|
||||
|
||||
/* Overridden by KUnit tests. */
|
||||
#ifndef fortify_panic
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ struct simple_xattr {
|
|||
struct rb_node rb_node;
|
||||
char *name;
|
||||
size_t size;
|
||||
char value[];
|
||||
char value[] __counted_by(size);
|
||||
};
|
||||
|
||||
void simple_xattrs_init(struct simple_xattrs *xattrs);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ struct sockaddr_alg_new {
|
|||
|
||||
struct af_alg_iv {
|
||||
__u32 ivlen;
|
||||
__u8 iv[];
|
||||
__u8 iv[] __counted_by(ivlen);
|
||||
};
|
||||
|
||||
/* Socket options */
|
||||
|
|
|
|||
|
|
@ -72,6 +72,10 @@
|
|||
#define __counted_by_be(m)
|
||||
#endif
|
||||
|
||||
#ifndef __counted_by_ptr
|
||||
#define __counted_by_ptr(m)
|
||||
#endif
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#define __kernel_nonstring __nonstring
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -143,6 +143,13 @@ config CC_HAS_COUNTED_BY
|
|||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896
|
||||
default y if CC_IS_GCC && GCC_VERSION >= 150100
|
||||
|
||||
config CC_HAS_COUNTED_BY_PTR
|
||||
bool
|
||||
# supported since clang 22
|
||||
default y if CC_IS_CLANG && CLANG_VERSION >= 220000
|
||||
# supported since gcc 16.0.0
|
||||
default y if CC_IS_GCC && GCC_VERSION >= 160000
|
||||
|
||||
config CC_HAS_MULTIDIMENSIONAL_NONSTRING
|
||||
def_bool $(success,echo 'char tag[][4] __attribute__((__nonstring__)) = { };' | $(CC) $(CLANG_FLAGS) -x c - -c -o /dev/null -Werror)
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ config UBSAN_DIV_ZERO
|
|||
This option enables -fsanitize=integer-divide-by-zero which checks
|
||||
for integer division by zero. This is effectively redundant with the
|
||||
kernel's existing exception handling, though it can provide greater
|
||||
debugging information under CONFIG_UBSAN_REPORT_FULL.
|
||||
debugging information.
|
||||
|
||||
config UBSAN_UNREACHABLE
|
||||
bool "Perform checking for unreachable code"
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ WANT="__${FILE%%-*}"
|
|||
# Argument 2: Where to write the build log.
|
||||
OUT="$1"
|
||||
shift
|
||||
TMP="${OUT}.tmp"
|
||||
TMP="${OUT%/*}/.${OUT##*/}.tmp"
|
||||
|
||||
# Argument 3: Path to "nm" tool.
|
||||
NM="$1"
|
||||
|
|
@ -29,7 +29,7 @@ shift
|
|||
__cleanup() {
|
||||
rm -f "$TMP"
|
||||
}
|
||||
trap __cleanup EXIT
|
||||
trap __cleanup EXIT HUP INT QUIT TERM
|
||||
|
||||
# Function names in warnings are wrapped in backticks under UTF-8 locales.
|
||||
# Run the commands with LANG=C so that grep output will not change.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ EXCEPTION
|
|||
#CORRUPT_STACK Crashes entire system on success
|
||||
#CORRUPT_STACK_STRONG Crashes entire system on success
|
||||
ARRAY_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
|
||||
FAM_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
|
||||
PTR_BOUNDS call trace:|UBSAN: array-index-out-of-bounds
|
||||
CORRUPT_LIST_ADD list_add corruption
|
||||
CORRUPT_LIST_DEL list_del corruption
|
||||
STACK_GUARD_PAGE_LEADING
|
||||
|
|
|
|||
Loading…
Reference in New Issue