Skip to content

Commit

Permalink
Merge tag 'hardening-v6.3-rc1' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/kees/linux

Pull hardening updates from Kees Cook:
 "Beyond some specific LoadPin, UBSAN, and fortify features, there are
  other fixes scattered around in various subsystems where maintainers
  were okay with me carrying them in my tree or were non-responsive but
  the patches were reviewed by others:

   - Replace 0-length and 1-element arrays with flexible arrays in
     various subsystems (Paulo Miguel Almeida, Stephen Rothwell, Kees
     Cook)

   - randstruct: Disable Clang 15 support (Eric Biggers)

   - GCC plugins: Drop -std=gnu++11 flag (Sam James)

   - strpbrk(): Refactor to use strchr() (Andy Shevchenko)

   - LoadPin LSM: Allow root filesystem switching when non-enforcing

   - fortify: Use dynamic object size hints when available

   - ext4: Fix CFI function prototype mismatch

   - Nouveau: Fix DP buffer size arguments

   - hisilicon: Wipe entire crypto DMA pool on error

   - coda: Fully allocate sig_inputArgs

   - UBSAN: Improve arm64 trap code reporting

   - copy_struct_from_user(): Add minimum bounds check on kernel buffer
     size"

* tag 'hardening-v6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  randstruct: disable Clang 15 support
  uaccess: Add minimum bounds check on kernel buffer size
  arm64: Support Clang UBSAN trap codes for better reporting
  coda: Avoid partial allocation of sig_inputArgs
  gcc-plugins: drop -std=gnu++11 to fix GCC 13 build
  lib/string: Use strchr() in strpbrk()
  crypto: hisilicon: Wipe entire pool on error
  net/i40e: Replace 0-length array with flexible array
  io_uring: Replace 0-length array with flexible array
  ext4: Fix function prototype mismatch for ext4_feat_ktype
  i915/gvt: Replace one-element array with flexible-array member
  drm/nouveau/disp: Fix nvif_outp_acquire_dp() argument size
  LoadPin: Allow filesystem switch when not enforcing
  LoadPin: Move pin reporting cleanly out of locking
  LoadPin: Refactor sysctl initialization
  LoadPin: Refactor read-only check into a helper
  ARM: ixp4xx: Replace 0-length arrays with flexible arrays
  fortify: Use __builtin_dynamic_object_size() when available
  rxrpc: replace zero-lenth array with DECLARE_FLEX_ARRAY() helper
  • Loading branch information
torvalds committed Feb 21, 2023
2 parents 902d9fc + 78f7a3f commit 4a7d37e
Show file tree
Hide file tree
Showing 24 changed files with 229 additions and 60 deletions.
3 changes: 3 additions & 0 deletions arch/arm64/include/asm/brk-imm.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
* 0x401: for compile time BRK instruction
* 0x800: kernel-mode BUG() and WARN() traps
* 0x9xx: tag-based KASAN trap (allowed values 0x900 - 0x9ff)
* 0x55xx: Undefined Behavior Sanitizer traps ('U' << 8)
* 0x8xxx: Control-Flow Integrity traps
*/
#define KPROBES_BRK_IMM 0x004
Expand All @@ -28,6 +29,8 @@
#define BUG_BRK_IMM 0x800
#define KASAN_BRK_IMM 0x900
#define KASAN_BRK_MASK 0x0ff
#define UBSAN_BRK_IMM 0x5500
#define UBSAN_BRK_MASK 0x00ff

#define CFI_BRK_IMM_TARGET GENMASK(4, 0)
#define CFI_BRK_IMM_TYPE GENMASK(9, 5)
Expand Down
21 changes: 21 additions & 0 deletions arch/arm64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/syscalls.h>
#include <linux/mm_types.h>
#include <linux/kasan.h>
#include <linux/ubsan.h>
#include <linux/cfi.h>

#include <asm/atomic.h>
Expand Down Expand Up @@ -1074,6 +1075,19 @@ static struct break_hook kasan_break_hook = {
};
#endif

#ifdef CONFIG_UBSAN_TRAP
static int ubsan_handler(struct pt_regs *regs, unsigned long esr)
{
die(report_ubsan_failure(regs, esr & UBSAN_BRK_MASK), regs, esr);
return DBG_HOOK_HANDLED;
}

static struct break_hook ubsan_break_hook = {
.fn = ubsan_handler,
.imm = UBSAN_BRK_IMM,
.mask = UBSAN_BRK_MASK,
};
#endif

#define esr_comment(esr) ((esr) & ESR_ELx_BRK64_ISS_COMMENT_MASK)

