Skip to content

Commit

Permalink
Merge tag 'hardening-v6.2-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 kernel hardening updates from Kees Cook:

 - Convert flexible array members, fix -Wstringop-overflow warnings, and
   fix KCFI function type mismatches that went ignored by maintainers
   (Gustavo A. R. Silva, Nathan Chancellor, Kees Cook)

 - Remove the remaining side-effect users of ksize() by converting
   dma-buf, btrfs, and coredump to using kmalloc_size_roundup(), add
   more __alloc_size attributes, and introduce full testing of all
   allocator functions. Finally remove the ksize() side-effect so that
   each allocation-aware checker can finally behave without exceptions

 - Introduce oops_limit (default 10,000) and warn_limit (default off) to
   provide greater granularity of control for panic_on_oops and
   panic_on_warn (Jann Horn, Kees Cook)

 - Introduce overflows_type() and castable_to_type() helpers for cleaner
   overflow checking

 - Improve code generation for strscpy() and update str*() kern-doc

 - Convert strscpy and sigphash tests to KUnit, and expand memcpy tests

 - Always use a non-NULL argument for prepare_kernel_cred()

 - Disable structleak plugin in FORTIFY KUnit test (Anders Roxell)

 - Adjust orphan linker section checking to respect CONFIG_WERROR (Xin
   Li)

 - Make sure siginfo is cleared for forced SIGKILL (haifeng.xu)

 - Fix um vs FORTIFY warnings for always-NULL arguments

* tag 'hardening-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (31 commits)
  ksmbd: replace one-element arrays with flexible-array members
  hpet: Replace one-element array with flexible-array member
  um: virt-pci: Avoid GCC non-NULL warning
  signal: Initialize the info in ksignal
  lib: fortify_kunit: build without structleak plugin
  panic: Expose "warn_count" to sysfs
  panic: Introduce warn_limit
  panic: Consolidate open-coded panic_on_warn checks
  exit: Allow oops_limit to be disabled
  exit: Expose "oops_count" to sysfs
  exit: Put an upper limit on how often we can oops
  panic: Separate sysctl logic from CONFIG_SMP
  mm/pgtable: Fix multiple -Wstringop-overflow warnings
  mm: Make ksize() a reporting-only function
  kunit/fortify: Validate __alloc_size attribute results
  drm/sti: Fix return type of sti_{dvo,hda,hdmi}_connector_mode_valid()
  drm/fsl-dcu: Fix return type of fsl_dcu_drm_connector_mode_valid()
  driver core: Add __alloc_size hint to devm allocators
  overflow: Introduce overflows_type() and castable_to_type()
  coredump: Proactively round up to kmalloc bucket size
  ...
  • Loading branch information
torvalds committed Dec 14, 2022
2 parents ad76bf1 + d272e01 commit 48ea09c
Show file tree
Hide file tree
Showing 61 changed files with 1,533 additions and 463 deletions.
6 changes: 6 additions & 0 deletions Documentation/ABI/testing/sysfs-kernel-oops_count
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
What: /sys/kernel/oops_count
Date: November 2022
KernelVersion: 6.2.0
Contact: Linux Kernel Hardening List <[email protected]>
Description:
Shows how many times the system has Oopsed since last boot.
6 changes: 6 additions & 0 deletions Documentation/ABI/testing/sysfs-kernel-warn_count
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
What: /sys/kernel/oops_count
Date: November 2022
KernelVersion: 6.2.0
Contact: Linux Kernel Hardening List <[email protected]>
Description:
Shows how many times the system has Warned since last boot.
19 changes: 19 additions & 0 deletions Documentation/admin-guide/sysctl/kernel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,15 @@ This is the default behavior.
an oops event is detected.


oops_limit
==========

Number of kernel oopses after which the kernel should panic when
``panic_on_oops`` is not set. Setting this to 0 disables checking
the count. Setting this to 1 has the same effect as setting
``panic_on_oops=1``. The default value is 10000.


osrelease, ostype & version
===========================

Expand Down Expand Up @@ -1526,6 +1535,16 @@ entry will default to 2 instead of 0.
2 Unprivileged calls to ``bpf()`` are disabled
= =============================================================


warn_limit
==========

Number of kernel warnings after which the kernel should panic when
``panic_on_warn`` is not set. Setting this to 0 disables checking
the warning count. Setting this to 1 has the same effect as setting
``panic_on_warn=1``. The default value is 0.


watchdog
========

