Skip to content

Commit

Permalink
Merge tag 'hardening-v5.20-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:

 - Fix Sparse warnings with randomizd kstack (GONG, Ruiqi)

 - Replace uintptr_t with unsigned long in usercopy (Jason A. Donenfeld)

 - Fix Clang -Wforward warning in LKDTM (Justin Stitt)

 - Fix comment to correctly refer to STRICT_DEVMEM (Lukas Bulwahn)

 - Introduce dm-verity binding logic to LoadPin LSM (Matthias Kaehlcke)

 - Clean up warnings and overflow and KASAN tests (Kees Cook)

* tag 'hardening-v5.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  dm: verity-loadpin: Drop use of dm_table_get_num_targets()
  kasan: test: Silence GCC 12 warnings
  drivers: lkdtm: fix clang -Wformat warning
  x86: mm: refer to the intended config STRICT_DEVMEM in a comment
  dm: verity-loadpin: Use CONFIG_SECURITY_LOADPIN_VERITY for conditional compilation
  LoadPin: Enable loading from trusted dm-verity devices
  dm: Add verity helpers for LoadPin
  stack: Declare {randomize_,}kstack_offset to fix Sparse warnings
  lib: overflow: Do not define 64-bit tests on 32-bit
  MAINTAINERS: Add a general "kernel hardening" section
  usercopy: use unsigned long instead of uintptr_t
  • Loading branch information
torvalds committed Aug 2, 2022
2 parents d7b767b + 27603a6 commit 6991a56
Show file tree
Hide file tree
Showing 14 changed files with 379 additions and 8 deletions.
21 changes: 17 additions & 4 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -4998,7 +4998,7 @@ R: Nick Desaulniers <[email protected]>
L: [email protected]
S: Supported
B: https://github.com/ClangBuiltLinux/linux/issues
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/clang/features
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: include/linux/cfi.h
F: kernel/cfi.c