Expand All @@ -1091,6 +1105,10 @@ int __init early_brk64(unsigned long addr, unsigned long esr,
#ifdef CONFIG_KASAN_SW_TAGS
if ((esr_comment(esr) & ~KASAN_BRK_MASK) == KASAN_BRK_IMM)
return kasan_handler(regs, esr) != DBG_HOOK_HANDLED;
#endif
#ifdef CONFIG_UBSAN_TRAP
if ((esr_comment(esr) & ~UBSAN_BRK_MASK) == UBSAN_BRK_IMM)
return ubsan_handler(regs, esr) != DBG_HOOK_HANDLED;
#endif
return bug_handler(regs, esr) != DBG_HOOK_HANDLED;
}
Expand All @@ -1104,6 +1122,9 @@ void __init trap_init(void)
register_kernel_break_hook(&fault_break_hook);
#ifdef CONFIG_KASAN_SW_TAGS
register_kernel_break_hook(&kasan_break_hook);
#endif
#ifdef CONFIG_UBSAN_TRAP
register_kernel_break_hook(&ubsan_break_hook);
#endif
debug_traps_init();
}
3 changes: 1 addition & 2 deletions drivers/crypto/hisilicon/sgl.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,9 +124,8 @@ struct hisi_acc_sgl_pool *hisi_acc_create_sgl_pool(struct device *dev,
for (j = 0; j < i; j++) {
dma_free_coherent(dev, block_size, block[j].sgl,
block[j].sgl_dma);
memset(block + j, 0, sizeof(*block));
}
kfree(pool);
kfree_sensitive(pool);
return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL_GPL(hisi_acc_create_sgl_pool);
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/i915/gvt/firmware.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ struct gvt_firmware_header {
u64 cfg_space_offset; /* offset in the file */
u64 mmio_size;
u64 mmio_offset; /* offset in the file */
unsigned char data[1];
unsigned char data[];
};

#define dev_to_drm_minor(d) dev_get_drvdata((d))
Expand Down Expand Up @@ -77,7 +77,7 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
unsigned long size, crc32_start;
int ret;

size = sizeof(*h) + info->mmio_size + info->cfg_space_size;
size = offsetof(struct gvt_firmware_header, data) + info->mmio_size + info->cfg_space_size;
firmware = vzalloc(size);
if (!firmware)
return -ENOMEM;
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/nouveau/include/nvif/outp.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define __NVIF_OUTP_H__
#include <nvif/object.h>
#include <nvif/if0012.h>
#include <drm/display/drm_dp.h>
struct nvif_disp;

struct nvif_outp {
Expand All @@ -21,7 +22,7 @@ int nvif_outp_acquire_rgb_crt(struct nvif_outp *);
int nvif_outp_acquire_tmds(struct nvif_outp *, int head,
bool hdmi, u8 max_ac_packet, u8 rekey, u8 scdc, bool hda);
int nvif_outp_acquire_lvds(struct nvif_outp *, bool dual, bool bpc8);
int nvif_outp_acquire_dp(struct nvif_outp *, u8 dpcd[16],
int nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
int link_nr, int link_bw, bool hda, bool mst);
void nvif_outp_release(struct nvif_outp *);
int nvif_outp_infoframe(struct nvif_outp *, u8 type, struct nvif_outp_infoframe_v0 *, u32 size);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/nvif/outp.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ nvif_outp_acquire(struct nvif_outp *outp, u8 proto, struct nvif_outp_acquire_v0
}

int
nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[16],
nvif_outp_acquire_dp(struct nvif_outp *outp, u8 dpcd[DP_RECEIVER_CAP_SIZE],
int link_nr, int link_bw, bool hda, bool mst)
{
struct nvif_outp_acquire_v0 args;
Expand Down
1 change: 1 addition & 0 deletions drivers/misc/lkdtm/heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ static void lkdtm_VMALLOC_LINEAR_OVERFLOW(void)
char *one, *two;

one = vzalloc(PAGE_SIZE);
OPTIMIZER_HIDE_VAR(one);
two = vzalloc(PAGE_SIZE);

pr_info("Attempting vmalloc linear overflow ...\n");
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/intel/i40e/i40e.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ enum i40e_interrupt_policy {

struct i40e_lump_tracking {
u16 num_entries;
u16 list[0];
u16 list[];
#define I40E_PILE_VALID_BIT 0x8000
#define I40E_IWARP_IRQ_PILE_ID (I40E_PILE_VALID_BIT - 2)
};
Expand Down
6 changes: 3 additions & 3 deletions drivers/soc/ixp4xx/ixp4xx-npe.c
Original file line number Diff line number Diff line change
Expand Up @@ -519,15 +519,15 @@ int npe_load_firmware(struct npe *npe, const char *name, struct device *dev)
u32 id;
u32 size;
union {
u32 data[0];
struct dl_block blocks[0];
DECLARE_FLEX_ARRAY(u32, data);
DECLARE_FLEX_ARRAY(struct dl_block, blocks);
};
} *image;

struct dl_codeblock {
u32 npe_addr;
u32 size;
u32 data[0];
u32 data[];
} *cb;

int i, j, err, data_size, instr_size, blocks, table_end;
Expand Down
2 changes: 1 addition & 1 deletion fs/coda/upcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,7 +791,7 @@ static int coda_upcall(struct venus_comm *vcp,
sig_req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
if (!sig_req) goto exit;

sig_inputArgs = kvzalloc(sizeof(struct coda_in_hdr), GFP_KERNEL);
sig_inputArgs = kvzalloc(sizeof(*sig_inputArgs), GFP_KERNEL);
if (!sig_inputArgs) {
kfree(sig_req);
goto exit;
Expand Down
7 changes: 6 additions & 1 deletion fs/ext4/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,11 @@ static void ext4_sb_release(struct kobject *kobj)
complete(&sbi->s_kobj_unregister);
}

static void ext4_feat_release(struct kobject *kobj)
{
kfree(kobj);
}

static const struct sysfs_ops ext4_attr_ops = {
.show = ext4_attr_show,
.store = ext4_attr_store,
Expand All @@ -505,7 +510,7 @@ static struct kobj_type ext4_sb_ktype = {
static struct kobj_type ext4_feat_ktype = {
.default_groups = ext4_feat_groups,
.sysfs_ops = &ext4_attr_ops,
.release = (void (*)(struct kobject *))kfree,
.release = ext4_feat_release,
};

void ext4_notify_error_sysfs(struct ext4_sb_info *sbi)
Expand Down
5 changes: 5 additions & 0 deletions include/linux/compiler_attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,11 @@
*
* clang: https://clang.llvm.org/docs/AttributeReference.html#pass-object-size-pass-dynamic-object-size
*/
#if __has_attribute(__pass_dynamic_object_size__)
# define __pass_dynamic_object_size(type) __attribute__((__pass_dynamic_object_size__(type)))
#else
# define __pass_dynamic_object_size(type)
#endif
#if __has_attribute(__pass_object_size__)
# define __pass_object_size(type) __attribute__((__pass_object_size__(type)))
#else
Expand Down
7 changes: 7 additions & 0 deletions include/linux/fortify-string.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,17 @@ extern char *__underlying_strncpy(char *p, const char *q, __kernel_size_t size)
* size, rather than struct size), but there remain some stragglers using
* type 0 that will be converted in the future.
*/
#if __has_builtin(__builtin_dynamic_object_size)
#define POS __pass_dynamic_object_size(1)
#define POS0 __pass_dynamic_object_size(0)
#define __struct_size(p) __builtin_dynamic_object_size(p, 0)
#define __member_size(p) __builtin_dynamic_object_size(p, 1)
#else
#define POS __pass_object_size(1)
#define POS0 __pass_object_size(0)
#define __struct_size(p) __builtin_object_size(p, 0)
#define __member_size(p) __builtin_object_size(p, 1)
#endif

#define __compiletime_lessthan(bounds, length) ( \
__builtin_constant_p((bounds) < (length)) && \
Expand Down
4 changes: 4 additions & 0 deletions include/linux/uaccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,10 @@ copy_struct_from_user(void *dst, size_t ksize, const void __user *src,
size_t size = min(ksize, usize);
size_t rest = max(ksize, usize) - size;

/* Double check if ksize is larger than a known object size. */
if (WARN_ON_ONCE(ksize > __builtin_object_size(dst, 1)))
return -E2BIG;

/* Deal with trailing bytes. */
if (usize < ksize) {
memset(dst + size, 0, rest);
Expand Down
9 changes: 9 additions & 0 deletions include/linux/ubsan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_UBSAN_H
#define _LINUX_UBSAN_H

#ifdef CONFIG_UBSAN_TRAP
const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type);
#endif

#endif
2 changes: 1 addition & 1 deletion include/uapi/linux/io_uring.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ struct io_uring_buf_ring {
__u16 resv3;
__u16 tail;
};
struct io_uring_buf bufs[0];
__DECLARE_FLEX_ARRAY(struct io_uring_buf, bufs);
};
};

Expand Down
2 changes: 0 additions & 2 deletions lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -340,9 +340,7 @@ quiet_cmd_build_OID_registry = GEN $@
clean-files += oid_registry_data.c

obj-$(CONFIG_UCS2_STRING) += ucs2_string.o
ifneq ($(CONFIG_UBSAN_TRAP),y)
obj-$(CONFIG_UBSAN) += ubsan.o
endif

UBSAN_SANITIZE_ubsan.o := n
KASAN_SANITIZE_ubsan.o := n
Expand Down
10 changes: 4 additions & 6 deletions lib/string.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,13 +480,11 @@ EXPORT_SYMBOL(strcspn);
*/
char *strpbrk(const char *cs, const char *ct)
{
const char *sc1, *sc2;
const char *sc;

for (sc1 = cs; *sc1 != '\0'; ++sc1) {
for (sc2 = ct; *sc2 != '\0'; ++sc2) {
if (*sc1 == *sc2)
return (char *)sc1;
}
for (sc = cs; *sc != '\0'; ++sc) {
if (strchr(ct, *sc))
return (char *)sc;
}
return NULL;
}
Expand Down
68 changes: 68 additions & 0 deletions lib/ubsan.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,76 @@
#include <linux/types.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#include <linux/ubsan.h>
#include <kunit/test-bug.h>

#include "ubsan.h"

#ifdef CONFIG_UBSAN_TRAP
/*
* Only include matches for UBSAN checks that are actually compiled in.
* The mappings of struct SanitizerKind (the -fsanitize=xxx args) to
* enum SanitizerHandler (the traps) in Clang is in clang/lib/CodeGen/.
*/
const char *report_ubsan_failure(struct pt_regs *regs, u32 check_type)
{
switch (check_type) {
#ifdef CONFIG_UBSAN_BOUNDS
/*
* SanitizerKind::ArrayBounds and SanitizerKind::LocalBounds
* emit SanitizerHandler::OutOfBounds.
*/
case ubsan_out_of_bounds:
return "UBSAN: array index out of bounds";
#endif
#ifdef CONFIG_UBSAN_SHIFT
/*
* SanitizerKind::ShiftBase and SanitizerKind::ShiftExponent
* emit SanitizerHandler::ShiftOutOfBounds.
*/
case ubsan_shift_out_of_bounds:
return "UBSAN: shift out of bounds";
#endif
#ifdef CONFIG_UBSAN_DIV_ZERO
/*
* SanitizerKind::IntegerDivideByZero emits
* SanitizerHandler::DivremOverflow.
*/
case ubsan_divrem_overflow:
return "UBSAN: divide/remainder overflow";
#endif
#ifdef CONFIG_UBSAN_UNREACHABLE
/*
* SanitizerKind::Unreachable emits
* SanitizerHandler::BuiltinUnreachable.
*/
case ubsan_builtin_unreachable:
return "UBSAN: unreachable code";
#endif
#if defined(CONFIG_UBSAN_BOOL) || defined(CONFIG_UBSAN_ENUM)
/*
* SanitizerKind::Bool and SanitizerKind::Enum emit
* SanitizerHandler::LoadInvalidValue.
*/
case ubsan_load_invalid_value:
return "UBSAN: loading invalid value";
#endif
#ifdef CONFIG_UBSAN_ALIGNMENT
/*
* SanitizerKind::Alignment emits SanitizerHandler::TypeMismatch
* or SanitizerHandler::AlignmentAssumption.
*/
case ubsan_alignment_assumption:
return "UBSAN: alignment assumption";
case ubsan_type_mismatch:
return "UBSAN: type mismatch";
#endif
default:
return "UBSAN: unrecognized failure code";
}
}

#else
static const char * const type_check_kinds[] = {
"load of",
"store to",
Expand Down Expand Up @@ -387,3 +453,5 @@ void __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
ubsan_epilogue();
}
EXPORT_SYMBOL(__ubsan_handle_alignment_assumption);

#endif /* !CONFIG_UBSAN_TRAP */
32 changes: 32 additions & 0 deletions lib/ubsan.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,38 @@
#ifndef _LIB_UBSAN_H
#define _LIB_UBSAN_H

/*
* ABI defined by Clang's UBSAN enum SanitizerHandler:
* https://github.com/llvm/llvm-project/blob/release/16.x/clang/lib/CodeGen/CodeGenFunction.h#L113
*/
enum ubsan_checks {
ubsan_add_overflow,
ubsan_builtin_unreachable,
ubsan_cfi_check_fail,
ubsan_divrem_overflow,
ubsan_dynamic_type_cache_miss,
ubsan_float_cast_overflow,
ubsan_function_type_mismatch,
ubsan_implicit_conversion,
ubsan_invalid_builtin,
ubsan_invalid_objc_cast,
ubsan_load_invalid_value,
ubsan_missing_return,
ubsan_mul_overflow,
ubsan_negate_overflow,
ubsan_nullability_arg,
ubsan_nullability_return,
ubsan_nonnull_arg,
ubsan_nonnull_return,
ubsan_out_of_bounds,
ubsan_pointer_overflow,
ubsan_shift_out_of_bounds,
ubsan_sub_overflow,
ubsan_type_mismatch,
ubsan_alignment_assumption,
ubsan_vla_bound_not_positive,
};

enum {
type_kind_int = 0,
type_kind_float = 1,
Expand Down
Loading

0 comments on commit 4a7d37e

Please sign in to comment.