Expand Down
3 changes: 3 additions & 0 deletions Documentation/core-api/kernel-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ String Conversions
String Manipulation
-------------------

.. kernel-doc:: include/linux/fortify-string.h
:internal:

.. kernel-doc:: lib/string.c
:export:

Expand Down
6 changes: 5 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -8105,6 +8105,8 @@ 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/fortify_kunit.c
F: lib/memcpy_kunit.c
F: lib/strscpy_kunit.c
F: lib/test_fortify/*
F: scripts/test_fortify.sh
K: \b__NO_FORTIFY\b
Expand Down Expand Up @@ -11208,6 +11210,8 @@ 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: Documentation/ABI/testing/sysfs-kernel-oops_count
F: Documentation/ABI/testing/sysfs-kernel-warn_count
F: include/linux/overflow.h
F: include/linux/randomize_kstack.h
F: mm/usercopy.c
Expand Down Expand Up @@ -19050,7 +19054,7 @@ M: Jason A. Donenfeld <[email protected]>
S: Maintained
F: include/linux/siphash.h
F: lib/siphash.c
F: lib/test_siphash.c
F: lib/siphash_kunit.c

SIS 190 ETHERNET DRIVER
M: Francois Romieu <[email protected]>
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -1120,7 +1120,7 @@ endif
# We never want expected sections to be placed heuristically by the
# linker. All sections should be explicitly named in the linker script.
ifdef CONFIG_LD_ORPHAN_WARN
LDFLAGS_vmlinux += --orphan-handling=warn
LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
endif

# Align the bit size of userspace programs with the kernel
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/boot/compressed/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ LDFLAGS_vmlinux += --no-undefined
LDFLAGS_vmlinux += -X
# Report orphan sections
ifdef CONFIG_LD_ORPHAN_WARN
LDFLAGS_vmlinux += --orphan-handling=warn
LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
endif
# Next argument is a linker script
LDFLAGS_vmlinux += -T
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/vdso/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ ldflags-y := -shared -soname=linux-vdso.so.1 --hash-style=sysv \
-Bsymbolic --build-id=sha1 -n $(btildflags-y)

ifdef CONFIG_LD_ORPHAN_WARN
ldflags-y += --orphan-handling=warn
ldflags-y += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
endif

ldflags-y += -T
Expand Down
2 changes: 1 addition & 1 deletion arch/arm64/kernel/vdso32/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ VDSO_AFLAGS += -D__ASSEMBLY__
VDSO_LDFLAGS += -Bsymbolic --no-undefined -soname=linux-vdso.so.1
VDSO_LDFLAGS += -z max-page-size=4096 -z common-page-size=4096
VDSO_LDFLAGS += -shared --hash-style=sysv --build-id=sha1
VDSO_LDFLAGS += --orphan-handling=warn
VDSO_LDFLAGS += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)


# Borrow vdsomunge.c from the arm vDSO
Expand Down
9 changes: 6 additions & 3 deletions arch/um/drivers/virt-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ static int um_pci_send_cmd(struct um_pci_device *dev,
}

buf = get_cpu_var(um_pci_msg_bufs);
memcpy(buf, cmd, cmd_size);
if (buf)
memcpy(buf, cmd, cmd_size);

if (posted) {
u8 *ncmd = kmalloc(cmd_size + extra_size, GFP_ATOMIC);
Expand Down Expand Up @@ -182,14 +183,16 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
struct um_pci_message_buffer *buf;
u8 *data;
unsigned long ret = ULONG_MAX;
size_t bytes = sizeof(buf->data);

if (!dev)
return ULONG_MAX;

buf = get_cpu_var(um_pci_msg_bufs);
data = buf->data;

memset(buf->data, 0xff, sizeof(buf->data));
if (buf)
memset(data, 0xff, bytes);

switch (size) {
case 1:
Expand All @@ -204,7 +207,7 @@ static unsigned long um_pci_cfgspace_read(void *priv, unsigned int offset,
goto out;
}

if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, 8))
if (um_pci_send_cmd(dev, &hdr, sizeof(hdr), NULL, 0, data, bytes))
goto out;

switch (size) {
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/boot/compressed/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ KBUILD_LDFLAGS += $(call ld-option,--no-ld-generated-unwind-info)
# address by the bootloader.
LDFLAGS_vmlinux := -pie $(call ld-option, --no-dynamic-linker)
ifdef CONFIG_LD_ORPHAN_WARN
LDFLAGS_vmlinux += --orphan-handling=warn
LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
endif
LDFLAGS_vmlinux += -z noexecstack
ifeq ($(CONFIG_LD_IS_BFD),y)
Expand Down
22 changes: 13 additions & 9 deletions arch/x86/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -299,9 +299,6 @@ static void pgd_prepopulate_pmd(struct mm_struct *mm, pgd_t *pgd, pmd_t *pmds[])
pud_t *pud;
int i;

if (PREALLOCATED_PMDS == 0) /* Work around gcc-3.4.x bug */
return;

