Commit 120a201b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull hardening updates from Kees Cook:

 - Introduce the param_unknown_fn type and other clean ups (Andy
   Shevchenko)

 - Various __counted_by annotations (Christophe JAILLET, Gustavo A. R.
   Silva, Kees Cook)

 - Add KFENCE test to LKDTM (Stephen Boyd)

 - Various strncpy() refactorings (Justin Stitt)

 - Fix qnx4 to avoid writing into the smaller of two overlapping buffers

 - Various strlcpy() refactorings

* tag 'hardening-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux:
  qnx4: Use get_directory_fname() in qnx4_match()
  qnx4: Extract dir entry filename processing into helper
  atags_proc: Add __counted_by for struct buffer and use struct_size()
  tracing/uprobe: Replace strlcpy() with strscpy()
  params: Fix multi-line comment style
  params: Sort headers
  params: Use size_add() for kmalloc()
  params: Do not go over the limit when getting the string length
  params: Introduce the param_unknown_fn type
  lkdtm: Add kfence read after free crash type
  nvme-fc: replace deprecated strncpy with strscpy
  nvdimm/btt: replace deprecated strncpy with strscpy
  nvme-fabrics: replace deprecated strncpy with strscpy
  drm/modes: replace deprecated strncpy with strscpy_pad
  afs: Add __counted_by for struct afs_acl and use struct_size()
  VMCI: Annotate struct vmci_handle_arr with __counted_by
  i40e: Annotate struct i40e_qvlist_info with __counted_by
  HID: uhid: replace deprecated strncpy with strscpy
  samples: Replace strlcpy() with strscpy()
  SUNRPC: Replace strlcpy() with strscpy()
parents 72116efd a75b3809
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -7,7 +7,7 @@

struct buffer {
	size_t size;
	char data[];
	char data[] __counted_by(size);
};

static ssize_t atags_read(struct file *file, char __user *buf,
@@ -54,7 +54,7 @@ static int __init init_atags_procfs(void)

	WARN_ON(tag->hdr.tag != ATAG_NONE);

	b = kmalloc(sizeof(*b) + size, GFP_KERNEL);
	b = kmalloc(struct_size(b, data, size), GFP_KERNEL);
	if (!b)
		goto nomem;

+2 −4
Original line number Diff line number Diff line
@@ -2617,8 +2617,7 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out,
		break;
	}

	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
	strscpy_pad(out->name, in->name, sizeof(out->name));
}

/**
@@ -2659,8 +2658,7 @@ int drm_mode_convert_umode(struct drm_device *dev,
	 * useful for the kernel->userspace direction anyway.
	 */
	out->type = in->type & DRM_MODE_TYPE_ALL;
	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
	strscpy_pad(out->name, in->name, sizeof(out->name));

	/* Clearing picture aspect ratio bits from out flags,
	 * as the aspect-ratio information is not stored in
+7 −8
Original line number Diff line number Diff line
@@ -490,7 +490,7 @@ static int uhid_dev_create2(struct uhid_device *uhid,
			    const struct uhid_event *ev)
{
	struct hid_device *hid;
	size_t rd_size, len;
	size_t rd_size;
	void *rd_data;
	int ret;

@@ -514,13 +514,12 @@ static int uhid_dev_create2(struct uhid_device *uhid,
		goto err_free;
	}

	/* @hid is zero-initialized, strncpy() is correct, strlcpy() not */
	len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1;
	strncpy(hid->name, ev->u.create2.name, len);
	len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1;
	strncpy(hid->phys, ev->u.create2.phys, len);
	len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1;
	strncpy(hid->uniq, ev->u.create2.uniq, len);
	BUILD_BUG_ON(sizeof(hid->name) != sizeof(ev->u.create2.name));
	strscpy(hid->name, ev->u.create2.name, sizeof(hid->name));
	BUILD_BUG_ON(sizeof(hid->phys) != sizeof(ev->u.create2.phys));
	strscpy(hid->phys, ev->u.create2.phys, sizeof(hid->phys));
	BUILD_BUG_ON(sizeof(hid->uniq) != sizeof(ev->u.create2.uniq));
	strscpy(hid->uniq, ev->u.create2.uniq, sizeof(hid->uniq));

	hid->ll_driver = &uhid_hid_driver;
	hid->bus = ev->u.create2.bus;
+60 −0
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
 * page allocation and slab allocations.
 */
#include "lkdtm.h"
#include <linux/kfence.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/sched.h>
@@ -132,6 +133,64 @@ static void lkdtm_READ_AFTER_FREE(void)
	kfree(val);
}

static void lkdtm_KFENCE_READ_AFTER_FREE(void)
{
	int *base, val, saw;
	unsigned long timeout, resched_after;
	size_t len = 1024;
	/*
	 * The slub allocator will use the either the first word or
	 * the middle of the allocation to store the free pointer,
	 * depending on configurations. Store in the second word to
	 * avoid running into the freelist.
	 */
	size_t offset = sizeof(*base);

	/*
	 * 100x the sample interval should be more than enough to ensure we get
	 * a KFENCE allocation eventually.
	 */
	timeout = jiffies + msecs_to_jiffies(100 * kfence_sample_interval);
	/*
	 * Especially for non-preemption kernels, ensure the allocation-gate
	 * timer can catch up: after @resched_after, every failed allocation
	 * attempt yields, to ensure the allocation-gate timer is scheduled.
	 */
	resched_after = jiffies + msecs_to_jiffies(kfence_sample_interval);
	do {
		base = kmalloc(len, GFP_KERNEL);
		if (!base) {
			pr_err("FAIL: Unable to allocate kfence memory!\n");
			return;
		}

		if (is_kfence_address(base)) {
			val = 0x12345678;
			base[offset] = val;
			pr_info("Value in memory before free: %x\n", base[offset]);

			kfree(base);

			pr_info("Attempting bad read from freed memory\n");
			saw = base[offset];
			if (saw != val) {
				/* Good! Poisoning happened, so declare a win. */
				pr_info("Memory correctly poisoned (%x)\n", saw);
			} else {
				pr_err("FAIL: Memory was not poisoned!\n");
				pr_expected_config_param(CONFIG_INIT_ON_FREE_DEFAULT_ON, "init_on_free");
			}
			return;
		}

		kfree(base);
		if (time_after(jiffies, resched_after))
			cond_resched();
	} while (time_before(jiffies, timeout));

	pr_err("FAIL: kfence memory never allocated!\n");
}

static void lkdtm_WRITE_BUDDY_AFTER_FREE(void)
{
	unsigned long p = __get_free_page(GFP_KERNEL);
@@ -327,6 +386,7 @@ static struct crashtype crashtypes[] = {
	CRASHTYPE(VMALLOC_LINEAR_OVERFLOW),
	CRASHTYPE(WRITE_AFTER_FREE),
	CRASHTYPE(READ_AFTER_FREE),
	CRASHTYPE(KFENCE_READ_AFTER_FREE),
	CRASHTYPE(WRITE_BUDDY_AFTER_FREE),
	CRASHTYPE(READ_BUDDY_AFTER_FREE),
	CRASHTYPE(SLAB_INIT_ON_ALLOC),
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ struct vmci_handle_arr {
	u32 max_capacity;
	u32 size;
	u32 pad;
	struct vmci_handle entries[];
	struct vmci_handle entries[] __counted_by(capacity);
};

#define VMCI_HANDLE_ARRAY_HEADER_SIZE				\
Loading