diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-10 11:03:52 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2024-01-10 11:03:52 -0800 |
commit | 120a201bd2ad0bffebdd2cf62c389dbba79bbfae (patch) | |
tree | 82250acc579a556aae85ca08c7c6ce77dceec554 /drivers | |
parent | 72116efd6307077546c93e0432a197876cedff70 (diff) | |
parent | a75b3809dce2ad006ebf7fa641f49881fa0d79d7 (diff) |
Merge tag 'hardening-v6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
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()
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/drm_modes.c | 6 | ||||
-rw-r--r-- | drivers/hid/uhid.c | 15 | ||||
-rw-r--r-- | drivers/misc/lkdtm/heap.c | 60 | ||||
-rw-r--r-- | drivers/misc/vmw_vmci/vmci_handle_array.h | 2 | ||||
-rw-r--r-- | drivers/nvdimm/btt.c | 2 | ||||
-rw-r--r-- | drivers/nvme/host/fabrics.c | 4 | ||||
-rw-r--r-- | drivers/nvme/host/fc.c | 8 |
7 files changed, 77 insertions, 20 deletions
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index ac9a406250c5..893f52ee4926 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -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 diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 4588d2cd4ea4..a54c7995b9be 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -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; diff --git a/drivers/misc/lkdtm/heap.c b/drivers/misc/lkdtm/heap.c index 0ce4cbf6abda..4f467d3972a6 100644 --- a/drivers/misc/lkdtm/heap.c +++ b/drivers/misc/lkdtm/heap.c @@ -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), diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.h b/drivers/misc/vmw_vmci/vmci_handle_array.h index 96193f85be5b..b0e6b1956014 100644 --- a/drivers/misc/vmw_vmci/vmci_handle_array.h +++ b/drivers/misc/vmw_vmci/vmci_handle_array.h @@ -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 \ diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c index d5593b0dc700..9372c36e8f76 100644 --- a/drivers/nvdimm/btt.c +++ b/drivers/nvdimm/btt.c @@ -986,7 +986,7 @@ static int btt_arena_write_layout(struct arena_info *arena) if (!super) return -ENOMEM; - strncpy(super->signature, BTT_SIG, BTT_SIG_LEN); + strscpy(super->signature, BTT_SIG, sizeof(super->signature)); export_uuid(super->uuid, nd_btt->uuid); export_uuid(super->parent_uuid, parent_uuid); super->flags = cpu_to_le32(arena->flags); diff --git a/drivers/nvme/host/fabrics.c b/drivers/nvme/host/fabrics.c index aa88606a44c4..b5752a77ad98 100644 --- a/drivers/nvme/host/fabrics.c +++ b/drivers/nvme/host/fabrics.c @@ -387,8 +387,8 @@ static struct nvmf_connect_data *nvmf_connect_data_prep(struct nvme_ctrl *ctrl, uuid_copy(&data->hostid, &ctrl->opts->host->id); data->cntlid = cpu_to_le16(cntlid); - strncpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE); - strncpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE); + strscpy(data->subsysnqn, ctrl->opts->subsysnqn, NVMF_NQN_SIZE); + strscpy(data->hostnqn, ctrl->opts->host->nqn, NVMF_NQN_SIZE); return data; } diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 1d51925ea67f..043f2d7798c1 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -1218,10 +1218,10 @@ nvme_fc_connect_admin_queue(struct nvme_fc_ctrl *ctrl, /* Linux supports only Dynamic controllers */ assoc_rqst->assoc_cmd.cntlid = cpu_to_be16(0xffff); uuid_copy(&assoc_rqst->assoc_cmd.hostid, &ctrl->ctrl.opts->host->id); - strncpy(assoc_rqst->assoc_cmd.hostnqn, ctrl->ctrl.opts->host->nqn, - min(FCNVME_ASSOC_HOSTNQN_LEN, NVMF_NQN_SIZE)); - strncpy(assoc_rqst->assoc_cmd.subnqn, ctrl->ctrl.opts->subsysnqn, - min(FCNVME_ASSOC_SUBNQN_LEN, NVMF_NQN_SIZE)); + strscpy(assoc_rqst->assoc_cmd.hostnqn, ctrl->ctrl.opts->host->nqn, + sizeof(assoc_rqst->assoc_cmd.hostnqn)); + strscpy(assoc_rqst->assoc_cmd.subnqn, ctrl->ctrl.opts->subsysnqn, + sizeof(assoc_rqst->assoc_cmd.subnqn)); lsop->queue = queue; lsreq->rqstaddr = assoc_rqst; |