Expand Down Expand Up @@ -7909,6 +7909,7 @@ FORTIFY_SOURCE
M: Kees Cook <[email protected]>
L: [email protected]
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: include/linux/fortify-string.h
F: lib/test_fortify/*
F: scripts/test_fortify.sh
Expand Down Expand Up @@ -8351,6 +8352,7 @@ GCC PLUGINS
M: Kees Cook <[email protected]>
L: [email protected]
S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: Documentation/kbuild/gcc-plugins.rst
F: scripts/Makefile.gcc-plugins
F: scripts/gcc-plugins/
Expand Down Expand Up @@ -10878,6 +10880,17 @@ F: scripts/mk*
F: scripts/mod/
F: scripts/package/

KERNEL HARDENING (not covered by other areas)
M: Kees Cook <[email protected]>
L: [email protected]
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: include/linux/overflow.h
F: include/linux/randomize_kstack.h
F: mm/usercopy.c
K: \b(add|choose)_random_kstack_offset\b
K: \b__check_(object_size|heap_object)\b

KERNEL JANITORS
L: [email protected]
S: Odd Fixes
Expand Down Expand Up @@ -11688,7 +11701,7 @@ F: drivers/media/usb/dvb-usb-v2/lmedm04*
LOADPIN SECURITY MODULE
M: Kees Cook <[email protected]>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git lsm/loadpin
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: Documentation/admin-guide/LSM/LoadPin.rst
F: security/loadpin/

Expand Down Expand Up @@ -18026,7 +18039,7 @@ M: Kees Cook <[email protected]>
R: Andy Lutomirski <[email protected]>
R: Will Drewry <[email protected]>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git seccomp
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/seccomp
F: Documentation/userspace-api/seccomp_filter.rst
F: include/linux/seccomp.h
F: include/uapi/linux/seccomp.h
Expand Down Expand Up @@ -22174,7 +22187,7 @@ F: include/linux/yam.h
YAMA SECURITY MODULE
M: Kees Cook <[email protected]>
S: Supported
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git yama/tip
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
F: Documentation/admin-guide/LSM/Yama.rst
F: security/yama/

Expand Down
1 change: 1 addition & 0 deletions drivers/md/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ obj-$(CONFIG_DM_LOG_WRITES) += dm-log-writes.o
obj-$(CONFIG_DM_INTEGRITY) += dm-integrity.o
obj-$(CONFIG_DM_ZONED) += dm-zoned.o
obj-$(CONFIG_DM_WRITECACHE) += dm-writecache.o
obj-$(CONFIG_SECURITY_LOADPIN_VERITY) += dm-verity-loadpin.o

ifeq ($(CONFIG_DM_INIT),y)
dm-mod-objs += dm-init.o
Expand Down
75 changes: 75 additions & 0 deletions drivers/md/dm-verity-loadpin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-2.0-only

#include <linux/list.h>
#include <linux/kernel.h>
#include <linux/dm-verity-loadpin.h>

#include "dm.h"
#include "dm-core.h"
#include "dm-verity.h"

#define DM_MSG_PREFIX "verity-loadpin"

LIST_HEAD(dm_verity_loadpin_trusted_root_digests);

static bool is_trusted_verity_target(struct dm_target *ti)
{
u8 *root_digest;
unsigned int digest_size;
struct dm_verity_loadpin_trusted_root_digest *trd;
bool trusted = false;

if (!dm_is_verity_target(ti))
return false;

if (dm_verity_get_root_digest(ti, &root_digest, &digest_size))
return false;

list_for_each_entry(trd, &dm_verity_loadpin_trusted_root_digests, node) {
if ((trd->len == digest_size) &&
!memcmp(trd->data, root_digest, digest_size)) {
trusted = true;
break;
}
}

kfree(root_digest);

return trusted;
}

/*
* Determines whether the file system of a superblock is located on
* a verity device that is trusted by LoadPin.
*/
bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev)
{
struct mapped_device *md;
struct dm_table *table;
struct dm_target *ti;
int srcu_idx;
bool trusted = false;

if (list_empty(&dm_verity_loadpin_trusted_root_digests))
return false;

md = dm_get_md(bdev->bd_dev);
if (!md)
return false;

table = dm_get_live_table(md, &srcu_idx);

if (table->num_targets != 1)
goto out;

ti = dm_table_get_target(table, 0);

if (is_trusted_verity_target(ti))
trusted = true;

out:
dm_put_live_table(md, srcu_idx);
dm_put(md);

return trusted;
}
33 changes: 32 additions & 1 deletion drivers/md/dm-verity-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <linux/module.h>
#include <linux/reboot.h>
#include <linux/scatterlist.h>
#include <linux/string.h>

#define DM_MSG_PREFIX "verity"

Expand Down Expand Up @@ -1309,10 +1310,40 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
return r;
}

/*
* Check whether a DM target is a verity target.
*/
bool dm_is_verity_target(struct dm_target *ti)
{
return ti->type->module == THIS_MODULE;
}

/*
* Get the root digest of a verity target.
*
* Returns a copy of the root digest, the caller is responsible for
* freeing the memory of the digest.
*/
int dm_verity_get_root_digest(struct dm_target *ti, u8 **root_digest, unsigned int *digest_size)
{
struct dm_verity *v = ti->private;

if (!dm_is_verity_target(ti))
return -EINVAL;

*root_digest = kmemdup(v->root_digest, v->digest_size, GFP_KERNEL);
if (*root_digest == NULL)
return -ENOMEM;

*digest_size = v->digest_size;

return 0;
}

