Pull hardening updates from Kees Cook: "One of the more voluminous set of changes is for adding the new __counted_by annotation[1] to gain run-time bounds checking of dynamically sized arrays with UBSan. - Add LKDTM test for stuck CPUs (Mark Rutland) - Improve LKDTM selftest behavior under UBSan (Ricardo Cañuelo) - Refactor more 1-element arrays into flexible arrays (Gustavo A. R. Silva) - Analyze and replace strlcpy and strncpy uses (Justin Stitt, Azeem Shaikh) - Convert group_info.usage to refcount_t (Elena Reshetova) - Add __counted_by annotations (Kees Cook, Gustavo A. R. Silva) - Add Kconfig fragment for basic hardening options (Kees Cook, Lukas Bulwahn) - Fix randstruct GCC plugin performance mode to stay in groups (Kees Cook) - Fix strtomem() compile-time check for small sources (Kees Cook)" * tag 'hardening-v6.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (56 commits) hwmon: (acpi_power_meter) replace open-coded kmemdup_nul reset: Annotate struct reset_control_array with __counted_by kexec: Annotate struct crash_mem with __counted_by virtio_console: Annotate struct port_buffer with __counted_by ima: Add __counted_by for struct modsig and use struct_size() MAINTAINERS: Include stackleak paths in hardening entry string: Adjust strtomem() logic to allow for smaller sources hardening: x86: drop reference to removed config AMD_IOMMU_V2 randstruct: Fix gcc-plugin performance mode to stay in group mailbox: zynqmp: Annotate struct zynqmp_ipi_pdata with __counted_by drivers: thermal: tsens: Annotate struct tsens_priv with __counted_by irqchip/imx-intmux: Annotate struct intmux_data with __counted_by KVM: Annotate struct kvm_irq_routing_table with __counted_by virt: acrn: Annotate struct vm_memory_region_batch with __counted_by hwmon: Annotate struct gsc_hwmon_platform_data with __counted_by sparc: Annotate struct cpuinfo_tree with __counted_by isdn: kcapi: replace deprecated strncpy with strscpy_pad isdn: replace deprecated strncpy with strscpy NFS/flexfiles: Annotate struct nfs4_ff_layout_segment with __counted_by nfs41: Annotate struct nfs4_file_layout_dsaddr with __counted_by ...
Unified · Split
| @@ -8649,6 +8649,8 @@ L: linux-hardening@vger.kernel.org · 8648 unmodified lines | ||
| 8649 | 8649 | S: Maintained |
| 8650 | 8650 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening |
| 8651 | 8651 | F: Documentation/kbuild/gcc-plugins.rst |
| 8652 | +F: include/linux/stackleak.h | |
| 8653 | +F: kernel/stackleak.c | |
| 8652 | 8654 | F: scripts/Makefile.gcc-plugins |
| 8653 | 8655 | F: scripts/gcc-plugins/ |
| 8654 | 8656 | |
| @@ -11415,16 +11417,20 @@ F: usr/ · 2760 unmodified lines | ||
| 11415 | 11417 | |
| 11416 | 11418 | KERNEL HARDENING (not covered by other areas) |
| 11417 | 11419 | M: Kees Cook <keescook@chromium.org> |
| 11420 | +R: Gustavo A. R. Silva <gustavoars@kernel.org> | |
| 11418 | 11421 | L: linux-hardening@vger.kernel.org |
| 11419 | 11422 | S: Supported |
| 11420 | 11423 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening |
| 11421 | 11424 | F: Documentation/ABI/testing/sysfs-kernel-oops_count |
| 11422 | 11425 | F: Documentation/ABI/testing/sysfs-kernel-warn_count |
| 11426 | +F: arch/*/configs/hardening.config | |
| 11423 | 11427 | F: include/linux/overflow.h |
| 11424 | 11428 | F: include/linux/randomize_kstack.h |
| 11429 | +F: kernel/configs/hardening.config | |
| 11425 | 11430 | F: mm/usercopy.c |
| 11426 | 11431 | K: \b(add|choose)_random_kstack_offset\b |
| 11427 | 11432 | K: \b__check_(object_size|heap_object)\b |
| 11433 | +K: \b__counted_by\b | |
| 11428 | 11434 | |
| 11429 | 11435 | KERNEL JANITORS |
| 11430 | 11436 | L: kernel-janitors@vger.kernel.org |
| @@ -0,0 +1,7 @@ | ||
| 1 | +# Basic kernel hardening options (specific to arm) | |
| 2 | + | |
| 3 | +# Make sure PXN/PAN emulation is enabled. | |
| 4 | +CONFIG_CPU_SW_DOMAIN_PAN=y | |
| 5 | + | |
| 6 | +# Dangerous; old interfaces and needless additional attack surface. | |
| 7 | +# CONFIG_OABI_COMPAT is not set | |
| @@ -0,0 +1,22 @@ | ||
| 1 | +# Basic kernel hardening options (specific to arm64) | |
| 2 | + | |
| 3 | +# Make sure PAN emulation is enabled. | |
| 4 | +CONFIG_ARM64_SW_TTBR0_PAN=y | |
| 5 | + | |
| 6 | +# Software Shadow Stack or PAC | |
| 7 | +CONFIG_SHADOW_CALL_STACK=y | |
| 8 | + | |
| 9 | +# Pointer authentication (ARMv8.3 and later). If hardware actually supports | |
| 10 | +# it, one can turn off CONFIG_STACKPROTECTOR_STRONG with this enabled. | |
| 11 | +CONFIG_ARM64_PTR_AUTH=y | |
| 12 | +CONFIG_ARM64_PTR_AUTH_KERNEL=y | |
| 13 | + | |
| 14 | +# Available in ARMv8.5 and later. | |
| 15 | +CONFIG_ARM64_BTI=y | |
| 16 | +CONFIG_ARM64_BTI_KERNEL=y | |
| 17 | +CONFIG_ARM64_MTE=y | |
| 18 | +CONFIG_KASAN_HW_TAGS=y | |
| 19 | +CONFIG_ARM64_E0PD=y | |
| 20 | + | |
| 21 | +# Available in ARMv8.7 and later. | |
| 22 | +CONFIG_ARM64_EPAN=y | |
| @@ -0,0 +1,10 @@ | ||
| 1 | +# PowerPC specific hardening options | |
| 2 | + | |
| 3 | +# Block kernel from unexpectedly reading userspace memory. | |
| 4 | +CONFIG_PPC_KUAP=y | |
| 5 | + | |
| 6 | +# Attack surface reduction. | |
| 7 | +# CONFIG_SCOM_DEBUGFS is not set | |
| 8 | + | |
| 9 | +# Disable internal kernel debugger. | |
| 10 | +# CONFIG_XMON is not set | |
| @@ -50,7 +50,7 @@ struct cpuinfo_tree { · 49 unmodified lines | ||
| 50 | 50 | |
| 51 | 51 | /* Offsets into nodes[] for each level of the tree */ |
| 52 | 52 | struct cpuinfo_level level[CPUINFO_LVL_MAX]; |
| 53 | − struct cpuinfo_node nodes[]; | |
| 53 | + struct cpuinfo_node nodes[] __counted_by(total_nodes); | |
| 54 | 54 | }; |
| 55 | 55 | |
| 56 | 56 | |
| @@ -105,7 +105,7 @@ static int etap_tramp(char *dev, char *gate, int control_me, · 104 unmodified lines | ||
| 105 | 105 | sprintf(data_fd_buf, "%d", data_remote); |
| 106 | 106 | sprintf(version_buf, "%d", UML_NET_VERSION); |
| 107 | 107 | if (gate != NULL) { |
| 108 | − strncpy(gate_buf, gate, 15); | |
| 108 | + strscpy(gate_buf, gate, sizeof(gate_buf)); | |
| 109 | 109 | args = setup_args; |
| 110 | 110 | } |
| 111 | 111 | else args = nosetup_args; |
| @@ -0,0 +1,14 @@ | ||
| 1 | +# Basic kernel hardening options (specific to x86) | |
| 2 | + | |
| 3 | +# Modern libc no longer needs a fixed-position mapping in userspace, remove | |
| 4 | +# it as a possible target. | |
| 5 | +CONFIG_LEGACY_VSYSCALL_NONE=y | |
| 6 | + | |
| 7 | +# Enable chip-specific IOMMU support. | |
| 8 | +CONFIG_INTEL_IOMMU=y | |
| 9 | +CONFIG_INTEL_IOMMU_DEFAULT_ON=y | |
| 10 | +CONFIG_INTEL_IOMMU_SVM=y | |
| 11 | +CONFIG_AMD_IOMMU=y | |
| 12 | + | |
| 13 | +# Enable CET Shadow Stack for userspace. | |
| 14 | +CONFIG_X86_USER_SHADOW_STACK=y | |
| @@ -51,7 +51,7 @@ struct ivpu_job { · 50 unmodified lines | ||
| 51 | 51 | u32 job_id; |
| 52 | 52 | u32 engine_idx; |
| 53 | 53 | size_t bo_count; |
| 54 | − struct ivpu_bo *bos[]; | |
| 54 | + struct ivpu_bo *bos[] __counted_by(bo_count); | |
| 55 | 55 | }; |
| 56 | 56 | |
| 57 | 57 | int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file); |
| @@ -1449,10 +1449,9 @@ static struct logical_input *panel_bind_key(const char *name, const char *press, · 1448 unmodified lines | ||
| 1449 | 1449 | key->rise_time = 1; |
| 1450 | 1450 | key->fall_time = 1; |
| 1451 | 1451 | |
| 1452 | − strncpy(key->u.kbd.press_str, press, sizeof(key->u.kbd.press_str)); | |
| 1453 | − strncpy(key->u.kbd.repeat_str, repeat, sizeof(key->u.kbd.repeat_str)); | |
| 1454 | − strncpy(key->u.kbd.release_str, release, | |
| 1455 | − sizeof(key->u.kbd.release_str)); | |
| 1452 | + strtomem_pad(key->u.kbd.press_str, press, '\0'); | |
| 1453 | + strtomem_pad(key->u.kbd.repeat_str, repeat, '\0'); | |
| 1454 | + strtomem_pad(key->u.kbd.release_str, release, '\0'); | |
| 1456 | 1455 | list_add(&key->list, &logical_inputs); |
| 1457 | 1456 | return key; |
| 1458 | 1457 | } |
| @@ -555,7 +555,7 @@ struct fifo_buffer { · 554 unmodified lines | ||
| 555 | 555 | unsigned int head_index; |
| 556 | 556 | unsigned int size; |
| 557 | 557 | int total; /* sum of all values */ |
| 558 | − int values[]; | |
| 558 | + int values[] __counted_by(size); | |
| 559 | 559 | }; |
| 560 | 560 | extern struct fifo_buffer *fifo_alloc(unsigned int fifo_size); |
| 561 | 561 | |
| @@ -450,10 +450,8 @@ int dprc_get_obj(struct fsl_mc_io *mc_io, · 449 unmodified lines | ||
| 450 | 450 | obj_desc->ver_major = le16_to_cpu(rsp_params->version_major); |
| 451 | 451 | obj_desc->ver_minor = le16_to_cpu(rsp_params->version_minor); |
| 452 | 452 | obj_desc->flags = le16_to_cpu(rsp_params->flags); |
| 453 | − strncpy(obj_desc->type, rsp_params->type, 16); | |
| 454 | − obj_desc->type[15] = '\0'; | |
| 455 | − strncpy(obj_desc->label, rsp_params->label, 16); | |
| 456 | − obj_desc->label[15] = '\0'; | |
| 453 | + strscpy_pad(obj_desc->type, rsp_params->type, 16); | |
| 454 | + strscpy_pad(obj_desc->label, rsp_params->label, 16); | |
| 457 | 455 | return 0; |
| 458 | 456 | } |
| 459 | 457 | EXPORT_SYMBOL_GPL(dprc_get_obj); |
| @@ -491,8 +489,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io, · 31 unmodified lines | ||
| 491 | 489 | cmd_params->irq_addr = cpu_to_le64(irq_cfg->paddr); |
| 492 | 490 | cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num); |
| 493 | 491 | cmd_params->obj_id = cpu_to_le32(obj_id); |
| 494 | − strncpy(cmd_params->obj_type, obj_type, 16); | |
| 495 | − cmd_params->obj_type[15] = '\0'; | |
| 492 | + strscpy_pad(cmd_params->obj_type, obj_type, 16); | |
| 496 | 493 | |
| 497 | 494 | /* send command to mc*/ |
| 498 | 495 | return mc_send_command(mc_io, &cmd); |
| @@ -564,8 +561,7 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io, · 65 unmodified lines | ||
| 564 | 561 | cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; |
| 565 | 562 | cmd_params->obj_id = cpu_to_le32(obj_id); |
| 566 | 563 | cmd_params->region_index = region_index; |
| 567 | − strncpy(cmd_params->obj_type, obj_type, 16); | |
| 568 | − cmd_params->obj_type[15] = '\0'; | |
| 564 | + strscpy_pad(cmd_params->obj_type, obj_type, 16); | |
| 569 | 565 | |
| 570 | 566 | /* send command to mc*/ |
| 571 | 567 | err = mc_send_command(mc_io, &cmd); |
| @@ -106,7 +106,7 @@ struct port_buffer { · 105 unmodified lines | ||
| 106 | 106 | unsigned int sgpages; |
| 107 | 107 | |
| 108 | 108 | /* sg is used if spages > 0. sg must be the last in is struct */ |
| 109 | − struct scatterlist sg[]; | |
| 109 | + struct scatterlist sg[] __counted_by(sgpages); | |
| 110 | 110 | }; |
| 111 | 111 | |
| 112 | 112 | /* |
| @@ -1650,7 +1650,7 @@ static void __cpufreq_offline(unsigned int cpu, struct cpufreq_policy *policy) · 1649 unmodified lines | ||
| 1650 | 1650 | } |
| 1651 | 1651 | |
| 1652 | 1652 | if (has_target()) |
| 1653 | − strncpy(policy->last_governor, policy->governor->name, | |
| 1653 | + strscpy(policy->last_governor, policy->governor->name, | |
| 1654 | 1654 | CPUFREQ_NAME_LEN); |
| 1655 | 1655 | else |
| 1656 | 1656 | policy->last_policy = policy->policy; |
| @@ -2996,7 +2996,7 @@ static int __init cpufreq_core_init(void) · 1339 unmodified lines | ||
| 2996 | 2996 | BUG_ON(!cpufreq_global_kobject); |
| 2997 | 2997 | |
| 2998 | 2998 | if (!strlen(default_governor)) |
| 2999 | − strncpy(default_governor, gov->name, CPUFREQ_NAME_LEN); | |
| 2999 | + strscpy(default_governor, gov->name, CPUFREQ_NAME_LEN); | |
| 3000 | 3000 | |
| 3001 | 3001 | return 0; |
| 3002 | 3002 | } |
| @@ -84,8 +84,8 @@ static int init_state_node(struct cpuidle_state *idle_state, · 83 unmodified lines | ||
| 84 | 84 | * replace with kstrdup and pointer assignment when name |
| 85 | 85 | * and desc become string pointers |
| 86 | 86 | */ |
| 87 | − strncpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN - 1); | |
| 88 | − strncpy(idle_state->desc, desc, CPUIDLE_DESC_LEN - 1); | |
| 87 | + strscpy(idle_state->name, state_node->name, CPUIDLE_NAME_LEN); | |
| 88 | + strscpy(idle_state->desc, desc, CPUIDLE_DESC_LEN); | |
| 89 | 89 | return 0; |
| 90 | 90 | } |
| 91 | 91 | |
| @@ -229,7 +229,7 @@ static ssize_t channel_dimm_label_store(struct device *dev, · 228 unmodified lines | ||
| 229 | 229 | if (copy_count == 0 || copy_count >= sizeof(rank->dimm->label)) |
| 230 | 230 | return -EINVAL; |
| 231 | 231 | |
| 232 | − strncpy(rank->dimm->label, data, copy_count); | |
| 232 | + memcpy(rank->dimm->label, data, copy_count); | |
| 233 | 233 | rank->dimm->label[copy_count] = '\0'; |
| 234 | 234 | |
| 235 | 235 | return count; |
| @@ -535,7 +535,7 @@ static ssize_t dimmdev_label_store(struct device *dev, · 299 unmodified lines | ||
| 535 | 535 | if (copy_count == 0 || copy_count >= sizeof(dimm->label)) |
| 536 | 536 | return -EINVAL; |
| 537 | 537 | |
| 538 | − strncpy(dimm->label, data, copy_count); | |
| 538 | + memcpy(dimm->label, data, copy_count); | |
| 539 | 539 | dimm->label[copy_count] = '\0'; |
| 540 | 540 | |
| 541 | 541 | return count; |
| @@ -610,7 +610,7 @@ static int debugfs_show(struct seq_file *m, void *p) · 609 unmodified lines | ||
| 610 | 610 | } |
| 611 | 611 | |
| 612 | 612 | len = strlen(filename); |
| 613 | − strncpy(namevirt, filename, namesize); | |
| 613 | + strscpy_pad(namevirt, filename, namesize); | |
| 614 | 614 | |
| 615 | 615 | err = mrq_debugfs_read(bpmp, namephys, len, dataphys, datasize, |
| 616 | 616 | &nbytes); |
| @@ -661,7 +661,7 @@ static ssize_t debugfs_store(struct file *file, const char __user *buf, · 44 unmodified lines | ||
| 661 | 661 | } |
| 662 | 662 | |
| 663 | 663 | len = strlen(filename); |
| 664 | − strncpy(namevirt, filename, namesize); | |
| 664 | + strscpy_pad(namevirt, filename, namesize); | |
| 665 | 665 | |
| 666 | 666 | if (copy_from_user(datavirt, buf, count)) { |
| 667 | 667 | err = -EFAULT; |
| @@ -503,7 +503,7 @@ int gud_pipe_check(struct drm_simple_display_pipe *pipe, · 502 unmodified lines | ||
| 503 | 503 | return -ENOENT; |
| 504 | 504 | |
| 505 | 505 | len = struct_size(req, properties, |
| 506 | − GUD_PROPERTIES_MAX_NUM + GUD_CONNECTOR_PROPERTIES_MAX_NUM); | |
| 506 | + size_add(GUD_PROPERTIES_MAX_NUM, GUD_CONNECTOR_PROPERTIES_MAX_NUM)); | |
| 507 | 507 | req = kzalloc(len, GFP_KERNEL); |
| 508 | 508 | if (!req) |
| 509 | 509 | return -ENOMEM; |
| @@ -67,7 +67,7 @@ struct nouveau_svm { · 66 unmodified lines | ||
| 67 | 67 | struct nouveau_svmm *svmm; |
| 68 | 68 | } **fault; |
| 69 | 69 | int fault_nr; |
| 70 | − } buffer[1]; | |
| 70 | + } buffer[]; | |
| 71 | 71 | }; |
| 72 | 72 | |
| 73 | 73 | #define FAULT_ACCESS_READ 0 |
| @@ -1063,7 +1063,8 @@ nouveau_svm_init(struct nouveau_drm *drm) · 989 unmodified lines | ||
| 1063 | 1063 | if (drm->client.device.info.family > NV_DEVICE_INFO_V0_PASCAL) |
| 1064 | 1064 | return; |
| 1065 | 1065 | |
| 1066 | − if (!(drm->svm = svm = kzalloc(sizeof(*drm->svm), GFP_KERNEL))) | |
| 1066 | + drm->svm = svm = kzalloc(struct_size(drm->svm, buffer, 1), GFP_KERNEL); | |
| 1067 | + if (!drm->svm) | |
| 1067 | 1068 | return; |
| 1068 | 1069 | |
| 1069 | 1070 | drm->svm->drm = drm; |
| @@ -639,9 +639,9 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm) · 638 unmodified lines | ||
| 639 | 639 | goto fail; |
| 640 | 640 | } |
| 641 | 641 | |
| 642 | − strncpy(card->driver, shortname, sizeof(card->driver)); | |
| 643 | − strncpy(card->shortname, shortname, sizeof(card->shortname)); | |
| 644 | − strncpy(card->longname, longname, sizeof(card->longname)); | |
| 642 | + strscpy(card->driver, shortname, sizeof(card->driver)); | |
| 643 | + strscpy(card->shortname, shortname, sizeof(card->shortname)); | |
| 644 | + strscpy(card->longname, longname, sizeof(card->longname)); | |
| 645 | 645 | |
| 646 | 646 | /* Set up rawmidi */ |
| 647 | 647 | err = snd_rawmidi_new(card, card->shortname, 0, |
| @@ -652,7 +652,7 @@ static int pcmidi_snd_initialise(struct pcmidi_snd *pm) · 4 unmodified lines | ||
| 652 | 652 | goto fail; |
| 653 | 653 | } |
| 654 | 654 | pm->rwmidi = rwmidi; |
| 655 | − strncpy(rwmidi->name, card->shortname, sizeof(rwmidi->name)); | |
| 655 | + strscpy(rwmidi->name, card->shortname, sizeof(rwmidi->name)); | |
| 656 | 656 | rwmidi->info_flags = SNDRV_RAWMIDI_INFO_INPUT; |
| 657 | 657 | rwmidi->private_data = pm; |
| 658 | 658 | |
| @@ -796,14 +796,13 @@ static int read_capabilities(struct acpi_power_meter_resource *resource) · 795 unmodified lines | ||
| 796 | 796 | goto error; |
| 797 | 797 | } |
| 798 | 798 | |
| 799 | − *str = kcalloc(element->string.length + 1, sizeof(u8), | |
| 800 | − GFP_KERNEL); | |
| 799 | + *str = kmemdup_nul(element->string.pointer, element->string.length, | |
| 800 | + GFP_KERNEL); | |
| 801 | 801 | if (!*str) { |
| 802 | 802 | res = -ENOMEM; |
| 803 | 803 | goto error; |
| 804 | 804 | } |
| 805 | 805 | |
| 806 | − strncpy(*str, element->string.pointer, element->string.length); | |
| 807 | 806 | str++; |
| 808 | 807 | } |
| 809 | 808 | |
| @@ -300,7 +300,7 @@ static int asus_wmi_sensor_info(int index, struct asus_wmi_sensor_info *s) · 299 unmodified lines | ||
| 300 | 300 | goto out_free_obj; |
| 301 | 301 | } |
| 302 | 302 | |
| 303 | − strncpy(s->name, name_obj.string.pointer, sizeof(s->name) - 1); | |
| 303 | + strscpy(s->name, name_obj.string.pointer, sizeof(s->name)); | |
| 304 | 304 | |
| 305 | 305 | data_type_obj = obj->package.elements[1]; |
| 306 | 306 | if (data_type_obj.type != ACPI_TYPE_INTEGER) { |
| @@ -234,7 +234,7 @@ static int get_sensor_index_attr(const char *name, u32 *index, char *attr) · 233 unmodified lines | ||
| 234 | 234 | if (copy_len >= sizeof(buf)) |
| 235 | 235 | return -EINVAL; |
| 236 | 236 | |
| 237 | − strncpy(buf, hash_pos + 1, copy_len); | |
| 237 | + memcpy(buf, hash_pos + 1, copy_len); | |
| 238 | 238 | |
| 239 | 239 | err = kstrtou32(buf, 10, index); |
| 240 | 240 | if (err) |
| @@ -73,7 +73,7 @@ struct intmux_data { · 72 unmodified lines | ||
| 73 | 73 | void __iomem *regs; |
| 74 | 74 | struct clk *ipg_clk; |
| 75 | 75 | int channum; |
| 76 | − struct intmux_irqchip_data irqchip_data[]; | |
| 76 | + struct intmux_irqchip_data irqchip_data[] __counted_by(channum); | |
| 77 | 77 | }; |
| 78 | 78 | |
| 79 | 79 | static void imx_intmux_irq_mask(struct irq_data *d) |
| @@ -732,7 +732,7 @@ u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]) · 731 unmodified lines | ||
| 732 | 732 | u16 ret; |
| 733 | 733 | |
| 734 | 734 | if (contr == 0) { |
| 735 | − strncpy(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); | |
| 735 | + strscpy_pad(buf, capi_manufakturer, CAPI_MANUFACTURER_LEN); | |
| 736 | 736 | return CAPI_NOERROR; |
| 737 | 737 | } |
| 738 | 738 | |
| @@ -740,7 +740,7 @@ u16 capi20_get_manufacturer(u32 contr, u8 buf[CAPI_MANUFACTURER_LEN]) · 1 unmodified line | ||
| 740 | 740 | |
| 741 | 741 | ctr = get_capi_ctr_by_nr(contr); |
| 742 | 742 | if (ctr && ctr->state == CAPI_CTR_RUNNING) { |
| 743 | − strncpy(buf, ctr->manu, CAPI_MANUFACTURER_LEN); | |
| 743 | + strscpy_pad(buf, ctr->manu, CAPI_MANUFACTURER_LEN); | |
| 744 | 744 | ret = CAPI_NOERROR; |
| 745 | 745 | } else |
| 746 | 746 | ret = CAPI_REGNOTINSTALLED; |
| @@ -96,7 +96,7 @@ struct mISDNclock · 95 unmodified lines | ||
| 96 | 96 | printk(KERN_ERR "%s: No memory for clock entry.\n", __func__); |
| 97 | 97 | return NULL; |
| 98 | 98 | } |
| 99 | − strncpy(iclock->name, name, sizeof(iclock->name) - 1); | |
| 99 | + strscpy(iclock->name, name, sizeof(iclock->name)); | |
| 100 | 100 | iclock->pri = pri; |
| 101 | 101 | iclock->priv = priv; |
| 102 | 102 | iclock->ctl = ctl; |
| @@ -108,7 +108,7 @@ struct zynqmp_ipi_pdata { · 107 unmodified lines | ||
| 108 | 108 | unsigned int method; |
| 109 | 109 | u32 local_id; |
| 110 | 110 | int num_mboxes; |
| 111 | − struct zynqmp_ipi_mbox ipi_mboxes[]; | |
| 111 | + struct zynqmp_ipi_mbox ipi_mboxes[] __counted_by(num_mboxes); | |
| 112 | 112 | }; |
| 113 | 113 | |
| 114 | 114 | static struct device_driver zynqmp_ipi_mbox_driver = { |
| @@ -26,7 +26,7 @@ struct prison_region { · 25 unmodified lines | ||
| 26 | 26 | struct dm_bio_prison { |
| 27 | 27 | mempool_t cell_pool; |
| 28 | 28 | unsigned int num_locks; |
| 29 | − struct prison_region regions[]; | |
| 29 | + struct prison_region regions[] __counted_by(num_locks); | |
| 30 | 30 | }; |
| 31 | 31 | |
| 32 | 32 | static struct kmem_cache *_cell_cache; |
| @@ -224,7 +224,7 @@ struct crypt_config { · 223 unmodified lines | ||
| 224 | 224 | struct mutex bio_alloc_lock; |
| 225 | 225 | |
| 226 | 226 | u8 *authenc_key; /* space for keys in authenc() format (if used) */ |
| 227 | − u8 key[]; | |
| 227 | + u8 key[] __counted_by(key_size); | |
| 228 | 228 | }; |
| 229 | 229 | |
| 230 | 230 | #define MIN_IOS 64 |
| @@ -254,7 +254,7 @@ struct raid_set { · 253 unmodified lines | ||
| 254 | 254 | int mode; |
| 255 | 255 | } journal_dev; |
| 256 | 256 | |
| 257 | − struct raid_dev dev[]; | |
| 257 | + struct raid_dev dev[] __counted_by(raid_disks); | |
| 258 | 258 | }; |
| 259 | 259 | |
| 260 | 260 | static void rs_config_backup(struct raid_set *rs, struct rs_layout *l) |
| @@ -56,7 +56,7 @@ struct dm_stat { · 55 unmodified lines | ||
| 56 | 56 | size_t percpu_alloc_size; |
| 57 | 57 | size_t histogram_alloc_size; |
| 58 | 58 | struct dm_stat_percpu *stat_percpu[NR_CPUS]; |
| 59 | − struct dm_stat_shared stat_shared[]; | |
| 59 | + struct dm_stat_shared stat_shared[] __counted_by(n_entries); | |
| 60 | 60 | }; |
| 61 | 61 | |
| 62 | 62 | #define STAT_PRECISE_TIMESTAMPS 1 |
| @@ -44,7 +44,7 @@ struct stripe_c { · 43 unmodified lines | ||
| 44 | 44 | /* Work struct used for triggering events*/ |
| 45 | 45 | struct work_struct trigger_event; |
| 46 | 46 | |
| 47 | − struct stripe stripe[]; | |
| 47 | + struct stripe stripe[] __counted_by(stripes); | |
| 48 | 48 | }; |
| 49 | 49 | |
| 50 | 50 | /* |
| @@ -6,12 +6,14 @@ · 5 unmodified lines | ||
| 6 | 6 | * test source files. |
| 7 | 7 | */ |
| 8 | 8 | #include "lkdtm.h" |
| 9 | +#include <linux/cpu.h> | |
| 9 | 10 | #include <linux/list.h> |
| 10 | 11 | #include <linux/sched.h> |
| 11 | 12 | #include <linux/sched/signal.h> |
| 12 | 13 | #include <linux/sched/task_stack.h> |
| 13 | −#include <linux/uaccess.h> | |
| 14 | 14 | #include <linux/slab.h> |
| 15 | +#include <linux/stop_machine.h> | |
| 16 | +#include <linux/uaccess.h> | |
| 15 | 17 | |
| 16 | 18 | #if IS_ENABLED(CONFIG_X86_32) && !IS_ENABLED(CONFIG_UML) |
| 17 | 19 | #include <asm/desc.h> |
| @@ -73,6 +75,31 @@ static void lkdtm_PANIC(void) · 55 unmodified lines | ||
| 73 | 75 | panic("dumptest"); |
| 74 | 76 | } |
| 75 | 77 | |
| 78 | +static int panic_stop_irqoff_fn(void *arg) | |
| 79 | +{ | |
| 80 | + atomic_t *v = arg; | |
| 81 | + | |
| 82 | + /* | |
| 83 | + * As stop_machine() disables interrupts, all CPUs within this function | |
| 84 | + * have interrupts disabled and cannot take a regular IPI. | |
| 85 | + * | |
| 86 | + * The last CPU which enters here will trigger a panic, and as all CPUs | |
| 87 | + * cannot take a regular IPI, we'll only be able to stop secondaries if | |
| 88 | + * smp_send_stop() or crash_smp_send_stop() uses an NMI. | |
| 89 | + */ | |
| 90 | + if (atomic_inc_return(v) == num_online_cpus()) | |
| 91 | + panic("panic stop irqoff test"); | |
| 92 | + | |
| 93 | + for (;;) | |
| 94 | + cpu_relax(); | |
| 95 | +} | |
| 96 | + | |
| 97 | +static void lkdtm_PANIC_STOP_IRQOFF(void) | |
| 98 | +{ | |
| 99 | + atomic_t v = ATOMIC_INIT(0); | |
| 100 | + stop_machine(panic_stop_irqoff_fn, &v, cpu_online_mask); | |
| 101 | +} | |
| 102 | + | |
| 76 | 103 | static void lkdtm_BUG(void) |
| 77 | 104 | { |
| 78 | 105 | BUG(); |
| @@ -638,6 +665,7 @@ static noinline void lkdtm_CORRUPT_PAC(void) · 559 unmodified lines | ||
| 638 | 665 | |
| 639 | 666 | static struct crashtype crashtypes[] = { |
| 640 | 667 | CRASHTYPE(PANIC), |
| 668 | + CRASHTYPE(PANIC_STOP_IRQOFF), | |
| 641 | 669 | CRASHTYPE(BUG), |
| 642 | 670 | CRASHTYPE(WARNING), |
| 643 | 671 | CRASHTYPE(WARNING_MESSAGE), |
| @@ -60,7 +60,7 @@ struct reset_control { · 59 unmodified lines | ||
| 60 | 60 | struct reset_control_array { |
| 61 | 61 | struct reset_control base; |
| 62 | 62 | unsigned int num_rstcs; |
| 63 | − struct reset_control *rstc[]; | |
| 63 | + struct reset_control *rstc[] __counted_by(num_rstcs); | |
| 64 | 64 | }; |
| 65 | 65 | |
| 66 | 66 | static const char *rcdev_name(struct reset_controller_dev *rcdev) |
| @@ -1185,6 +1185,7 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional, · 1118 unmodified lines | ||
| 1185 | 1185 | resets = kzalloc(struct_size(resets, rstc, num), GFP_KERNEL); |
| 1186 | 1186 | if (!resets) |
| 1187 | 1187 | return ERR_PTR(-ENOMEM); |
| 1188 | + resets->num_rstcs = num; | |
| 1188 | 1189 | |
| 1189 | 1190 | for (i = 0; i < num; i++) { |
| 1190 | 1191 | rstc = __of_reset_control_get(np, NULL, i, shared, optional, |
| @@ -1193,7 +1194,6 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional, · 2 unmodified lines | ||
| 1193 | 1194 | goto err_rst; |
| 1194 | 1195 | resets->rstc[i] = rstc; |
| 1195 | 1196 | } |
| 1196 | − resets->num_rstcs = num; | |
| 1197 | 1197 | resets->base.array = true; |
| 1198 | 1198 | |
| 1199 | 1199 | return &resets->base; |
| @@ -585,7 +585,7 @@ struct tsens_priv { · 584 unmodified lines | ||
| 585 | 585 | struct dentry *debug_root; |
| 586 | 586 | struct dentry *debug; |
| 587 | 587 | |
| 588 | − struct tsens_sensor sensor[]; | |
| 588 | + struct tsens_sensor sensor[] __counted_by(num_sensors); | |
| 589 | 589 | }; |
| 590 | 590 | |
| 591 | 591 | /** |
| @@ -1018,7 +1018,8 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, · 1017 unmodified lines | ||
| 1018 | 1018 | size_t size; |
| 1019 | 1019 | |
| 1020 | 1020 | /* instance init */ |
| 1021 | − size = struct_size(instance, urbs, num_rcv_urbs + num_snd_urbs); | |
| 1021 | + size = struct_size(instance, urbs, | |
| 1022 | + size_add(num_rcv_urbs, num_snd_urbs)); | |
| 1022 | 1023 | instance = kzalloc(size, GFP_KERNEL); |
| 1023 | 1024 | if (!instance) |
| 1024 | 1025 | return -ENOMEM; |
| @@ -202,7 +202,7 @@ struct ffs_epfile { · 201 unmodified lines | ||
| 202 | 202 | struct ffs_buffer { |
| 203 | 203 | size_t length; |
| 204 | 204 | char *data; |
| 205 | − char storage[]; | |
| 205 | + char storage[] __counted_by(length); | |
| 206 | 206 | }; |
| 207 | 207 | |
| 208 | 208 | /* ffs_io_data structure ***************************************************/ |
| @@ -99,7 +99,7 @@ struct f_midi { · 98 unmodified lines | ||
| 99 | 99 | unsigned int in_last_port; |
| 100 | 100 | unsigned char free_ref; |
| 101 | 101 | |
| 102 | − struct gmidi_in_port in_ports_array[/* in_ports */]; | |
| 102 | + struct gmidi_in_port in_ports_array[] __counted_by(in_ports); | |
| 103 | 103 | }; |
| 104 | 104 | |
| 105 | 105 | static inline struct f_midi *func_to_midi(struct usb_function *f) |
| @@ -1349,6 +1349,7 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) · 1243 unmodified lines | ||
| 1349 | 1349 | status = -ENOMEM; |
| 1350 | 1350 | goto setup_fail; |
| 1351 | 1351 | } |
| 1352 | + midi->in_ports = opts->in_ports; | |
| 1352 | 1353 | |
| 1353 | 1354 | for (i = 0; i < opts->in_ports; i++) |
| 1354 | 1355 | midi->in_ports_array[i].cable = i; |
| @@ -1359,7 +1360,6 @@ static struct usb_function *f_midi_alloc(struct usb_function_instance *fi) · 4 unmodified lines | ||
| 1359 | 1360 | status = -ENOMEM; |
| 1360 | 1361 | goto midi_free; |
| 1361 | 1362 | } |
| 1362 | − midi->in_ports = opts->in_ports; | |
| 1363 | 1363 | midi->out_ports = opts->out_ports; |
| 1364 | 1364 | midi->index = opts->index; |
| 1365 | 1365 | midi->buflen = opts->buflen; |
| @@ -337,7 +337,7 @@ typedef struct urb_priv { · 336 unmodified lines | ||
| 337 | 337 | u16 length; // # tds in this request |
| 338 | 338 | u16 td_cnt; // tds already serviced |
| 339 | 339 | struct list_head pending; |
| 340 | − struct td *td[]; // all TDs in this request | |
| 340 | + struct td *td[] __counted_by(length); // all TDs in this request | |
| 341 | 341 | |
| 342 | 342 | } urb_priv_t; |
| 343 | 343 | |
| @@ -1666,7 +1666,7 @@ struct xhci_scratchpad { · 1665 unmodified lines | ||
| 1666 | 1666 | struct urb_priv { |
| 1667 | 1667 | int num_tds; |
| 1668 | 1668 | int num_tds_done; |
| 1669 | − struct xhci_td td[]; | |
| 1669 | + struct xhci_td td[] __counted_by(num_tds); | |
| 1670 | 1670 | }; |
| 1671 | 1671 | |
| 1672 | 1672 | /* |
| @@ -60,7 +60,7 @@ struct vm_memory_region_batch { · 59 unmodified lines | ||
| 60 | 60 | u16 reserved[3]; |
| 61 | 61 | u32 regions_num; |
| 62 | 62 | u64 regions_gpa; |
| 63 | − struct vm_memory_region_op regions_op[]; | |
| 63 | + struct vm_memory_region_op regions_op[] __counted_by(regions_num); | |
| 64 | 64 | }; |
| 65 | 65 | |
| 66 | 66 | /** |
| @@ -250,11 +250,11 @@ int acrn_vm_ram_map(struct acrn_vm *vm, struct acrn_vm_memmap *memmap) · 249 unmodified lines | ||
| 250 | 250 | ret = -ENOMEM; |
| 251 | 251 | goto unmap_kernel_map; |
| 252 | 252 | } |
| 253 | + regions_info->regions_num = nr_regions; | |
| 253 | 254 | |
| 254 | 255 | /* Fill each vm_memory_region_op */ |
| 255 | 256 | vm_region = regions_info->regions_op; |
| 256 | 257 | regions_info->vmid = vm->vmid; |
| 257 | − regions_info->regions_num = nr_regions; | |
| 258 | 258 | regions_info->regions_gpa = virt_to_phys(vm_region); |
| 259 | 259 | user_vm_pa = memmap->user_vm_pa; |
| 260 | 260 | i = 0; |
| @@ -87,7 +87,7 @@ struct afs_addr_list { · 86 unmodified lines | ||
| 87 | 87 | enum dns_lookup_status status:8; |
| 88 | 88 | unsigned long failed; /* Mask of addrs that failed locally/ICMP */ |
| 89 | 89 | unsigned long responded; /* Mask of addrs that responded */ |
| 90 | − struct sockaddr_rxrpc addrs[]; | |
| 90 | + struct sockaddr_rxrpc addrs[] __counted_by(max_addrs); | |
| 91 | 91 | #define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8)) |
| 92 | 92 | }; |
| 93 | 93 | |
| @@ -705,7 +705,7 @@ struct afs_permits { · 611 unmodified lines | ||
| 705 | 705 | refcount_t usage; |
| 706 | 706 | unsigned short nr_permits; /* Number of records */ |
| 707 | 707 | bool invalidated; /* Invalidated due to key change */ |
| 708 | − struct afs_permit permits[]; /* List of permits sorted by key pointer */ | |
| 708 | + struct afs_permit permits[] __counted_by(nr_permits); /* List of permits sorted by key pointer */ | |
| 709 | 709 | }; |
| 710 | 710 | |
| 711 | 711 | /* |
| @@ -51,7 +51,7 @@ struct nfs4_file_layout_dsaddr { · 50 unmodified lines | ||
| 51 | 51 | u32 stripe_count; |
| 52 | 52 | u8 *stripe_indices; |
| 53 | 53 | u32 ds_num; |
| 54 | − struct nfs4_pnfs_ds *ds_list[]; | |
| 54 | + struct nfs4_pnfs_ds *ds_list[] __counted_by(ds_num); | |
| 55 | 55 | }; |
| 56 | 56 | |
| 57 | 57 | struct nfs4_filelayout_segment { |
| @@ -99,7 +99,7 @@ struct nfs4_ff_layout_segment { · 98 unmodified lines | ||
| 99 | 99 | u64 stripe_unit; |
| 100 | 100 | u32 flags; |
| 101 | 101 | u32 mirror_array_cnt; |
| 102 | − struct nfs4_ff_layout_mirror *mirror_array[]; | |
| 102 | + struct nfs4_ff_layout_mirror *mirror_array[] __counted_by(mirror_array_cnt); | |
| 103 | 103 | }; |
| 104 | 104 | |
| 105 | 105 | struct nfs4_flexfile_layout { |
| @@ -37,7 +37,7 @@ struct ocfs2_slot_info { · 36 unmodified lines | ||
| 37 | 37 | unsigned int si_blocks; |
| 38 | 38 | struct buffer_head **si_bh; |
| 39 | 39 | unsigned int si_num_slots; |
| 40 | − struct ocfs2_slot si_slots[]; | |
| 40 | + struct ocfs2_slot si_slots[] __counted_by(si_num_slots); | |
| 41 | 41 | }; |
| 42 | 42 | |
| 43 | 43 | |
| @@ -278,7 +278,7 @@ struct ceph_osd_request { · 277 unmodified lines | ||
| 278 | 278 | int r_attempts; |
| 279 | 279 | u32 r_map_dne_bound; |
| 280 | 280 | |
| 281 | − struct ceph_osd_req_op r_ops[]; | |
| 281 | + struct ceph_osd_req_op r_ops[] __counted_by(r_num_ops); | |
| 282 | 282 | }; |
| 283 | 283 | |
| 284 | 284 | struct ceph_request_redirect { |
| @@ -92,7 +92,7 @@ int parse_crashkernel_low(char *cmdline, unsigned long long system_ram, · 91 unmodified lines | ||
| 92 | 92 | struct crash_mem { |
| 93 | 93 | unsigned int max_nr_ranges; |
| 94 | 94 | unsigned int nr_ranges; |
| 95 | − struct range ranges[]; | |
| 95 | + struct range ranges[] __counted_by(max_nr_ranges); | |
| 96 | 96 | }; |
| 97 | 97 | |
| 98 | 98 | extern int crash_exclude_mem_range(struct crash_mem *mem, |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | #include <linux/init.h> |
| 13 | 13 | #include <linux/key.h> |
| 14 | 14 | #include <linux/atomic.h> |
| 15 | +#include <linux/refcount.h> | |
| 15 | 16 | #include <linux/uidgid.h> |
| 16 | 17 | #include <linux/sched.h> |
| 17 | 18 | #include <linux/sched/user.h> |
| @@ -23,7 +24,7 @@ struct inode; · 5 unmodified lines | ||
| 23 | 24 | * COW Supplementary groups list |
| 24 | 25 | */ |
| 25 | 26 | struct group_info { |
| 26 | − atomic_t usage; | |
| 27 | + refcount_t usage; | |
| 27 | 28 | int ngroups; |
| 28 | 29 | kgid_t gid[]; |
| 29 | 30 | } __randomize_layout; |
| @@ -39,7 +40,7 @@ struct group_info { · 9 unmodified lines | ||
| 39 | 40 | */ |
| 40 | 41 | static inline struct group_info *get_group_info(struct group_info *gi) |
| 41 | 42 | { |
| 42 | − atomic_inc(&gi->usage); | |
| 43 | + refcount_inc(&gi->usage); | |
| 43 | 44 | return gi; |
| 44 | 45 | } |
| 45 | 46 | |
| @@ -49,7 +50,7 @@ static inline struct group_info *get_group_info(struct group_info *gi) · 3 unmodified lines | ||
| 49 | 50 | */ |
| 50 | 51 | #define put_group_info(group_info) \ |
| 51 | 52 | do { \ |
| 52 | − if (atomic_dec_and_test(&(group_info)->usage)) \ | |
| 53 | + if (refcount_dec_and_test(&(group_info)->usage)) \ | |
| 53 | 54 | groups_free(group_info); \ |
| 54 | 55 | } while (0) |
| 55 | 56 | |
| @@ -664,7 +664,7 @@ struct kvm_irq_routing_table { · 663 unmodified lines | ||
| 664 | 664 | * Array indexed by gsi. Each entry contains list of irq chips |
| 665 | 665 | * the gsi is connected to. |
| 666 | 666 | */ |
| 667 | − struct hlist_head map[]; | |
| 667 | + struct hlist_head map[] __counted_by(nr_rt_entries); | |
| 668 | 668 | }; |
| 669 | 669 | #endif |
| 670 | 670 | |
| @@ -40,6 +40,6 @@ struct gsc_hwmon_platform_data { · 39 unmodified lines | ||
| 40 | 40 | unsigned int resolution; |
| 41 | 41 | unsigned int vreference; |
| 42 | 42 | unsigned int fan_base; |
| 43 | − struct gsc_hwmon_channel channels[]; | |
| 43 | + struct gsc_hwmon_channel channels[] __counted_by(nchannels); | |
| 44 | 44 | }; |
| 45 | 45 | #endif |
| @@ -277,10 +277,12 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, · 276 unmodified lines | ||
| 277 | 277 | */ |
| 278 | 278 | #define strtomem_pad(dest, src, pad) do { \ |
| 279 | 279 | const size_t _dest_len = __builtin_object_size(dest, 1); \ |
| 280 | + const size_t _src_len = __builtin_object_size(src, 1); \ | |
| 280 | 281 | \ |
| 281 | 282 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
| 282 | 283 | _dest_len == (size_t)-1); \ |
| 283 | − memcpy_and_pad(dest, _dest_len, src, strnlen(src, _dest_len), pad); \ | |
| 284 | + memcpy_and_pad(dest, _dest_len, src, \ | |
| 285 | + strnlen(src, min(_src_len, _dest_len)), pad); \ | |
| 284 | 286 | } while (0) |
| 285 | 287 | |
| 286 | 288 | /** |
| @@ -298,10 +300,11 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count, · 11 unmodified lines | ||
| 298 | 300 | */ |
| 299 | 301 | #define strtomem(dest, src) do { \ |
| 300 | 302 | const size_t _dest_len = __builtin_object_size(dest, 1); \ |
| 303 | + const size_t _src_len = __builtin_object_size(src, 1); \ | |
| 301 | 304 | \ |
| 302 | 305 | BUILD_BUG_ON(!__builtin_constant_p(_dest_len) || \ |
| 303 | 306 | _dest_len == (size_t)-1); \ |
| 304 | − memcpy(dest, src, min(_dest_len, strnlen(src, _dest_len))); \ | |
| 307 | + memcpy(dest, src, strnlen(src, min(_src_len, _dest_len))); \ | |
| 305 | 308 | } while (0) |
| 306 | 309 | |
| 307 | 310 | /** |
| @@ -21,10 +21,10 @@ static int __init early_hostname(char *arg) · 20 unmodified lines | ||
| 21 | 21 | { |
| 22 | 22 | size_t bufsize = sizeof(init_uts_ns.name.nodename); |
| 23 | 23 | size_t maxlen = bufsize - 1; |
| 24 | − size_t arglen; | |
| 24 | + ssize_t arglen; | |
| 25 | 25 | |
| 26 | − arglen = strlcpy(init_uts_ns.name.nodename, arg, bufsize); | |
| 27 | − if (arglen > maxlen) { | |
| 26 | + arglen = strscpy(init_uts_ns.name.nodename, arg, bufsize); | |
| 27 | + if (arglen < 0) { | |
| 28 | 28 | pr_warn("hostname parameter exceeds %zd characters and will be truncated", |
| 29 | 29 | maxlen); |
| 30 | 30 | } |
| @@ -0,0 +1,98 @@ | ||
| 1 | +# Help: Basic kernel hardening options | |
| 2 | +# | |
| 3 | +# These are considered the basic kernel hardening, self-protection, and | |
| 4 | +# attack surface reduction options. They are expected to have low (or | |
| 5 | +# no) performance impact on most workloads, and have a reasonable level | |
| 6 | +# of legacy API removals. | |
| 7 | + | |
| 8 | +# Make sure reporting of various hardening actions is possible. | |
| 9 | +CONFIG_BUG=y | |
| 10 | + | |
| 11 | +# Basic kernel memory permission enforcement. | |
| 12 | +CONFIG_STRICT_KERNEL_RWX=y | |
| 13 | +CONFIG_STRICT_MODULE_RWX=y | |
| 14 | +CONFIG_VMAP_STACK=y | |
| 15 | + | |
| 16 | +# Kernel image and memory ASLR. | |
| 17 | +CONFIG_RANDOMIZE_BASE=y | |
| 18 | +CONFIG_RANDOMIZE_MEMORY=y | |
| 19 | + | |
| 20 | +# Randomize allocator freelists, harden metadata. | |
| 21 | +CONFIG_SLAB_FREELIST_RANDOM=y | |
| 22 | +CONFIG_SLAB_FREELIST_HARDENED=y | |
| 23 | +CONFIG_SHUFFLE_PAGE_ALLOCATOR=y | |
| 24 | +CONFIG_RANDOM_KMALLOC_CACHES=y | |
| 25 | + | |
| 26 | +# Randomize kernel stack offset on syscall entry. | |
| 27 | +CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y | |
| 28 | + | |
| 29 | +# Basic stack frame overflow protection. | |
| 30 | +CONFIG_STACKPROTECTOR=y | |
| 31 | +CONFIG_STACKPROTECTOR_STRONG=y | |
| 32 | + | |
| 33 | +# Basic buffer length bounds checking. | |
| 34 | +CONFIG_HARDENED_USERCOPY=y | |
| 35 | +CONFIG_FORTIFY_SOURCE=y | |
| 36 | + | |
| 37 | +# Basic array index bounds checking. | |
| 38 | +CONFIG_UBSAN=y | |
| 39 | +CONFIG_UBSAN_TRAP=y | |
| 40 | +CONFIG_UBSAN_BOUNDS=y | |
| 41 | +# CONFIG_UBSAN_SHIFT is not set | |
| 42 | +# CONFIG_UBSAN_DIV_ZERO | |
| 43 | +# CONFIG_UBSAN_UNREACHABLE | |
| 44 | +# CONFIG_UBSAN_BOOL | |
| 45 | +# CONFIG_UBSAN_ENUM | |
| 46 | +# CONFIG_UBSAN_ALIGNMENT | |
| 47 | +CONFIG_UBSAN_SANITIZE_ALL=y | |
| 48 | + | |
| 49 | +# Linked list integrity checking. | |
| 50 | +CONFIG_LIST_HARDENED=y | |
| 51 | + | |
| 52 | +# Initialize all heap variables to zero on allocation. | |
| 53 | +CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y | |
| 54 | + | |
| 55 | +# Initialize all stack variables to zero on function entry. | |
| 56 | +CONFIG_INIT_STACK_ALL_ZERO=y | |
| 57 | + | |
| 58 | +# Wipe RAM at reboot via EFI. For more details, see: | |
| 59 | +# https://trustedcomputinggroup.org/resource/pc-client-work-group-platform-reset-attack-mitigation-specification/ | |
| 60 | +# https://bugzilla.redhat.com/show_bug.cgi?id=1532058 | |
| 61 | +CONFIG_RESET_ATTACK_MITIGATION=y | |
| 62 | + | |
| 63 | +# Disable DMA between EFI hand-off and the kernel's IOMMU setup. | |
| 64 | +CONFIG_EFI_DISABLE_PCI_DMA=y | |
| 65 | + | |
| 66 | +# Force IOMMU TLB invalidation so devices will never be able to access stale | |
| 67 | +# data content. | |
| 68 | +CONFIG_IOMMU_SUPPORT=y | |
| 69 | +CONFIG_IOMMU_DEFAULT_DMA_STRICT=y | |
| 70 | + | |
| 71 | +# Do not allow direct physical memory access to non-device memory. | |
| 72 | +CONFIG_STRICT_DEVMEM=y | |
| 73 | +CONFIG_IO_STRICT_DEVMEM=y | |
| 74 | + | |
| 75 | +# Provide userspace with seccomp BPF API for syscall attack surface reduction. | |
| 76 | +CONFIG_SECCOMP=y | |
| 77 | +CONFIG_SECCOMP_FILTER=y | |
| 78 | + | |
| 79 | +# Provides some protections against SYN flooding. | |
| 80 | +CONFIG_SYN_COOKIES=y | |
| 81 | + | |
| 82 | +# Attack surface reduction: do not autoload TTY line disciplines. | |
| 83 | +# CONFIG_LDISC_AUTOLOAD is not set | |
| 84 | + | |
| 85 | +# Dangerous; enabling this disables userspace brk ASLR. | |
| 86 | +# CONFIG_COMPAT_BRK is not set | |
| 87 | + | |
| 88 | +# Dangerous; exposes kernel text image layout. | |
| 89 | +# CONFIG_PROC_KCORE is not set | |
| 90 | + | |
| 91 | +# Dangerous; enabling this disables userspace VDSO ASLR. | |
| 92 | +# CONFIG_COMPAT_VDSO is not set | |
| 93 | + | |
| 94 | +# Attack surface reduction: Use the modern PTY interface (devpts) only. | |
| 95 | +# CONFIG_LEGACY_PTYS is not set | |
| 96 | + | |
| 97 | +# Attack surface reduction: Use only modesetting video drivers. | |
| 98 | +# CONFIG_DRM_LEGACY is not set | |
| @@ -36,7 +36,7 @@ do { \ · 35 unmodified lines | ||
| 36 | 36 | static struct kmem_cache *cred_jar; |
| 37 | 37 | |
| 38 | 38 | /* init to 2 - one for init_task, one to ensure it is never freed */ |
| 39 | −static struct group_info init_groups = { .usage = ATOMIC_INIT(2) }; | |
| 39 | +static struct group_info init_groups = { .usage = REFCOUNT_INIT(2) }; | |
| 40 | 40 | |
| 41 | 41 | /* |
| 42 | 42 | * The initial credentials for the initial task |
| @@ -19,7 +19,7 @@ struct group_info *groups_alloc(int gidsetsize) · 18 unmodified lines | ||
| 19 | 19 | if (!gi) |
| 20 | 20 | return NULL; |
| 21 | 21 | |
| 22 | − atomic_set(&gi->usage, 1); | |
| 22 | + refcount_set(&gi->usage, 1); | |
| 23 | 23 | gi->ngroups = gidsetsize; |
| 24 | 24 | return gi; |
| 25 | 25 | } |
| @@ -254,10 +254,10 @@ static int init_uevent_argv(struct kobj_uevent_env *env, const char *subsystem) · 253 unmodified lines | ||
| 254 | 254 | int buffer_size = sizeof(env->buf) - env->buflen; |
| 255 | 255 | int len; |
| 256 | 256 | |
| 257 | − len = strlcpy(&env->buf[env->buflen], subsystem, buffer_size); | |
| 258 | − if (len >= buffer_size) { | |
| 259 | − pr_warn("init_uevent_argv: buffer size of %d too small, needed %d\n", | |
| 260 | − buffer_size, len); | |
| 257 | + len = strscpy(&env->buf[env->buflen], subsystem, buffer_size); | |
| 258 | + if (len < 0) { | |
| 259 | + pr_warn("%s: insufficient buffer space (%u left) for %s\n", | |
| 260 | + __func__, buffer_size, subsystem); | |
| 261 | 261 | return -ENOMEM; |
| 262 | 262 | } |
| 263 | 263 | |
| @@ -191,12 +191,14 @@ static void partition_struct(tree *fields, unsigned long length, struct partitio · 190 unmodified lines | ||
| 191 | 191 | |
| 192 | 192 | static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prng_state) |
| 193 | 193 | { |
| 194 | − unsigned long i, x; | |
| 194 | + unsigned long i, x, index; | |
| 195 | 195 | struct partition_group size_group[length]; |
| 196 | 196 | unsigned long num_groups = 0; |
| 197 | 197 | unsigned long randnum; |
| 198 | 198 | |
| 199 | 199 | partition_struct(newtree, length, (struct partition_group *)&size_group, &num_groups); |
| 200 | + | |
| 201 | + /* FIXME: this group shuffle is currently a no-op. */ | |
| 200 | 202 | for (i = num_groups - 1; i > 0; i--) { |
| 201 | 203 | struct partition_group tmp; |
| 202 | 204 | randnum = ranval(prng_state) % (i + 1); |
| @@ -206,11 +208,14 @@ static void performance_shuffle(tree *newtree, unsigned long length, ranctx *prn · 3 unmodified lines | ||
| 206 | 208 | } |
| 207 | 209 | |
| 208 | 210 | for (x = 0; x < num_groups; x++) { |
| 209 | − for (i = size_group[x].start + size_group[x].length - 1; i > size_group[x].start; i--) { | |
| 211 | + for (index = size_group[x].length - 1; index > 0; index--) { | |
| 210 | 212 | tree tmp; |
| 213 | + | |
| 214 | + i = size_group[x].start + index; | |
| 211 | 215 | if (DECL_BIT_FIELD_TYPE(newtree[i])) |
| 212 | 216 | continue; |
| 213 | − randnum = ranval(prng_state) % (i + 1); | |
| 217 | + randnum = ranval(prng_state) % (index + 1); | |
| 218 | + randnum += size_group[x].start; | |
| 214 | 219 | // we could handle this case differently if desired |
| 215 | 220 | if (DECL_BIT_FIELD_TYPE(newtree[randnum])) |
| 216 | 221 | continue; |
| @@ -29,7 +29,7 @@ struct modsig { · 28 unmodified lines | ||
| 29 | 29 | * storing the signature. |
| 30 | 30 | */ |
| 31 | 31 | int raw_pkcs7_len; |
| 32 | − u8 raw_pkcs7[]; | |
| 32 | + u8 raw_pkcs7[] __counted_by(raw_pkcs7_len); | |
| 33 | 33 | }; |
| 34 | 34 | |
| 35 | 35 | /* |
| @@ -65,10 +65,11 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, · 29 unmodified lines | ||
| 65 | 65 | buf_len -= sig_len + sizeof(*sig); |
| 66 | 66 | |
| 67 | 67 | /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ |
| 68 | − hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL); | |
| 68 | + hdr = kzalloc(struct_size(hdr, raw_pkcs7, sig_len), GFP_KERNEL); | |
| 69 | 69 | if (!hdr) |
| 70 | 70 | return -ENOMEM; |
| 71 | 71 | |
| 72 | + hdr->raw_pkcs7_len = sig_len; | |
| 72 | 73 | hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); |
| 73 | 74 | if (IS_ERR(hdr->pkcs7_msg)) { |
| 74 | 75 | rc = PTR_ERR(hdr->pkcs7_msg); |
| @@ -77,7 +78,6 @@ int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, · 2 unmodified lines | ||
| 77 | 78 | } |
| 78 | 79 | |
| 79 | 80 | memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len); |
| 80 | − hdr->raw_pkcs7_len = sig_len; | |
| 81 | 81 | |
| 82 | 82 | /* We don't know the hash algorithm yet. */ |
| 83 | 83 | hdr->hash_algo = HASH_ALGO__LAST; |
| @@ -9,7 +9,6 @@ CONFIG_INIT_ON_FREE_DEFAULT_ON=y · 8 unmodified lines | ||
| 9 | 9 | CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y |
| 10 | 10 | CONFIG_UBSAN=y |
| 11 | 11 | CONFIG_UBSAN_BOUNDS=y |
| 12 | −CONFIG_UBSAN_TRAP=y | |
| 13 | 12 | CONFIG_STACKPROTECTOR_STRONG=y |
| 14 | 13 | CONFIG_SLUB_DEBUG=y |
| 15 | 14 | CONFIG_SLUB_DEBUG_ON=y |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | #PANIC |
| 2 | +#PANIC_STOP_IRQOFF Crashes entire system | |
| 2 | 3 | BUG kernel BUG at |
| 3 | 4 | WARNING WARNING: |
| 4 | 5 | WARNING_MESSAGE message trigger |
| @@ -7,7 +8,7 @@ EXCEPTION · 2 unmodified lines | ||
| 7 | 8 | #EXHAUST_STACK Corrupts memory on failure |
| 8 | 9 | #CORRUPT_STACK Crashes entire system on success |
| 9 | 10 | #CORRUPT_STACK_STRONG Crashes entire system on success |
| 10 | −ARRAY_BOUNDS | |
| 11 | +ARRAY_BOUNDS call trace:|UBSAN: array-index-out-of-bounds | |
| 11 | 12 | CORRUPT_LIST_ADD list_add corruption |
| 12 | 13 | CORRUPT_LIST_DEL list_del corruption |
| 13 | 14 | STACK_GUARD_PAGE_LEADING |