p4d = p4d_offset(pgd, 0);
pud = pud_offset(p4d, 0);

Expand Down Expand Up @@ -434,10 +431,12 @@ pgd_t *pgd_alloc(struct mm_struct *mm)

mm->pgd = pgd;

if (preallocate_pmds(mm, pmds, PREALLOCATED_PMDS) != 0)
if (sizeof(pmds) != 0 &&
preallocate_pmds(mm, pmds, PREALLOCATED_PMDS) != 0)
goto out_free_pgd;

if (preallocate_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS) != 0)
if (sizeof(u_pmds) != 0 &&
preallocate_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS) != 0)
goto out_free_pmds;

if (paravirt_pgd_alloc(mm) != 0)
Expand All @@ -451,17 +450,22 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
spin_lock(&pgd_lock);

pgd_ctor(mm, pgd);
pgd_prepopulate_pmd(mm, pgd, pmds);
pgd_prepopulate_user_pmd(mm, pgd, u_pmds);
if (sizeof(pmds) != 0)
pgd_prepopulate_pmd(mm, pgd, pmds);

if (sizeof(u_pmds) != 0)
pgd_prepopulate_user_pmd(mm, pgd, u_pmds);

spin_unlock(&pgd_lock);

return pgd;

out_free_user_pmds:
free_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS);
if (sizeof(u_pmds) != 0)
free_pmds(mm, u_pmds, PREALLOCATED_USER_PMDS);
out_free_pmds:
free_pmds(mm, pmds, PREALLOCATED_PMDS);
if (sizeof(pmds) != 0)
free_pmds(mm, pmds, PREALLOCATED_PMDS);
out_free_pgd:
_pgd_free(pgd);
out:
Expand Down
2 changes: 1 addition & 1 deletion drivers/base/firmware_loader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,7 @@ _request_firmware(const struct firmware **firmware_p, const char *name,
* called by a driver when serving an unrelated request from userland, we use
* the kernel credentials to read the file.
*/
kern_cred = prepare_kernel_cred(NULL);
kern_cred = prepare_kernel_cred(&init_task);
if (!kern_cred) {
ret = -ENOMEM;
goto out;
Expand Down
9 changes: 7 additions & 2 deletions drivers/dma-buf/dma-resv.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,17 @@ static void dma_resv_list_set(struct dma_resv_list *list,
static struct dma_resv_list *dma_resv_list_alloc(unsigned int max_fences)
{
struct dma_resv_list *list;
size_t size;

list = kmalloc(struct_size(list, table, max_fences), GFP_KERNEL);
/* Round up to the next kmalloc bucket size. */
size = kmalloc_size_roundup(struct_size(list, table, max_fences));

list = kmalloc(size, GFP_KERNEL);
if (!list)
return NULL;

list->max_fences = (ksize(list) - offsetof(typeof(*list), table)) /
/* Given the resulting bucket size, recalculated max_fences. */
list->max_fences = (size - offsetof(typeof(*list), table)) /
sizeof(*list->table);

return list;
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ static int fsl_dcu_drm_connector_get_modes(struct drm_connector *connector)
return drm_panel_get_modes(fsl_connector->panel, connector);
}

static int fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
static enum drm_mode_status
fsl_dcu_drm_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
if (mode->hdisplay & 0xf)
return MODE_ERROR;
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/i915_user_extensions.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ int i915_user_extensions(struct i915_user_extension __user *ext,
return err;

if (get_user(next, &ext->next_extension) ||
overflows_type(next, ext))
overflows_type(next, uintptr_t))
return -EFAULT;

ext = u64_to_user_ptr(next);
Expand Down
4 changes: 0 additions & 4 deletions drivers/gpu/drm/i915/i915_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,6 @@ bool i915_error_injected(void);
#define range_overflows_end_t(type, start, size, max) \
range_overflows_end((type)(start), (type)(size), (type)(max))

/* Note we don't consider signbits :| */
#define overflows_type(x, T) \
(sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T))

#define ptr_mask_bits(ptr, n) ({ \
unsigned long __v = (unsigned long)(ptr); \
(typeof(ptr))(__v & -BIT(n)); \
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/sti/sti_dvo.c
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,9 @@ static int sti_dvo_connector_get_modes(struct drm_connector *connector)

#define CLK_TOLERANCE_HZ 50

static int sti_dvo_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
static enum drm_mode_status
sti_dvo_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
int target = mode->clock * 1000;
int target_min = target - CLK_TOLERANCE_HZ;
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/sti/sti_hda.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,8 +601,9 @@ static int sti_hda_connector_get_modes(struct drm_connector *connector)

#define CLK_TOLERANCE_HZ 50

static int sti_hda_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
static enum drm_mode_status
sti_hda_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
int target = mode->clock * 1000;
int target_min = target - CLK_TOLERANCE_HZ;
Expand Down
5 changes: 3 additions & 2 deletions drivers/gpu/drm/sti/sti_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1004,8 +1004,9 @@ static int sti_hdmi_connector_get_modes(struct drm_connector *connector)

#define CLK_TOLERANCE_HZ 50

static int sti_hdmi_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
static enum drm_mode_status
sti_hdmi_connector_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
int target = mode->clock * 1000;
int target_min = target - CLK_TOLERANCE_HZ;
Expand Down
11 changes: 6 additions & 5 deletions fs/btrfs/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,11 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
path_len = p->end - p->start;
old_buf_len = p->buf_len;

/*
* Allocate to the next largest kmalloc bucket size, to let
* the fast path happen most of the time.
*/
len = kmalloc_size_roundup(len);
/*
* First time the inline_buf does not suffice
*/
Expand All @@ -498,11 +503,7 @@ static int fs_path_ensure_buf(struct fs_path *p, int len)
if (!tmp_buf)
return -ENOMEM;
p->buf = tmp_buf;
/*
* The real size of the buffer is bigger, this will let the fast path
* happen most of the time
*/
p->buf_len = ksize(p->buf);
p->buf_len = len;

if (p->reversed) {
tmp_buf = p->buf + old_buf_len - path_len - 1;
Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/cifs_spnego.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ init_cifs_spnego(void)
* spnego upcalls.
*/

cred = prepare_kernel_cred(NULL);
cred = prepare_kernel_cred(&init_task);
if (!cred)
return -ENOMEM;

Expand Down
2 changes: 1 addition & 1 deletion fs/cifs/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ init_cifs_idmap(void)
* this is used to prevent malicious redirections from being installed
* with add_key().
*/
cred = prepare_kernel_cred(NULL);
cred = prepare_kernel_cred(&init_task);
if (!cred)
return -ENOMEM;

Expand Down
7 changes: 5 additions & 2 deletions fs/coredump.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,18 @@ struct core_name {

static int expand_corename(struct core_name *cn, int size)
{
char *corename = krealloc(cn->corename, size, GFP_KERNEL);
char *corename;

size = kmalloc_size_roundup(size);
corename = krealloc(cn->corename, size, GFP_KERNEL);

if (!corename)
return -ENOMEM;

if (size > core_name_size) /* racy but harmless */
core_name_size = size;

cn->size = ksize(corename);
cn->size = size;
cn->corename = corename;
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions fs/ksmbd/smb2pdu.c
Original file line number Diff line number Diff line change
Expand Up @@ -3438,7 +3438,7 @@ static int smb2_populate_readdir_entry(struct ksmbd_conn *conn, int info_level,
goto free_conv_name;
}

struct_sz = readdir_info_level_struct_sz(info_level) - 1 + conv_len;
struct_sz = readdir_info_level_struct_sz(info_level) + conv_len;
next_entry_offset = ALIGN(struct_sz, KSMBD_DIR_INFO_ALIGNMENT);
d_info->last_entry_off_align = next_entry_offset - struct_sz;

Expand Down Expand Up @@ -3690,7 +3690,7 @@ static int reserve_populate_dentry(struct ksmbd_dir_info *d_info,
return -EOPNOTSUPP;

conv_len = (d_info->name_len + 1) * 2;
next_entry_offset = ALIGN(struct_sz - 1 + conv_len,
next_entry_offset = ALIGN(struct_sz + conv_len,
KSMBD_DIR_INFO_ALIGNMENT);

if (next_entry_offset > d_info->out_buf_len) {
Expand Down
Loading

0 comments on commit 48ea09c

Please sign in to comment.