static struct target_type verity_target = {
.name = "verity",
.features = DM_TARGET_IMMUTABLE,
.version = {1, 8, 0},
.version = {1, 8, 1},
.module = THIS_MODULE,
.ctr = verity_ctr,
.dtr = verity_dtr,
Expand Down
4 changes: 4 additions & 0 deletions drivers/md/dm-verity.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,8 @@ extern int verity_hash(struct dm_verity *v, struct ahash_request *req,
extern int verity_hash_for_block(struct dm_verity *v, struct dm_verity_io *io,
sector_t block, u8 *digest, bool *is_zero);

extern bool dm_is_verity_target(struct dm_target *ti);
extern int dm_verity_get_root_digest(struct dm_target *ti, u8 **root_digest,
unsigned int *digest_size);

#endif /* DM_VERITY_H */
2 changes: 1 addition & 1 deletion drivers/misc/lkdtm/bugs.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct lkdtm_list {
#if defined(CONFIG_FRAME_WARN) && (CONFIG_FRAME_WARN > 0)
#define REC_STACK_SIZE (_AC(CONFIG_FRAME_WARN, UL) / 2)
#else
#define REC_STACK_SIZE (THREAD_SIZE / 8)
#define REC_STACK_SIZE (THREAD_SIZE / 8UL)
#endif
#define REC_NUM_DEFAULT ((THREAD_SIZE / REC_STACK_SIZE) * 2)

Expand Down
27 changes: 27 additions & 0 deletions include/linux/dm-verity-loadpin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */

#ifndef __LINUX_DM_VERITY_LOADPIN_H
#define __LINUX_DM_VERITY_LOADPIN_H

#include <linux/list.h>

struct block_device;

extern struct list_head dm_verity_loadpin_trusted_root_digests;

struct dm_verity_loadpin_trusted_root_digest {
struct list_head node;
unsigned int len;
u8 data[];
};

#if IS_ENABLED(CONFIG_SECURITY_LOADPIN_VERITY)
bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev);
#else
static inline bool dm_verity_loadpin_is_bdev_trusted(struct block_device *bdev)
{
return false;
}
#endif

#endif /* __LINUX_DM_VERITY_LOADPIN_H */
22 changes: 22 additions & 0 deletions include/uapi/linux/loadpin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
* Copyright (c) 2022, Google LLC
*/

#ifndef _UAPI_LINUX_LOOP_LOADPIN_H
#define _UAPI_LINUX_LOOP_LOADPIN_H

#define LOADPIN_IOC_MAGIC 'L'

/**
* LOADPIN_IOC_SET_TRUSTED_VERITY_DIGESTS - Set up the root digests of verity devices
* that loadpin should trust.
*
* Takes a file descriptor from which to read the root digests of trusted verity devices. The file
* is expected to contain a list of digests in ASCII format, with one line per digest. The ioctl
* must be issued on the securityfs attribute 'loadpin/dm-verity' (which can be typically found
* under /sys/kernel/security/loadpin/dm-verity).
*/
#define LOADPIN_IOC_SET_TRUSTED_VERITY_DIGESTS _IOW(LOADPIN_IOC_MAGIC, 0x00, unsigned int)

#endif /* _UAPI_LINUX_LOOP_LOADPIN_H */
1 change: 1 addition & 0 deletions init/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
#include <linux/kcsan.h>
#include <linux/init_syscalls.h>
#include <linux/stackdepot.h>
#include <linux/randomize_kstack.h>
#include <net/net_namespace.h>

#include <asm/io.h>
Expand Down
6 changes: 6 additions & 0 deletions lib/overflow_kunit.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ DEFINE_TEST_ARRAY(u32) = {
{-4U, 5U, 1U, -9U, -20U, true, false, true},
};

#if BITS_PER_LONG == 64
DEFINE_TEST_ARRAY(u64) = {
{0, 0, 0, 0, 0, false, false, false},
{1, 1, 2, 0, 1, false, false, false},
Expand All @@ -114,6 +115,7 @@ DEFINE_TEST_ARRAY(u64) = {
false, true, false},
{-15ULL, 10ULL, -5ULL, -25ULL, -150ULL, false, false, true},
};
#endif

DEFINE_TEST_ARRAY(s8) = {
{0, 0, 0, 0, 0, false, false, false},
Expand Down Expand Up @@ -188,6 +190,8 @@ DEFINE_TEST_ARRAY(s32) = {
{S32_MIN, S32_MIN, 0, 0, 0, true, false, true},
{S32_MAX, S32_MAX, -2, 0, 1, true, false, true},
};

#if BITS_PER_LONG == 64
DEFINE_TEST_ARRAY(s64) = {
{0, 0, 0, 0, 0, false, false, false},

Expand Down Expand Up @@ -216,6 +220,7 @@ DEFINE_TEST_ARRAY(s64) = {
{-128, -1, -129, -127, 128, false, false, false},
{0, -S64_MAX, -S64_MAX, S64_MAX, 0, false, false, false},
};
#endif

#define check_one_op(t, fmt, op, sym, a, b, r, of) do { \
t _r; \
Expand Down Expand Up @@ -650,6 +655,7 @@ static struct kunit_case overflow_test_cases[] = {
KUNIT_CASE(s16_overflow_test),
KUNIT_CASE(u32_overflow_test),
KUNIT_CASE(s32_overflow_test),
/* Clang 13 and earlier generate unwanted libcalls on 32-bit. */
#if BITS_PER_LONG == 64
KUNIT_CASE(u64_overflow_test),
KUNIT_CASE(s64_overflow_test),
Expand Down
10 changes: 10 additions & 0 deletions lib/test_kasan.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ static void kmalloc_oob_right(struct kunit *test)
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);

OPTIMIZER_HIDE_VAR(ptr);
/*
* An unaligned access past the requested kmalloc size.
* Only generic KASAN can precisely detect these.
Expand Down Expand Up @@ -159,6 +160,7 @@ static void kmalloc_oob_left(struct kunit *test)
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);

OPTIMIZER_HIDE_VAR(ptr);
KUNIT_EXPECT_KASAN_FAIL(test, *ptr = *(ptr - 1));
kfree(ptr);
}
Expand All @@ -171,6 +173,7 @@ static void kmalloc_node_oob_right(struct kunit *test)
ptr = kmalloc_node(size, GFP_KERNEL, 0);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);

OPTIMIZER_HIDE_VAR(ptr);
KUNIT_EXPECT_KASAN_FAIL(test, ptr[0] = ptr[size]);
kfree(ptr);
}
Expand All @@ -191,6 +194,7 @@ static void kmalloc_pagealloc_oob_right(struct kunit *test)
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);

OPTIMIZER_HIDE_VAR(ptr);
KUNIT_EXPECT_KASAN_FAIL(test, ptr[size + OOB_TAG_OFF] = 0);

kfree(ptr);
Expand Down Expand Up @@ -271,6 +275,7 @@ static void kmalloc_large_oob_right(struct kunit *test)
ptr = kmalloc(size, GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);

OPTIMIZER_HIDE_VAR(ptr);
KUNIT_EXPECT_KASAN_FAIL(test, ptr[size] = 0);
kfree(ptr);
}
Expand Down Expand Up @@ -410,6 +415,8 @@ static void kmalloc_oob_16(struct kunit *test)
ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr2);

OPTIMIZER_HIDE_VAR(ptr1);
OPTIMIZER_HIDE_VAR(ptr2);
KUNIT_EXPECT_KASAN_FAIL(test, *ptr1 = *ptr2);
kfree(ptr1);
kfree(ptr2);
Expand Down Expand Up @@ -756,6 +763,8 @@ static void ksize_unpoisons_memory(struct kunit *test)
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
real_size = ksize(ptr);

OPTIMIZER_HIDE_VAR(ptr);

/* This access shouldn't trigger a KASAN report. */
ptr[size] = 'x';

Expand All @@ -778,6 +787,7 @@ static void ksize_uaf(struct kunit *test)
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ptr);
kfree(ptr);

OPTIMIZER_HIDE_VAR(ptr);
KUNIT_EXPECT_KASAN_FAIL(test, ksize(ptr));
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[0]);
KUNIT_EXPECT_KASAN_FAIL(test, ((volatile char *)ptr)[size]);
Expand Down
2 changes: 1 addition & 1 deletion mm/usercopy.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ static inline void check_bogus_address(const unsigned long ptr, unsigned long n,
static inline void check_heap_object(const void *ptr, unsigned long n,
bool to_user)
{
uintptr_t addr = (uintptr_t)ptr;
unsigned long addr = (unsigned long)ptr;
unsigned long offset;
struct folio *folio;

Expand Down
Loading

0 comments on commit 6991a56

Please sign in to comment.