From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 35BFD1382C5 for ; Thu, 10 Jun 2021 11:47:00 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 7ECEEE08A0; Thu, 10 Jun 2021 11:46:59 +0000 (UTC) Received: from smtp.gentoo.org (dev.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id 5B209E08A0 for ; Thu, 10 Jun 2021 11:46:59 +0000 (UTC) Received: from oystercatcher.gentoo.org (unknown [IPv6:2a01:4f8:202:4333:225:90ff:fed9:fc84]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.gentoo.org (Postfix) with ESMTPS id 50BD8335DC3 for ; Thu, 10 Jun 2021 11:46:58 +0000 (UTC) Received: from localhost.localdomain (localhost [IPv6:::1]) by oystercatcher.gentoo.org (Postfix) with ESMTP id CF81279A for ; Thu, 10 Jun 2021 11:46:56 +0000 (UTC) From: "Mike Pagano" To: gentoo-commits@lists.gentoo.org Content-Transfer-Encoding: 8bit Content-type: text/plain; charset=UTF-8 Reply-To: gentoo-dev@lists.gentoo.org, "Mike Pagano" Message-ID: <1623325604.6b2a68bf1a50782b86e60e62e8f5b8fa1f87dd59.mpagano@gentoo> Subject: [gentoo-commits] proj/linux-patches:4.19 commit in: / X-VCS-Repository: proj/linux-patches X-VCS-Files: 0000_README 1193_linux-4.19.194.patch X-VCS-Directories: / X-VCS-Committer: mpagano X-VCS-Committer-Name: Mike Pagano X-VCS-Revision: 6b2a68bf1a50782b86e60e62e8f5b8fa1f87dd59 X-VCS-Branch: 4.19 Date: Thu, 10 Jun 2021 11:46:56 +0000 (UTC) Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-commits@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply X-Archives-Salt: 26d28f42-c450-435c-9e3a-2a1b990e26ec X-Archives-Hash: 1620883e06c837c8b292a1ad4ca80097 commit: 6b2a68bf1a50782b86e60e62e8f5b8fa1f87dd59 Author: Mike Pagano gentoo org> AuthorDate: Thu Jun 10 11:46:44 2021 +0000 Commit: Mike Pagano gentoo org> CommitDate: Thu Jun 10 11:46:44 2021 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=6b2a68bf Linux patch 4.19.194 Signed-off-by: Mike Pagano gentoo.org> 0000_README | 4 + 1193_linux-4.19.194.patch | 2835 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 2839 insertions(+) diff --git a/0000_README b/0000_README index 757010f..50ca271 100644 --- a/0000_README +++ b/0000_README @@ -811,6 +811,10 @@ Patch: 1192_linux-4.19.193.patch From: https://www.kernel.org Desc: Linux 4.19.193 +Patch: 1193_linux-4.19.194.patch +From: https://www.kernel.org +Desc: Linux 4.19.194 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1193_linux-4.19.194.patch b/1193_linux-4.19.194.patch new file mode 100644 index 0000000..4d073e2 --- /dev/null +++ b/1193_linux-4.19.194.patch @@ -0,0 +1,2835 @@ +diff --git a/Makefile b/Makefile +index e5d41b6792d7f..8ea26b64b3347 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 193 ++SUBLEVEL = 194 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c +index fe97b2ad82b91..98e8bc9195830 100644 +--- a/arch/arm64/kvm/sys_regs.c ++++ b/arch/arm64/kvm/sys_regs.c +@@ -426,14 +426,14 @@ static bool trap_bvr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg); + + return true; + } +@@ -441,7 +441,7 @@ static bool trap_bvr(struct kvm_vcpu *vcpu, + static int set_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -451,7 +451,7 @@ static int set_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static int get_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -461,21 +461,21 @@ static int get_bvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static void reset_bvr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_bvr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_bvr[rd->CRm] = rd->val; + } + + static bool trap_bcr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg); + + return true; + } +@@ -483,7 +483,7 @@ static bool trap_bcr(struct kvm_vcpu *vcpu, + static int set_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -494,7 +494,7 @@ static int set_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static int get_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -504,22 +504,22 @@ static int get_bcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static void reset_bcr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_bcr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_bcr[rd->CRm] = rd->val; + } + + static bool trap_wvr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, +- vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, ++ vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]); + + return true; + } +@@ -527,7 +527,7 @@ static bool trap_wvr(struct kvm_vcpu *vcpu, + static int set_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -537,7 +537,7 @@ static int set_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static int get_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -547,21 +547,21 @@ static int get_wvr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static void reset_wvr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_wvr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_wvr[rd->CRm] = rd->val; + } + + static bool trap_wcr(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *rd) + { +- u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg]; ++ u64 *dbg_reg = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm]; + + if (p->is_write) + reg_to_dbg(vcpu, p, dbg_reg); + else + dbg_to_reg(vcpu, p, dbg_reg); + +- trace_trap_reg(__func__, rd->reg, p->is_write, *dbg_reg); ++ trace_trap_reg(__func__, rd->CRm, p->is_write, *dbg_reg); + + return true; + } +@@ -569,7 +569,7 @@ static bool trap_wcr(struct kvm_vcpu *vcpu, + static int set_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm]; + + if (copy_from_user(r, uaddr, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -579,7 +579,7 @@ static int set_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static int get_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + const struct kvm_one_reg *reg, void __user *uaddr) + { +- __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg]; ++ __u64 *r = &vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm]; + + if (copy_to_user(uaddr, r, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; +@@ -589,7 +589,7 @@ static int get_wcr(struct kvm_vcpu *vcpu, const struct sys_reg_desc *rd, + static void reset_wcr(struct kvm_vcpu *vcpu, + const struct sys_reg_desc *rd) + { +- vcpu->arch.vcpu_debug_state.dbg_wcr[rd->reg] = rd->val; ++ vcpu->arch.vcpu_debug_state.dbg_wcr[rd->CRm] = rd->val; + } + + static void reset_amair_el1(struct kvm_vcpu *vcpu, const struct sys_reg_desc *r) +diff --git a/arch/x86/include/asm/apic.h b/arch/x86/include/asm/apic.h +index b5354e216b07c..163c2af44a44f 100644 +--- a/arch/x86/include/asm/apic.h ++++ b/arch/x86/include/asm/apic.h +@@ -172,6 +172,7 @@ static inline int apic_is_clustered_box(void) + extern int setup_APIC_eilvt(u8 lvt_off, u8 vector, u8 msg_type, u8 mask); + extern void lapic_assign_system_vectors(void); + extern void lapic_assign_legacy_vector(unsigned int isairq, bool replace); ++extern void lapic_update_legacy_vectors(void); + extern void lapic_online(void); + extern void lapic_offline(void); + +diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c +index da6b52c709641..9791828f3fcdd 100644 +--- a/arch/x86/kernel/apic/apic.c ++++ b/arch/x86/kernel/apic/apic.c +@@ -2507,6 +2507,7 @@ void __init apic_bsp_setup(bool upmode) + end_local_APIC_setup(); + irq_remap_enable_fault_handling(); + setup_IO_APIC(); ++ lapic_update_legacy_vectors(); + } + + #ifdef CONFIG_UP_LATE_INIT +diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c +index f0d0535e8f345..dc7c759442f17 100644 +--- a/arch/x86/kernel/apic/vector.c ++++ b/arch/x86/kernel/apic/vector.c +@@ -682,6 +682,26 @@ void lapic_assign_legacy_vector(unsigned int irq, bool replace) + irq_matrix_assign_system(vector_matrix, ISA_IRQ_VECTOR(irq), replace); + } + ++void __init lapic_update_legacy_vectors(void) ++{ ++ unsigned int i; ++ ++ if (IS_ENABLED(CONFIG_X86_IO_APIC) && nr_ioapics > 0) ++ return; ++ ++ /* ++ * If the IO/APIC is disabled via config, kernel command line or ++ * lack of enumeration then all legacy interrupts are routed ++ * through the PIC. Make sure that they are marked as legacy ++ * vectors. PIC_CASCADE_IRQ has already been marked in ++ * lapic_assign_system_vectors(). ++ */ ++ for (i = 0; i < nr_legacy_irqs(); i++) { ++ if (i != PIC_CASCADE_IR) ++ lapic_assign_legacy_vector(i, true); ++ } ++} ++ + void __init lapic_assign_system_vectors(void) + { + unsigned int i, vector = 0; +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index 8cb9277aa6ff2..ad24e67772778 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -4033,7 +4033,7 @@ static int cr_interception(struct vcpu_svm *svm) + err = 0; + if (cr >= 16) { /* mov to cr */ + cr -= 16; +- val = kvm_register_read(&svm->vcpu, reg); ++ val = kvm_register_readl(&svm->vcpu, reg); + switch (cr) { + case 0: + if (!check_selective_cr0_intercepted(svm, val)) +@@ -4078,7 +4078,7 @@ static int cr_interception(struct vcpu_svm *svm) + kvm_queue_exception(&svm->vcpu, UD_VECTOR); + return 1; + } +- kvm_register_write(&svm->vcpu, reg, val); ++ kvm_register_writel(&svm->vcpu, reg, val); + } + return kvm_complete_insn_gp(&svm->vcpu, err); + } +@@ -4108,13 +4108,13 @@ static int dr_interception(struct vcpu_svm *svm) + if (dr >= 16) { /* mov to DRn */ + if (!kvm_require_dr(&svm->vcpu, dr - 16)) + return 1; +- val = kvm_register_read(&svm->vcpu, reg); ++ val = kvm_register_readl(&svm->vcpu, reg); + kvm_set_dr(&svm->vcpu, dr - 16, val); + } else { + if (!kvm_require_dr(&svm->vcpu, dr)) + return 1; + kvm_get_dr(&svm->vcpu, dr, &val); +- kvm_register_write(&svm->vcpu, reg, val); ++ kvm_register_writel(&svm->vcpu, reg, val); + } + + return kvm_skip_emulated_instruction(&svm->vcpu); +diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c +index 92a1468610867..d60e57d14c859 100644 +--- a/drivers/acpi/bus.c ++++ b/drivers/acpi/bus.c +@@ -1054,16 +1054,6 @@ void __init acpi_early_init(void) + goto error0; + } + +- if (!acpi_gbl_execute_tables_as_methods && +- acpi_gbl_group_module_level_code) { +- status = acpi_load_tables(); +- if (ACPI_FAILURE(status)) { +- printk(KERN_ERR PREFIX +- "Unable to load the System Description Tables\n"); +- goto error0; +- } +- } +- + #ifdef CONFIG_X86 + if (!acpi_ioapic) { + /* compatible (0) means level (3) */ +@@ -1133,26 +1123,24 @@ static int __init acpi_bus_init(void) + + acpi_os_initialize1(); + ++ status = acpi_load_tables(); ++ if (ACPI_FAILURE(status)) { ++ printk(KERN_ERR PREFIX ++ "Unable to load the System Description Tables\n"); ++ goto error1; ++ } ++ + /* +- * ACPI 2.0 requires the EC driver to be loaded and work before +- * the EC device is found in the namespace (i.e. before +- * acpi_load_tables() is called). ++ * ACPI 2.0 requires the EC driver to be loaded and work before the EC ++ * device is found in the namespace. ++ * ++ * This is accomplished by looking for the ECDT table and getting the EC ++ * parameters out of that. + * +- * This is accomplished by looking for the ECDT table, and getting +- * the EC parameters out of that. ++ * Do that before calling acpi_initialize_objects() which may trigger EC ++ * address space accesses. + */ +- status = acpi_ec_ecdt_probe(); +- /* Ignore result. Not having an ECDT is not fatal. */ +- +- if (acpi_gbl_execute_tables_as_methods || +- !acpi_gbl_group_module_level_code) { +- status = acpi_load_tables(); +- if (ACPI_FAILURE(status)) { +- printk(KERN_ERR PREFIX +- "Unable to load the System Description Tables\n"); +- goto error1; +- } +- } ++ acpi_ec_ecdt_probe(); + + status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE); + if (ACPI_FAILURE(status)) { +diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c +index 116989cf3d457..97da083afd324 100644 +--- a/drivers/firmware/efi/cper.c ++++ b/drivers/firmware/efi/cper.c +@@ -275,8 +275,7 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg) + if (!msg || !(mem->validation_bits & CPER_MEM_VALID_MODULE_HANDLE)) + return 0; + +- n = 0; +- len = CPER_REC_LEN - 1; ++ len = CPER_REC_LEN; + dmi_memdev_name(mem->mem_dev_handle, &bank, &device); + if (bank && device) + n = snprintf(msg, len, "DIMM location: %s %s ", bank, device); +@@ -285,7 +284,6 @@ static int cper_dimm_err_location(struct cper_mem_err_compact *mem, char *msg) + "DIMM location: not present. DMI handle: 0x%.4x ", + mem->mem_dev_handle); + +- msg[n] = '\0'; + return n; + } + +diff --git a/drivers/firmware/efi/memattr.c b/drivers/firmware/efi/memattr.c +index aac972b056d91..e0889922cc6d7 100644 +--- a/drivers/firmware/efi/memattr.c ++++ b/drivers/firmware/efi/memattr.c +@@ -69,11 +69,6 @@ static bool entry_is_valid(const efi_memory_desc_t *in, efi_memory_desc_t *out) + return false; + } + +- if (!(in->attribute & (EFI_MEMORY_RO | EFI_MEMORY_XP))) { +- pr_warn("Entry attributes invalid: RO and XP bits both cleared\n"); +- return false; +- } +- + if (PAGE_SIZE > EFI_PAGE_SIZE && + (!PAGE_ALIGNED(in->phys_addr) || + !PAGE_ALIGNED(in->num_pages << EFI_PAGE_SHIFT))) { +diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c +index ccda72f748ee5..c20945ed1dc19 100644 +--- a/drivers/hid/hid-multitouch.c ++++ b/drivers/hid/hid-multitouch.c +@@ -588,9 +588,13 @@ static struct mt_report_data *mt_allocate_report_data(struct mt_device *td, + if (!(HID_MAIN_ITEM_VARIABLE & field->flags)) + continue; + +- for (n = 0; n < field->report_count; n++) { +- if (field->usage[n].hid == HID_DG_CONTACTID) +- rdata->is_mt_collection = true; ++ if (field->logical == HID_DG_FINGER || td->hdev->group != HID_GROUP_MULTITOUCH_WIN_8) { ++ for (n = 0; n < field->report_count; n++) { ++ if (field->usage[n].hid == HID_DG_CONTACTID) { ++ rdata->is_mt_collection = true; ++ break; ++ } ++ } + } + } + +diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c +index 1f8d403d3db4d..19f4b807a5d1d 100644 +--- a/drivers/hid/i2c-hid/i2c-hid-core.c ++++ b/drivers/hid/i2c-hid/i2c-hid-core.c +@@ -1160,8 +1160,8 @@ static int i2c_hid_probe(struct i2c_client *client, + hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); + hid->product = le16_to_cpu(ihid->hdesc.wProductID); + +- snprintf(hid->name, sizeof(hid->name), "%s %04hX:%04hX", +- client->name, hid->vendor, hid->product); ++ snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", ++ client->name, (u16)hid->vendor, (u16)hid->product); + strlcpy(hid->phys, dev_name(&client->dev), sizeof(hid->phys)); + + ihid->quirks = i2c_hid_lookup_quirk(hid->vendor, hid->product); +diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c +index 08174d341f4a1..bc75f1efa0f4c 100644 +--- a/drivers/hid/usbhid/hid-pidff.c ++++ b/drivers/hid/usbhid/hid-pidff.c +@@ -1304,6 +1304,7 @@ int hid_pidff_init(struct hid_device *hid) + + if (pidff->pool[PID_DEVICE_MANAGED_POOL].value && + pidff->pool[PID_DEVICE_MANAGED_POOL].value[0] == 0) { ++ error = -EPERM; + hid_notice(hid, + "device does not support device managed pool\n"); + goto fail; +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 6033970fb667b..ebcf4ea66385a 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -5252,7 +5252,6 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp) + + pf->fw_fid = le16_to_cpu(resp->fid); + pf->port_id = le16_to_cpu(resp->port_id); +- bp->dev->dev_port = pf->port_id; + memcpy(pf->mac_addr, resp->mac_address, ETH_ALEN); + pf->first_vf_id = le16_to_cpu(resp->first_vf_id); + pf->max_vfs = le16_to_cpu(resp->max_vfs); +diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +index a10756f0b0d8b..7f94b445595ce 100644 +--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c ++++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +@@ -1071,11 +1071,14 @@ static struct sk_buff *ixgbevf_run_xdp(struct ixgbevf_adapter *adapter, + case XDP_TX: + xdp_ring = adapter->xdp_ring[rx_ring->queue_index]; + result = ixgbevf_xmit_xdp_ring(xdp_ring, xdp); ++ if (result == IXGBEVF_XDP_CONSUMED) ++ goto out_failure; + break; + default: + bpf_warn_invalid_xdp_action(act); + /* fallthrough */ + case XDP_ABORTED: ++out_failure: + trace_xdp_exception(rx_ring->netdev, xdp_prog, act); + /* fallthrough -- handle aborts by dropping packet */ + case XDP_DROP: +diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c +index faca70c3647d3..82ec00a7370d4 100644 +--- a/drivers/net/usb/cdc_ncm.c ++++ b/drivers/net/usb/cdc_ncm.c +@@ -1590,6 +1590,15 @@ cdc_ncm_speed_change(struct usbnet *dev, + uint32_t rx_speed = le32_to_cpu(data->DLBitRRate); + uint32_t tx_speed = le32_to_cpu(data->ULBitRate); + ++ /* if the speed hasn't changed, don't report it. ++ * RTL8156 shipped before 2021 sends notification about every 32ms. ++ */ ++ if (dev->rx_speed == rx_speed && dev->tx_speed == tx_speed) ++ return; ++ ++ dev->rx_speed = rx_speed; ++ dev->tx_speed = tx_speed; ++ + /* + * Currently the USB-NET API does not support reporting the actual + * device speed. Do print it instead. +@@ -1633,7 +1642,8 @@ static void cdc_ncm_status(struct usbnet *dev, struct urb *urb) + * USB_CDC_NOTIFY_NETWORK_CONNECTION notification shall be + * sent by device after USB_CDC_NOTIFY_SPEED_CHANGE. + */ +- usbnet_link_change(dev, !!event->wValue, 0); ++ if (netif_carrier_ok(dev->net) != !!event->wValue) ++ usbnet_link_change(dev, !!event->wValue, 0); + break; + + case USB_CDC_NOTIFY_SPEED_CHANGE: +diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c +index af26a8a20e0bc..5919ecb7d4b76 100644 +--- a/drivers/usb/dwc2/core_intr.c ++++ b/drivers/usb/dwc2/core_intr.c +@@ -700,7 +700,11 @@ static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg, + dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN); + + hsotg->hibernated = 0; ++ ++#if IS_ENABLED(CONFIG_USB_DWC2_HOST) || \ ++ IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE) + hsotg->bus_suspended = 0; ++#endif + + if (gpwrdn & GPWRDN_IDSTS) { + hsotg->op_state = OTG_STATE_B_PERIPHERAL; +diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig +index 42dc1d3d71cf0..fcbfd0aacebcd 100644 +--- a/drivers/vfio/pci/Kconfig ++++ b/drivers/vfio/pci/Kconfig +@@ -1,6 +1,7 @@ + config VFIO_PCI + tristate "VFIO support for PCI devices" + depends on VFIO && PCI && EVENTFD ++ depends on MMU + select VFIO_VIRQFD + select IRQ_BYPASS_MANAGER + help +diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c +index a1a26465d224c..86e917f1cc211 100644 +--- a/drivers/vfio/pci/vfio_pci_config.c ++++ b/drivers/vfio/pci/vfio_pci_config.c +@@ -1579,7 +1579,7 @@ static int vfio_ecap_init(struct vfio_pci_device *vdev) + if (len == 0xFF) { + len = vfio_ext_cap_len(vdev, ecap, epos); + if (len < 0) +- return ret; ++ return len; + } + } + +diff --git a/drivers/vfio/platform/vfio_platform_common.c b/drivers/vfio/platform/vfio_platform_common.c +index 460760d0becfe..c29fc6844f845 100644 +--- a/drivers/vfio/platform/vfio_platform_common.c ++++ b/drivers/vfio/platform/vfio_platform_common.c +@@ -295,7 +295,7 @@ err_irq: + vfio_platform_regions_cleanup(vdev); + err_reg: + mutex_unlock(&driver_lock); +- module_put(THIS_MODULE); ++ module_put(vdev->parent_module); + return ret; + } + +diff --git a/drivers/xen/xen-pciback/vpci.c b/drivers/xen/xen-pciback/vpci.c +index f6ba18191c0f9..30313084f06c1 100644 +--- a/drivers/xen/xen-pciback/vpci.c ++++ b/drivers/xen/xen-pciback/vpci.c +@@ -69,7 +69,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, + struct pci_dev *dev, int devid, + publish_pci_dev_cb publish_cb) + { +- int err = 0, slot, func = -1; ++ int err = 0, slot, func = PCI_FUNC(dev->devfn); + struct pci_dev_entry *t, *dev_entry; + struct vpci_dev_data *vpci_dev = pdev->pci_dev_data; + +@@ -94,23 +94,26 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, + + /* + * Keep multi-function devices together on the virtual PCI bus, except +- * virtual functions. ++ * that we want to keep virtual functions at func 0 on their own. They ++ * aren't multi-function devices and hence their presence at func 0 ++ * may cause guests to not scan the other functions. + */ +- if (!dev->is_virtfn) { ++ if (!dev->is_virtfn || func) { + for (slot = 0; slot < PCI_SLOT_MAX; slot++) { + if (list_empty(&vpci_dev->dev_list[slot])) + continue; + + t = list_entry(list_first(&vpci_dev->dev_list[slot]), + struct pci_dev_entry, list); ++ if (t->dev->is_virtfn && !PCI_FUNC(t->dev->devfn)) ++ continue; + + if (match_slot(dev, t->dev)) { + pr_info("vpci: %s: assign to virtual slot %d func %d\n", + pci_name(dev), slot, +- PCI_FUNC(dev->devfn)); ++ func); + list_add_tail(&dev_entry->list, + &vpci_dev->dev_list[slot]); +- func = PCI_FUNC(dev->devfn); + goto unlock; + } + } +@@ -123,7 +126,6 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, + pci_name(dev), slot); + list_add_tail(&dev_entry->list, + &vpci_dev->dev_list[slot]); +- func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn); + goto unlock; + } + } +diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c +index ce5e0f6c6af4f..bf46ed74eae67 100644 +--- a/fs/btrfs/extent-tree.c ++++ b/fs/btrfs/extent-tree.c +@@ -1984,16 +1984,20 @@ int btrfs_discard_extent(struct btrfs_fs_info *fs_info, u64 bytenr, + for (i = 0; i < bbio->num_stripes; i++, stripe++) { + u64 bytes; + struct request_queue *req_q; ++ struct btrfs_device *device = stripe->dev; + +- if (!stripe->dev->bdev) { ++ if (!device->bdev) { + ASSERT(btrfs_test_opt(fs_info, DEGRADED)); + continue; + } +- req_q = bdev_get_queue(stripe->dev->bdev); ++ req_q = bdev_get_queue(device->bdev); + if (!blk_queue_discard(req_q)) + continue; + +- ret = btrfs_issue_discard(stripe->dev->bdev, ++ if (!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state)) ++ continue; ++ ++ ret = btrfs_issue_discard(device->bdev, + stripe->physical, + stripe->length, + &bytes); +@@ -2501,7 +2505,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans, + head->qgroup_reserved); + btrfs_delayed_ref_unlock(head); + btrfs_put_delayed_ref_head(head); +- return 0; ++ return ret; + } + + /* +diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c +index 1b8a04b767ffd..40db31b69ef7b 100644 +--- a/fs/btrfs/file-item.c ++++ b/fs/btrfs/file-item.c +@@ -586,7 +586,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, + u64 end_byte = bytenr + len; + u64 csum_end; + struct extent_buffer *leaf; +- int ret; ++ int ret = 0; + u16 csum_size = btrfs_super_csum_size(fs_info->super_copy); + int blocksize_bits = fs_info->sb->s_blocksize_bits; + +@@ -605,6 +605,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, + path->leave_spinning = 1; + ret = btrfs_search_slot(trans, root, &key, path, -1, 1); + if (ret > 0) { ++ ret = 0; + if (path->slots[0] == 0) + break; + path->slots[0]--; +@@ -661,7 +662,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, + ret = btrfs_del_items(trans, root, path, + path->slots[0], del_nr); + if (ret) +- goto out; ++ break; + if (key.offset == bytenr) + break; + } else if (key.offset < bytenr && csum_end > end_byte) { +@@ -705,8 +706,9 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, + ret = btrfs_split_item(trans, root, path, &key, offset); + if (ret && ret != -EAGAIN) { + btrfs_abort_transaction(trans, ret); +- goto out; ++ break; + } ++ ret = 0; + + key.offset = end_byte - 1; + } else { +@@ -716,8 +718,6 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans, + } + btrfs_release_path(path); + } +- ret = 0; +-out: + btrfs_free_path(path); + return ret; + } +diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c +index 8c6f619c9ee6a..bf0e0e3e09c5d 100644 +--- a/fs/btrfs/inode.c ++++ b/fs/btrfs/inode.c +@@ -3162,6 +3162,18 @@ out: + if (ret || truncated) { + u64 start, end; + ++ /* ++ * If we failed to finish this ordered extent for any reason we ++ * need to make sure BTRFS_ORDERED_IOERR is set on the ordered ++ * extent, and mark the inode with the error if it wasn't ++ * already set. Any error during writeback would have already ++ * set the mapping error, so we need to set it if we're the ones ++ * marking this ordered extent as failed. ++ */ ++ if (ret && !test_and_set_bit(BTRFS_ORDERED_IOERR, ++ &ordered_extent->flags)) ++ mapping_set_error(ordered_extent->inode->i_mapping, -EIO); ++ + if (truncated) + start = ordered_extent->file_offset + logical_len; + else +diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c +index 1cd610ddbb244..93e59ce001742 100644 +--- a/fs/btrfs/tree-log.c ++++ b/fs/btrfs/tree-log.c +@@ -1699,6 +1699,7 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, + break; + + if (ret == 1) { ++ ret = 0; + if (path->slots[0] == 0) + break; + path->slots[0]--; +@@ -1711,17 +1712,19 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, + + ret = btrfs_del_item(trans, root, path); + if (ret) +- goto out; ++ break; + + btrfs_release_path(path); + inode = read_one_inode(root, key.offset); +- if (!inode) +- return -EIO; ++ if (!inode) { ++ ret = -EIO; ++ break; ++ } + + ret = fixup_inode_link_count(trans, root, inode); + iput(inode); + if (ret) +- goto out; ++ break; + + /* + * fixup on a directory may create new entries, +@@ -1730,8 +1733,6 @@ static noinline int fixup_inode_link_counts(struct btrfs_trans_handle *trans, + */ + key.offset = (u64)-1; + } +- ret = 0; +-out: + btrfs_release_path(path); + return ret; + } +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 36708d9d71cbb..093cb675841b0 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -3263,7 +3263,10 @@ static int ext4_split_extent_at(handle_t *handle, + ext4_ext_mark_unwritten(ex2); + + err = ext4_ext_insert_extent(handle, inode, ppath, &newex, flags); +- if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { ++ if (err != -ENOSPC && err != -EDQUOT) ++ goto out; ++ ++ if (EXT4_EXT_MAY_ZEROOUT & split_flag) { + if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { + if (split_flag & EXT4_EXT_DATA_VALID1) { + err = ext4_ext_zeroout(inode, ex2); +@@ -3289,30 +3292,30 @@ static int ext4_split_extent_at(handle_t *handle, + ext4_ext_pblock(&orig_ex)); + } + +- if (err) +- goto fix_extent_len; +- /* update the extent length and mark as initialized */ +- ex->ee_len = cpu_to_le16(ee_len); +- ext4_ext_try_to_merge(handle, inode, path, ex); +- err = ext4_ext_dirty(handle, inode, path + path->p_depth); +- if (err) +- goto fix_extent_len; +- +- /* update extent status tree */ +- err = ext4_zeroout_es(inode, &zero_ex); +- +- goto out; +- } else if (err) +- goto fix_extent_len; +- +-out: +- ext4_ext_show_leaf(inode, path); +- return err; ++ if (!err) { ++ /* update the extent length and mark as initialized */ ++ ex->ee_len = cpu_to_le16(ee_len); ++ ext4_ext_try_to_merge(handle, inode, path, ex); ++ err = ext4_ext_dirty(handle, inode, path + path->p_depth); ++ if (!err) ++ /* update extent status tree */ ++ err = ext4_zeroout_es(inode, &zero_ex); ++ /* If we failed at this point, we don't know in which ++ * state the extent tree exactly is so don't try to fix ++ * length of the original extent as it may do even more ++ * damage. ++ */ ++ goto out; ++ } ++ } + + fix_extent_len: + ex->ee_len = orig_ex.ee_len; + ext4_ext_dirty(handle, inode, path + path->p_depth); + return err; ++out: ++ ext4_ext_show_leaf(inode, path); ++ return err; + } + + /* +diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c +index 5c507569ef704..94df697e26385 100644 +--- a/fs/ocfs2/file.c ++++ b/fs/ocfs2/file.c +@@ -1863,6 +1863,45 @@ out: + return ret; + } + ++/* ++ * zero out partial blocks of one cluster. ++ * ++ * start: file offset where zero starts, will be made upper block aligned. ++ * len: it will be trimmed to the end of current cluster if "start + len" ++ * is bigger than it. ++ */ ++static int ocfs2_zeroout_partial_cluster(struct inode *inode, ++ u64 start, u64 len) ++{ ++ int ret; ++ u64 start_block, end_block, nr_blocks; ++ u64 p_block, offset; ++ u32 cluster, p_cluster, nr_clusters; ++ struct super_block *sb = inode->i_sb; ++ u64 end = ocfs2_align_bytes_to_clusters(sb, start); ++ ++ if (start + len < end) ++ end = start + len; ++ ++ start_block = ocfs2_blocks_for_bytes(sb, start); ++ end_block = ocfs2_blocks_for_bytes(sb, end); ++ nr_blocks = end_block - start_block; ++ if (!nr_blocks) ++ return 0; ++ ++ cluster = ocfs2_bytes_to_clusters(sb, start); ++ ret = ocfs2_get_clusters(inode, cluster, &p_cluster, ++ &nr_clusters, NULL); ++ if (ret) ++ return ret; ++ if (!p_cluster) ++ return 0; ++ ++ offset = start_block - ocfs2_clusters_to_blocks(sb, cluster); ++ p_block = ocfs2_clusters_to_blocks(sb, p_cluster) + offset; ++ return sb_issue_zeroout(sb, p_block, nr_blocks, GFP_NOFS); ++} ++ + /* + * Parts of this function taken from xfs_change_file_space() + */ +@@ -1873,7 +1912,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, + { + int ret; + s64 llen; +- loff_t size; ++ loff_t size, orig_isize; + struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); + struct buffer_head *di_bh = NULL; + handle_t *handle; +@@ -1904,6 +1943,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, + goto out_inode_unlock; + } + ++ orig_isize = i_size_read(inode); + switch (sr->l_whence) { + case 0: /*SEEK_SET*/ + break; +@@ -1911,7 +1951,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, + sr->l_start += f_pos; + break; + case 2: /*SEEK_END*/ +- sr->l_start += i_size_read(inode); ++ sr->l_start += orig_isize; + break; + default: + ret = -EINVAL; +@@ -1965,6 +2005,14 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, + default: + ret = -EINVAL; + } ++ ++ /* zeroout eof blocks in the cluster. */ ++ if (!ret && change_size && orig_isize < size) { ++ ret = ocfs2_zeroout_partial_cluster(inode, orig_isize, ++ size - orig_isize); ++ if (!ret) ++ i_size_write(inode, size); ++ } + up_write(&OCFS2_I(inode)->ip_alloc_sem); + if (ret) { + mlog_errno(ret); +@@ -1981,9 +2029,6 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, + goto out_inode_unlock; + } + +- if (change_size && i_size_read(inode) < size) +- i_size_write(inode, size); +- + inode->i_ctime = inode->i_mtime = current_time(inode); + ret = ocfs2_mark_inode_dirty(handle, inode, di_bh); + if (ret < 0) +diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h +index d8b4d31acd18e..efe30b9b11908 100644 +--- a/include/linux/perf_event.h ++++ b/include/linux/perf_event.h +@@ -747,6 +747,11 @@ struct perf_event_context { + int nr_stat; + int nr_freq; + int rotate_disable; ++ /* ++ * Set when nr_events != nr_active, except tolerant to events not ++ * necessary to be active due to scheduling constraints, such as cgroups. ++ */ ++ int rotate_necessary; + atomic_t refcount; + struct task_struct *task; + +diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h +index e2ec3582e5493..452ca06ed2534 100644 +--- a/include/linux/usb/usbnet.h ++++ b/include/linux/usb/usbnet.h +@@ -83,6 +83,8 @@ struct usbnet { + # define EVENT_LINK_CHANGE 11 + # define EVENT_SET_RX_MODE 12 + # define EVENT_NO_IP_ALIGN 13 ++ u32 rx_speed; /* in bps - NOT Mbps */ ++ u32 tx_speed; /* in bps - NOT Mbps */ + }; + + static inline struct usb_driver *driver_of(struct usb_interface *intf) +diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h +index 028b754ae9b17..0baf2e21a533f 100644 +--- a/include/net/caif/caif_dev.h ++++ b/include/net/caif/caif_dev.h +@@ -119,7 +119,7 @@ void caif_free_client(struct cflayer *adap_layer); + * The link_support layer is used to add any Link Layer specific + * framing. + */ +-void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, ++int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, + struct cflayer *link_support, int head_room, + struct cflayer **layer, int (**rcv_func)( + struct sk_buff *, struct net_device *, +diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h +index 70bfd017581fb..219094ace893c 100644 +--- a/include/net/caif/cfcnfg.h ++++ b/include/net/caif/cfcnfg.h +@@ -62,7 +62,7 @@ void cfcnfg_remove(struct cfcnfg *cfg); + * @fcs: Specify if checksum is used in CAIF Framing Layer. + * @head_room: Head space needed by link specific protocol. + */ +-void ++int + cfcnfg_add_phy_layer(struct cfcnfg *cnfg, + struct net_device *dev, struct cflayer *phy_layer, + enum cfcnfg_phy_preference pref, +diff --git a/include/net/caif/cfserl.h b/include/net/caif/cfserl.h +index b5b020f3c72eb..bc3fae07a25f9 100644 +--- a/include/net/caif/cfserl.h ++++ b/include/net/caif/cfserl.h +@@ -9,4 +9,5 @@ + #include + + struct cflayer *cfserl_create(int instance, bool use_stx); ++void cfserl_release(struct cflayer *layer); + #endif +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 71ca8c4dc290f..8481fc7676c0b 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -228,6 +228,20 @@ enum bpf_attach_type { + */ + #define BPF_F_STRICT_ALIGNMENT (1U << 0) + ++/* If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the ++ * verifier will allow any alignment whatsoever. On platforms ++ * with strict alignment requirements for loads ands stores (such ++ * as sparc and mips) the verifier validates that all loads and ++ * stores provably follow this requirement. This flag turns that ++ * checking and enforcement off. ++ * ++ * It is mostly used for testing when we want to validate the ++ * context and memory access aspects of the verifier, but because ++ * of an unaligned access the alignment check would trigger before ++ * the one we are interested in. ++ */ ++#define BPF_F_ANY_ALIGNMENT (1U << 1) ++ + /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ + #define BPF_PSEUDO_MAP_FD 1 + +diff --git a/init/main.c b/init/main.c +index fdfef08da0c4b..7baad67c2e937 100644 +--- a/init/main.c ++++ b/init/main.c +@@ -1124,7 +1124,7 @@ static noinline void __init kernel_init_freeable(void) + */ + set_mems_allowed(node_states[N_MEMORY]); + +- cad_pid = task_pid(current); ++ cad_pid = get_pid(task_pid(current)); + + smp_prepare_cpus(setup_max_cpus); + +diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c +index 21a366a661acd..353a8d672302b 100644 +--- a/kernel/bpf/syscall.c ++++ b/kernel/bpf/syscall.c +@@ -1367,9 +1367,14 @@ static int bpf_prog_load(union bpf_attr *attr) + if (CHECK_ATTR(BPF_PROG_LOAD)) + return -EINVAL; + +- if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT) ++ if (attr->prog_flags & ~(BPF_F_STRICT_ALIGNMENT | BPF_F_ANY_ALIGNMENT)) + return -EINVAL; + ++ if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && ++ (attr->prog_flags & BPF_F_ANY_ALIGNMENT) && ++ !capable(CAP_SYS_ADMIN)) ++ return -EPERM; ++ + /* copy eBPF program license from user space */ + if (strncpy_from_user(license, u64_to_user_ptr(attr->license), + sizeof(license) - 1) < 0) +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 1f4c88ce58deb..4ce032c4acd03 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -6440,6 +6440,9 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr) + if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) + env->strict_alignment = true; + ++ if (attr->prog_flags & BPF_F_ANY_ALIGNMENT) ++ env->strict_alignment = false; ++ + ret = replace_map_fd_with_map_ptr(env); + if (ret < 0) + goto skip_full_check; +diff --git a/kernel/events/core.c b/kernel/events/core.c +index b8b74a4a524c1..d3be2cd57af12 100644 +--- a/kernel/events/core.c ++++ b/kernel/events/core.c +@@ -2952,6 +2952,12 @@ static void ctx_sched_out(struct perf_event_context *ctx, + if (!ctx->nr_active || !(is_active & EVENT_ALL)) + return; + ++ /* ++ * If we had been multiplexing, no rotations are necessary, now no events ++ * are active. ++ */ ++ ctx->rotate_necessary = 0; ++ + perf_pmu_disable(ctx->pmu); + if (is_active & EVENT_PINNED) { + list_for_each_entry_safe(event, tmp, &ctx->pinned_active, active_list) +@@ -3319,10 +3325,13 @@ static int flexible_sched_in(struct perf_event *event, void *data) + return 0; + + if (group_can_go_on(event, sid->cpuctx, sid->can_add_hw)) { +- if (!group_sched_in(event, sid->cpuctx, sid->ctx)) +- list_add_tail(&event->active_list, &sid->ctx->flexible_active); +- else ++ int ret = group_sched_in(event, sid->cpuctx, sid->ctx); ++ if (ret) { + sid->can_add_hw = 0; ++ sid->ctx->rotate_necessary = 1; ++ return 0; ++ } ++ list_add_tail(&event->active_list, &sid->ctx->flexible_active); + } + + return 0; +@@ -3680,34 +3689,39 @@ static void rotate_ctx(struct perf_event_context *ctx, struct perf_event *event) + perf_event_groups_insert(&ctx->flexible_groups, event); + } + ++/* pick an event from the flexible_groups to rotate */ + static inline struct perf_event * +-ctx_first_active(struct perf_event_context *ctx) ++ctx_event_to_rotate(struct perf_event_context *ctx) + { +- return list_first_entry_or_null(&ctx->flexible_active, +- struct perf_event, active_list); ++ struct perf_event *event; ++ ++ /* pick the first active flexible event */ ++ event = list_first_entry_or_null(&ctx->flexible_active, ++ struct perf_event, active_list); ++ ++ /* if no active flexible event, pick the first event */ ++ if (!event) { ++ event = rb_entry_safe(rb_first(&ctx->flexible_groups.tree), ++ typeof(*event), group_node); ++ } ++ ++ return event; + } + + static bool perf_rotate_context(struct perf_cpu_context *cpuctx) + { + struct perf_event *cpu_event = NULL, *task_event = NULL; +- bool cpu_rotate = false, task_rotate = false; +- struct perf_event_context *ctx = NULL; ++ struct perf_event_context *task_ctx = NULL; ++ int cpu_rotate, task_rotate; + + /* + * Since we run this from IRQ context, nobody can install new + * events, thus the event count values are stable. + */ + +- if (cpuctx->ctx.nr_events) { +- if (cpuctx->ctx.nr_events != cpuctx->ctx.nr_active) +- cpu_rotate = true; +- } +- +- ctx = cpuctx->task_ctx; +- if (ctx && ctx->nr_events) { +- if (ctx->nr_events != ctx->nr_active) +- task_rotate = true; +- } ++ cpu_rotate = cpuctx->ctx.rotate_necessary; ++ task_ctx = cpuctx->task_ctx; ++ task_rotate = task_ctx ? task_ctx->rotate_necessary : 0; + + if (!(cpu_rotate || task_rotate)) + return false; +@@ -3716,25 +3730,25 @@ static bool perf_rotate_context(struct perf_cpu_context *cpuctx) + perf_pmu_disable(cpuctx->ctx.pmu); + + if (task_rotate) +- task_event = ctx_first_active(ctx); ++ task_event = ctx_event_to_rotate(task_ctx); + if (cpu_rotate) +- cpu_event = ctx_first_active(&cpuctx->ctx); ++ cpu_event = ctx_event_to_rotate(&cpuctx->ctx); + + /* + * As per the order given at ctx_resched() first 'pop' task flexible + * and then, if needed CPU flexible. + */ +- if (task_event || (ctx && cpu_event)) +- ctx_sched_out(ctx, cpuctx, EVENT_FLEXIBLE); ++ if (task_event || (task_ctx && cpu_event)) ++ ctx_sched_out(task_ctx, cpuctx, EVENT_FLEXIBLE); + if (cpu_event) + cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE); + + if (task_event) +- rotate_ctx(ctx, task_event); ++ rotate_ctx(task_ctx, task_event); + if (cpu_event) + rotate_ctx(&cpuctx->ctx, cpu_event); + +- perf_event_sched_in(cpuctx, ctx, current); ++ perf_event_sched_in(cpuctx, task_ctx, current); + + perf_pmu_enable(cpuctx->ctx.pmu); + perf_ctx_unlock(cpuctx, cpuctx->task_ctx); +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 80392cdd5f3b2..f06687053f96b 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -6154,6 +6154,7 @@ static inline int select_idle_smt(struct task_struct *p, struct sched_domain *sd + */ + static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int target) + { ++ struct cpumask *cpus = this_cpu_cpumask_var_ptr(select_idle_mask); + struct sched_domain *this_sd; + u64 avg_cost, avg_idle; + u64 time, cost; +@@ -6184,11 +6185,11 @@ static int select_idle_cpu(struct task_struct *p, struct sched_domain *sd, int t + + time = local_clock(); + +- for_each_cpu_wrap(cpu, sched_domain_span(sd), target) { ++ cpumask_and(cpus, sched_domain_span(sd), &p->cpus_allowed); ++ ++ for_each_cpu_wrap(cpu, cpus, target) { + if (!--nr) + return -1; +- if (!cpumask_test_cpu(cpu, &p->cpus_allowed)) +- continue; + if (available_idle_cpu(cpu)) + break; + } +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 2f769a6615688..c69f12e4c1499 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -4154,10 +4154,20 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, + struct page *page; + + if (!*pagep) { +- ret = -ENOMEM; ++ /* If a page already exists, then it's UFFDIO_COPY for ++ * a non-missing case. Return -EEXIST. ++ */ ++ if (vm_shared && ++ hugetlbfs_pagecache_present(h, dst_vma, dst_addr)) { ++ ret = -EEXIST; ++ goto out; ++ } ++ + page = alloc_huge_page(dst_vma, dst_addr, 0); +- if (IS_ERR(page)) ++ if (IS_ERR(page)) { ++ ret = -ENOMEM; + goto out; ++ } + + ret = copy_huge_page_from_user(page, + (const void __user *) src_addr, +diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c +index 04d6f50798c98..219cdbb476fb7 100644 +--- a/net/bluetooth/hci_core.c ++++ b/net/bluetooth/hci_core.c +@@ -1498,8 +1498,13 @@ static int hci_dev_do_open(struct hci_dev *hdev) + } else { + /* Init failed, cleanup */ + flush_work(&hdev->tx_work); +- flush_work(&hdev->cmd_work); ++ ++ /* Since hci_rx_work() is possible to awake new cmd_work ++ * it should be flushed first to avoid unexpected call of ++ * hci_cmd_work() ++ */ + flush_work(&hdev->rx_work); ++ flush_work(&hdev->cmd_work); + + skb_queue_purge(&hdev->cmd_q); + skb_queue_purge(&hdev->rx_q); +diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c +index e506c51ff7653..06156de24c50b 100644 +--- a/net/bluetooth/hci_sock.c ++++ b/net/bluetooth/hci_sock.c +@@ -755,7 +755,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) + /* Detach sockets from device */ + read_lock(&hci_sk_list.lock); + sk_for_each(sk, &hci_sk_list.head) { +- bh_lock_sock_nested(sk); ++ lock_sock(sk); + if (hci_pi(sk)->hdev == hdev) { + hci_pi(sk)->hdev = NULL; + sk->sk_err = EPIPE; +@@ -764,7 +764,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event) + + hci_dev_put(hdev); + } +- bh_unlock_sock(sk); ++ release_sock(sk); + } + read_unlock(&hci_sk_list.lock); + } +diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c +index 711d7156efd8b..cc305d84168f4 100644 +--- a/net/caif/caif_dev.c ++++ b/net/caif/caif_dev.c +@@ -303,7 +303,7 @@ static void dev_flowctrl(struct net_device *dev, int on) + caifd_put(caifd); + } + +-void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, ++int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, + struct cflayer *link_support, int head_room, + struct cflayer **layer, + int (**rcv_func)(struct sk_buff *, struct net_device *, +@@ -314,11 +314,12 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, + enum cfcnfg_phy_preference pref; + struct cfcnfg *cfg = get_cfcnfg(dev_net(dev)); + struct caif_device_entry_list *caifdevs; ++ int res; + + caifdevs = caif_device_list(dev_net(dev)); + caifd = caif_device_alloc(dev); + if (!caifd) +- return; ++ return -ENOMEM; + *layer = &caifd->layer; + spin_lock_init(&caifd->flow_lock); + +@@ -339,7 +340,7 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, + strlcpy(caifd->layer.name, dev->name, + sizeof(caifd->layer.name)); + caifd->layer.transmit = transmit; +- cfcnfg_add_phy_layer(cfg, ++ res = cfcnfg_add_phy_layer(cfg, + dev, + &caifd->layer, + pref, +@@ -349,6 +350,7 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, + mutex_unlock(&caifdevs->lock); + if (rcv_func) + *rcv_func = receive; ++ return res; + } + EXPORT_SYMBOL(caif_enroll_dev); + +@@ -363,6 +365,7 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, + struct cflayer *layer, *link_support; + int head_room = 0; + struct caif_device_entry_list *caifdevs; ++ int res; + + cfg = get_cfcnfg(dev_net(dev)); + caifdevs = caif_device_list(dev_net(dev)); +@@ -388,8 +391,10 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, + break; + } + } +- caif_enroll_dev(dev, caifdev, link_support, head_room, ++ res = caif_enroll_dev(dev, caifdev, link_support, head_room, + &layer, NULL); ++ if (res) ++ cfserl_release(link_support); + caifdev->flowctrl = dev_flowctrl; + break; + +diff --git a/net/caif/caif_usb.c b/net/caif/caif_usb.c +index 1a082a946045e..76d49a1bc6f68 100644 +--- a/net/caif/caif_usb.c ++++ b/net/caif/caif_usb.c +@@ -116,6 +116,11 @@ static struct cflayer *cfusbl_create(int phyid, u8 ethaddr[ETH_ALEN], + return (struct cflayer *) this; + } + ++static void cfusbl_release(struct cflayer *layer) ++{ ++ kfree(layer); ++} ++ + static struct packet_type caif_usb_type __read_mostly = { + .type = cpu_to_be16(ETH_P_802_EX1), + }; +@@ -128,6 +133,7 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, + struct cflayer *layer, *link_support; + struct usbnet *usbnet; + struct usb_device *usbdev; ++ int res; + + /* Check whether we have a NCM device, and find its VID/PID. */ + if (!(dev->dev.parent && dev->dev.parent->driver && +@@ -170,8 +176,11 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, + if (dev->num_tx_queues > 1) + pr_warn("USB device uses more than one tx queue\n"); + +- caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN, ++ res = caif_enroll_dev(dev, &common, link_support, CFUSB_MAX_HEADLEN, + &layer, &caif_usb_type.func); ++ if (res) ++ goto err; ++ + if (!pack_added) + dev_add_pack(&caif_usb_type); + pack_added = true; +@@ -179,6 +188,9 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what, + strlcpy(layer->name, dev->name, sizeof(layer->name)); + + return 0; ++err: ++ cfusbl_release(link_support); ++ return res; + } + + static struct notifier_block caif_device_notifier = { +diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c +index 8f00bea093b94..b456b79abd3b7 100644 +--- a/net/caif/cfcnfg.c ++++ b/net/caif/cfcnfg.c +@@ -450,7 +450,7 @@ unlock: + rcu_read_unlock(); + } + +-void ++int + cfcnfg_add_phy_layer(struct cfcnfg *cnfg, + struct net_device *dev, struct cflayer *phy_layer, + enum cfcnfg_phy_preference pref, +@@ -459,7 +459,7 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, + { + struct cflayer *frml; + struct cfcnfg_phyinfo *phyinfo = NULL; +- int i; ++ int i, res = 0; + u8 phyid; + + mutex_lock(&cnfg->lock); +@@ -473,12 +473,15 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, + goto got_phyid; + } + pr_warn("Too many CAIF Link Layers (max 6)\n"); ++ res = -EEXIST; + goto out; + + got_phyid: + phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC); +- if (!phyinfo) ++ if (!phyinfo) { ++ res = -ENOMEM; + goto out_err; ++ } + + phy_layer->id = phyid; + phyinfo->pref = pref; +@@ -492,8 +495,10 @@ got_phyid: + + frml = cffrml_create(phyid, fcs); + +- if (!frml) ++ if (!frml) { ++ res = -ENOMEM; + goto out_err; ++ } + phyinfo->frm_layer = frml; + layer_set_up(frml, cnfg->mux); + +@@ -511,11 +516,12 @@ got_phyid: + list_add_rcu(&phyinfo->node, &cnfg->phys); + out: + mutex_unlock(&cnfg->lock); +- return; ++ return res; + + out_err: + kfree(phyinfo); + mutex_unlock(&cnfg->lock); ++ return res; + } + EXPORT_SYMBOL(cfcnfg_add_phy_layer); + +diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c +index ce60f06d76de3..af1e1e36dc90a 100644 +--- a/net/caif/cfserl.c ++++ b/net/caif/cfserl.c +@@ -31,6 +31,11 @@ static int cfserl_transmit(struct cflayer *layr, struct cfpkt *pkt); + static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, + int phyid); + ++void cfserl_release(struct cflayer *layer) ++{ ++ kfree(layer); ++} ++ + struct cflayer *cfserl_create(int instance, bool use_stx) + { + struct cfserl *this = kzalloc(sizeof(struct cfserl), GFP_ATOMIC); +diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c +index c0930b9fe848b..7531cb1665d2b 100644 +--- a/net/ieee802154/nl-mac.c ++++ b/net/ieee802154/nl-mac.c +@@ -688,8 +688,10 @@ int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info) + nla_put_u8(msg, IEEE802154_ATTR_LLSEC_SECLEVEL, params.out_level) || + nla_put_u32(msg, IEEE802154_ATTR_LLSEC_FRAME_COUNTER, + be32_to_cpu(params.frame_counter)) || +- ieee802154_llsec_fill_key_id(msg, ¶ms.out_key)) ++ ieee802154_llsec_fill_key_id(msg, ¶ms.out_key)) { ++ rc = -ENOBUFS; + goto out_free; ++ } + + dev_put(dev); + +diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c +index b231e40f006a6..ca1dd9ff07aba 100644 +--- a/net/ieee802154/nl-phy.c ++++ b/net/ieee802154/nl-phy.c +@@ -249,8 +249,10 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) + } + + if (nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || +- nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name)) ++ nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name)) { ++ rc = -EMSGSIZE; + goto nla_put_failure; ++ } + dev_put(dev); + + wpan_phy_put(phy); +diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c +index 3ad1de081e3c7..6208fa09fe713 100644 +--- a/net/netfilter/ipvs/ip_vs_ctl.c ++++ b/net/netfilter/ipvs/ip_vs_ctl.c +@@ -1269,7 +1269,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u, + ip_vs_addr_copy(svc->af, &svc->addr, &u->addr); + svc->port = u->port; + svc->fwmark = u->fwmark; +- svc->flags = u->flags; ++ svc->flags = u->flags & ~IP_VS_SVC_F_HASHED; + svc->timeout = u->timeout * HZ; + svc->netmask = u->netmask; + svc->ipvs = ipvs; +diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c +index ddcb1b6074745..c8b0f1122c44d 100644 +--- a/net/netfilter/nfnetlink_cthelper.c ++++ b/net/netfilter/nfnetlink_cthelper.c +@@ -381,10 +381,14 @@ static int + nfnl_cthelper_update(const struct nlattr * const tb[], + struct nf_conntrack_helper *helper) + { ++ u32 size; + int ret; + +- if (tb[NFCTH_PRIV_DATA_LEN]) +- return -EBUSY; ++ if (tb[NFCTH_PRIV_DATA_LEN]) { ++ size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN])); ++ if (size != helper->data_len) ++ return -EBUSY; ++ } + + if (tb[NFCTH_POLICY]) { + ret = nfnl_cthelper_update_policy(helper, tb[NFCTH_POLICY]); +diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c +index 59de4f54dd18c..23f7116d122a2 100644 +--- a/net/nfc/llcp_sock.c ++++ b/net/nfc/llcp_sock.c +@@ -122,6 +122,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) + if (!llcp_sock->service_name) { + nfc_llcp_local_put(llcp_sock->local); + llcp_sock->local = NULL; ++ llcp_sock->dev = NULL; + ret = -ENOMEM; + goto put_dev; + } +@@ -131,6 +132,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) + llcp_sock->local = NULL; + kfree(llcp_sock->service_name); + llcp_sock->service_name = NULL; ++ llcp_sock->dev = NULL; + ret = -EADDRINUSE; + goto put_dev; + } +diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c +index 2649a0a0d45e0..e1006ed4d90ab 100644 +--- a/net/tipc/bearer.c ++++ b/net/tipc/bearer.c +@@ -231,7 +231,8 @@ void tipc_bearer_remove_dest(struct net *net, u32 bearer_id, u32 dest) + */ + static int tipc_enable_bearer(struct net *net, const char *name, + u32 disc_domain, u32 prio, +- struct nlattr *attr[]) ++ struct nlattr *attr[], ++ struct netlink_ext_ack *extack) + { + struct tipc_net *tn = tipc_net(net); + struct tipc_bearer_names b_names; +@@ -242,20 +243,24 @@ static int tipc_enable_bearer(struct net *net, const char *name, + int bearer_id = 0; + int res = -EINVAL; + char *errstr = ""; ++ u32 i; + + if (!bearer_name_validate(name, &b_names)) { + errstr = "illegal name"; ++ NL_SET_ERR_MSG(extack, "Illegal name"); + goto rejected; + } + + if (prio > TIPC_MAX_LINK_PRI && prio != TIPC_MEDIA_LINK_PRI) { + errstr = "illegal priority"; ++ NL_SET_ERR_MSG(extack, "Illegal priority"); + goto rejected; + } + + m = tipc_media_find(b_names.media_name); + if (!m) { + errstr = "media not registered"; ++ NL_SET_ERR_MSG(extack, "Media not registered"); + goto rejected; + } + +@@ -263,33 +268,43 @@ static int tipc_enable_bearer(struct net *net, const char *name, + prio = m->priority; + + /* Check new bearer vs existing ones and find free bearer id if any */ +- while (bearer_id < MAX_BEARERS) { +- b = rtnl_dereference(tn->bearer_list[bearer_id]); +- if (!b) +- break; ++ bearer_id = MAX_BEARERS; ++ i = MAX_BEARERS; ++ while (i-- != 0) { ++ b = rtnl_dereference(tn->bearer_list[i]); ++ if (!b) { ++ bearer_id = i; ++ continue; ++ } + if (!strcmp(name, b->name)) { + errstr = "already enabled"; ++ NL_SET_ERR_MSG(extack, "Already enabled"); + goto rejected; + } +- bearer_id++; +- if (b->priority != prio) +- continue; +- if (++with_this_prio <= 2) +- continue; +- pr_warn("Bearer <%s>: already 2 bearers with priority %u\n", +- name, prio); +- if (prio == TIPC_MIN_LINK_PRI) { +- errstr = "cannot adjust to lower"; +- goto rejected; ++ ++ if (b->priority == prio && ++ (++with_this_prio > 2)) { ++ pr_warn("Bearer <%s>: already 2 bearers with priority %u\n", ++ name, prio); ++ ++ if (prio == TIPC_MIN_LINK_PRI) { ++ errstr = "cannot adjust to lower"; ++ NL_SET_ERR_MSG(extack, "Cannot adjust to lower"); ++ goto rejected; ++ } ++ ++ pr_warn("Bearer <%s>: trying with adjusted priority\n", ++ name); ++ prio--; ++ bearer_id = MAX_BEARERS; ++ i = MAX_BEARERS; ++ with_this_prio = 1; + } +- pr_warn("Bearer <%s>: trying with adjusted priority\n", name); +- prio--; +- bearer_id = 0; +- with_this_prio = 1; + } + + if (bearer_id >= MAX_BEARERS) { + errstr = "max 3 bearers permitted"; ++ NL_SET_ERR_MSG(extack, "Max 3 bearers permitted"); + goto rejected; + } + +@@ -303,6 +318,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, + if (res) { + kfree(b); + errstr = "failed to enable media"; ++ NL_SET_ERR_MSG(extack, "Failed to enable media"); + goto rejected; + } + +@@ -318,6 +334,7 @@ static int tipc_enable_bearer(struct net *net, const char *name, + if (res) { + bearer_disable(net, b); + errstr = "failed to create discoverer"; ++ NL_SET_ERR_MSG(extack, "Failed to create discoverer"); + goto rejected; + } + +@@ -795,6 +812,7 @@ int tipc_nl_bearer_get(struct sk_buff *skb, struct genl_info *info) + bearer = tipc_bearer_find(net, name); + if (!bearer) { + err = -EINVAL; ++ NL_SET_ERR_MSG(info->extack, "Bearer not found"); + goto err_out; + } + +@@ -834,8 +852,10 @@ int __tipc_nl_bearer_disable(struct sk_buff *skb, struct genl_info *info) + name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + + bearer = tipc_bearer_find(net, name); +- if (!bearer) ++ if (!bearer) { ++ NL_SET_ERR_MSG(info->extack, "Bearer not found"); + return -EINVAL; ++ } + + bearer_disable(net, bearer); + +@@ -893,7 +913,8 @@ int __tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) + prio = nla_get_u32(props[TIPC_NLA_PROP_PRIO]); + } + +- return tipc_enable_bearer(net, bearer, domain, prio, attrs); ++ return tipc_enable_bearer(net, bearer, domain, prio, attrs, ++ info->extack); + } + + int tipc_nl_bearer_enable(struct sk_buff *skb, struct genl_info *info) +@@ -932,6 +953,7 @@ int tipc_nl_bearer_add(struct sk_buff *skb, struct genl_info *info) + b = tipc_bearer_find(net, name); + if (!b) { + rtnl_unlock(); ++ NL_SET_ERR_MSG(info->extack, "Bearer not found"); + return -EINVAL; + } + +@@ -972,8 +994,10 @@ int __tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) + name = nla_data(attrs[TIPC_NLA_BEARER_NAME]); + + b = tipc_bearer_find(net, name); +- if (!b) ++ if (!b) { ++ NL_SET_ERR_MSG(info->extack, "Bearer not found"); + return -EINVAL; ++ } + + if (attrs[TIPC_NLA_BEARER_PROP]) { + struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; +@@ -992,12 +1016,18 @@ int __tipc_nl_bearer_set(struct sk_buff *skb, struct genl_info *info) + if (props[TIPC_NLA_PROP_WIN]) + b->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]); + if (props[TIPC_NLA_PROP_MTU]) { +- if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) ++ if (b->media->type_id != TIPC_MEDIA_TYPE_UDP) { ++ NL_SET_ERR_MSG(info->extack, ++ "MTU property is unsupported"); + return -EINVAL; ++ } + #ifdef CONFIG_TIPC_MEDIA_UDP + if (tipc_udp_mtu_bad(nla_get_u32 +- (props[TIPC_NLA_PROP_MTU]))) ++ (props[TIPC_NLA_PROP_MTU]))) { ++ NL_SET_ERR_MSG(info->extack, ++ "MTU value is out-of-range"); + return -EINVAL; ++ } + b->mtu = nla_get_u32(props[TIPC_NLA_PROP_MTU]); + tipc_node_apply_property(net, b, TIPC_NLA_PROP_MTU); + #endif +@@ -1125,6 +1155,7 @@ int tipc_nl_media_get(struct sk_buff *skb, struct genl_info *info) + rtnl_lock(); + media = tipc_media_find(name); + if (!media) { ++ NL_SET_ERR_MSG(info->extack, "Media not found"); + err = -EINVAL; + goto err_out; + } +@@ -1161,9 +1192,10 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info) + name = nla_data(attrs[TIPC_NLA_MEDIA_NAME]); + + m = tipc_media_find(name); +- if (!m) ++ if (!m) { ++ NL_SET_ERR_MSG(info->extack, "Media not found"); + return -EINVAL; +- ++ } + if (attrs[TIPC_NLA_MEDIA_PROP]) { + struct nlattr *props[TIPC_NLA_PROP_MAX + 1]; + +@@ -1179,12 +1211,18 @@ int __tipc_nl_media_set(struct sk_buff *skb, struct genl_info *info) + if (props[TIPC_NLA_PROP_WIN]) + m->window = nla_get_u32(props[TIPC_NLA_PROP_WIN]); + if (props[TIPC_NLA_PROP_MTU]) { +- if (m->type_id != TIPC_MEDIA_TYPE_UDP) ++ if (m->type_id != TIPC_MEDIA_TYPE_UDP) { ++ NL_SET_ERR_MSG(info->extack, ++ "MTU property is unsupported"); + return -EINVAL; ++ } + #ifdef CONFIG_TIPC_MEDIA_UDP + if (tipc_udp_mtu_bad(nla_get_u32 +- (props[TIPC_NLA_PROP_MTU]))) ++ (props[TIPC_NLA_PROP_MTU]))) { ++ NL_SET_ERR_MSG(info->extack, ++ "MTU value is out-of-range"); + return -EINVAL; ++ } + m->mtu = nla_get_u32(props[TIPC_NLA_PROP_MTU]); + #endif + } +diff --git a/net/wireless/core.h b/net/wireless/core.h +index f5d58652108dd..5f177dad2fa80 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -404,6 +404,8 @@ void cfg80211_sme_abandon_assoc(struct wireless_dev *wdev); + + /* internal helpers */ + bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher); ++bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev, ++ int key_idx, bool pairwise); + int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, + struct key_params *params, int key_idx, + bool pairwise, const u8 *mac_addr); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 5f0605275fa39..04c4fd376e1d5 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -3624,9 +3624,6 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) + if (err) + return err; + +- if (key.idx < 0) +- return -EINVAL; +- + if (info->attrs[NL80211_ATTR_MAC]) + mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); + +@@ -3642,6 +3639,10 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) + key.type != NL80211_KEYTYPE_GROUP) + return -EINVAL; + ++ if (!cfg80211_valid_key_idx(rdev, key.idx, ++ key.type == NL80211_KEYTYPE_PAIRWISE)) ++ return -EINVAL; ++ + if (!rdev->ops->del_key) + return -EOPNOTSUPP; + +diff --git a/net/wireless/util.c b/net/wireless/util.c +index 6f9cff2ee7953..c4536468dfbea 100644 +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -214,11 +214,48 @@ bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher) + return false; + } + ++static bool ++cfg80211_igtk_cipher_supported(struct cfg80211_registered_device *rdev) ++{ ++ struct wiphy *wiphy = &rdev->wiphy; ++ int i; ++ ++ for (i = 0; i < wiphy->n_cipher_suites; i++) { ++ switch (wiphy->cipher_suites[i]) { ++ case WLAN_CIPHER_SUITE_AES_CMAC: ++ case WLAN_CIPHER_SUITE_BIP_CMAC_256: ++ case WLAN_CIPHER_SUITE_BIP_GMAC_128: ++ case WLAN_CIPHER_SUITE_BIP_GMAC_256: ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++bool cfg80211_valid_key_idx(struct cfg80211_registered_device *rdev, ++ int key_idx, bool pairwise) ++{ ++ int max_key_idx; ++ ++ if (pairwise) ++ max_key_idx = 3; ++ else if (cfg80211_igtk_cipher_supported(rdev)) ++ max_key_idx = 5; ++ else ++ max_key_idx = 3; ++ ++ if (key_idx < 0 || key_idx > max_key_idx) ++ return false; ++ ++ return true; ++} ++ + int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, + struct key_params *params, int key_idx, + bool pairwise, const u8 *mac_addr) + { +- if (key_idx < 0 || key_idx > 5) ++ if (!cfg80211_valid_key_idx(rdev, key_idx, pairwise)) + return -EINVAL; + + if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN)) +diff --git a/samples/vfio-mdev/mdpy-fb.c b/samples/vfio-mdev/mdpy-fb.c +index 2719bb2596530..a760e130bd0d6 100644 +--- a/samples/vfio-mdev/mdpy-fb.c ++++ b/samples/vfio-mdev/mdpy-fb.c +@@ -117,22 +117,27 @@ static int mdpy_fb_probe(struct pci_dev *pdev, + if (format != DRM_FORMAT_XRGB8888) { + pci_err(pdev, "format mismatch (0x%x != 0x%x)\n", + format, DRM_FORMAT_XRGB8888); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_release_regions; + } + if (width < 100 || width > 10000) { + pci_err(pdev, "width (%d) out of range\n", width); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_release_regions; + } + if (height < 100 || height > 10000) { + pci_err(pdev, "height (%d) out of range\n", height); +- return -EINVAL; ++ ret = -EINVAL; ++ goto err_release_regions; + } + pci_info(pdev, "mdpy found: %dx%d framebuffer\n", + width, height); + + info = framebuffer_alloc(sizeof(struct mdpy_fb_par), &pdev->dev); +- if (!info) ++ if (!info) { ++ ret = -ENOMEM; + goto err_release_regions; ++ } + pci_set_drvdata(pdev, info); + par = info->par; + +diff --git a/sound/core/timer.c b/sound/core/timer.c +index b5dc51030316a..b4fe1324b56c2 100644 +--- a/sound/core/timer.c ++++ b/sound/core/timer.c +@@ -500,9 +500,10 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event) + return; + if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) + return; ++ event += 10; /* convert to SNDRV_TIMER_EVENT_MXXX */ + list_for_each_entry(ts, &ti->slave_active_head, active_list) + if (ts->ccallback) +- ts->ccallback(ts, event + 100, &tstamp, resolution); ++ ts->ccallback(ts, event, &tstamp, resolution); + } + + /* start/continue a master timer */ +diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c +index f9ebbee3824bb..42c30fba699fb 100644 +--- a/sound/pci/hda/patch_realtek.c ++++ b/sound/pci/hda/patch_realtek.c +@@ -7095,6 +7095,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x82bf, "HP G3 mini", ALC221_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x82c0, "HP G3 mini premium", ALC221_FIXUP_HP_MIC_NO_PRESENCE), + SND_PCI_QUIRK(0x103c, 0x83b9, "HP Spectre x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), ++ SND_PCI_QUIRK(0x103c, 0x841c, "HP Pavilion 15-CK0xx", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), + SND_PCI_QUIRK(0x103c, 0x8736, "HP", ALC285_FIXUP_HP_GPIO_LED), +diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c +index 169679419b398..a74e07eff60c3 100644 +--- a/sound/usb/mixer_quirks.c ++++ b/sound/usb/mixer_quirks.c +@@ -1708,7 +1708,7 @@ static struct snd_kcontrol_new snd_microii_mixer_spdif[] = { + static int snd_microii_controls_create(struct usb_mixer_interface *mixer) + { + int err, i; +- const static usb_mixer_elem_resume_func_t resume_funcs[] = { ++ static const usb_mixer_elem_resume_func_t resume_funcs[] = { + snd_microii_spdif_default_update, + NULL, + snd_microii_spdif_switch_update +diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h +index 13944978ada5b..9e060c6a01ac2 100644 +--- a/tools/include/uapi/linux/bpf.h ++++ b/tools/include/uapi/linux/bpf.h +@@ -226,6 +226,20 @@ enum bpf_attach_type { + */ + #define BPF_F_STRICT_ALIGNMENT (1U << 0) + ++/* If BPF_F_ANY_ALIGNMENT is used in BPF_PROF_LOAD command, the ++ * verifier will allow any alignment whatsoever. On platforms ++ * with strict alignment requirements for loads ands stores (such ++ * as sparc and mips) the verifier validates that all loads and ++ * stores provably follow this requirement. This flag turns that ++ * checking and enforcement off. ++ * ++ * It is mostly used for testing when we want to validate the ++ * context and memory access aspects of the verifier, but because ++ * of an unaligned access the alignment check would trigger before ++ * the one we are interested in. ++ */ ++#define BPF_F_ANY_ALIGNMENT (1U << 1) ++ + /* when bpf_ldimm64->src_reg == BPF_PSEUDO_MAP_FD, bpf_ldimm64->imm == fd */ + #define BPF_PSEUDO_MAP_FD 1 + +diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c +index 482025b728399..f28ae6a68697a 100644 +--- a/tools/lib/bpf/bpf.c ++++ b/tools/lib/bpf/bpf.c +@@ -261,9 +261,9 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, + } + + int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, +- size_t insns_cnt, int strict_alignment, +- const char *license, __u32 kern_version, +- char *log_buf, size_t log_buf_sz, int log_level) ++ size_t insns_cnt, __u32 prog_flags, const char *license, ++ __u32 kern_version, char *log_buf, size_t log_buf_sz, ++ int log_level) + { + union bpf_attr attr; + +@@ -277,7 +277,7 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, + attr.log_level = log_level; + log_buf[0] = 0; + attr.kern_version = kern_version; +- attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0; ++ attr.prog_flags = prog_flags; + + return sys_bpf_prog_load(&attr, sizeof(attr)); + } +diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h +index c3145ab3bdcac..7f2e947d940c1 100644 +--- a/tools/lib/bpf/bpf.h ++++ b/tools/lib/bpf/bpf.h +@@ -79,7 +79,7 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns, + __u32 kern_version, char *log_buf, + size_t log_buf_sz); + int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns, +- size_t insns_cnt, int strict_alignment, ++ size_t insns_cnt, __u32 prog_flags, + const char *license, __u32 kern_version, + char *log_buf, size_t log_buf_sz, int log_level); + +diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c +index 5f377ec53f2f8..3c789d03b629d 100644 +--- a/tools/testing/selftests/bpf/test_align.c ++++ b/tools/testing/selftests/bpf/test_align.c +@@ -620,8 +620,8 @@ static int do_test_single(struct bpf_align_test *test) + + prog_len = probe_filter_length(prog); + fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, +- prog, prog_len, 1, "GPL", 0, +- bpf_vlog, sizeof(bpf_vlog), 2); ++ prog, prog_len, BPF_F_STRICT_ALIGNMENT, ++ "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 2); + if (fd_prog < 0 && test->result != REJECT) { + printf("Failed to load program.\n"); + printf("%s", bpf_vlog); +diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c +index e1e4b6ab83f74..b44324530948d 100644 +--- a/tools/testing/selftests/bpf/test_verifier.c ++++ b/tools/testing/selftests/bpf/test_verifier.c +@@ -70,7 +70,7 @@ struct bpf_test { + int fixup_cgroup_storage[MAX_FIXUPS]; + const char *errstr; + const char *errstr_unpriv; +- uint32_t retval; ++ uint32_t retval, retval_unpriv; + enum { + UNDEF, + ACCEPT, +@@ -963,6 +963,7 @@ static struct bpf_test tests[] = { + .errstr_unpriv = "attempt to corrupt spilled", + .errstr = "corrupted spill", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "invalid src register in STX", +@@ -1777,6 +1778,7 @@ static struct bpf_test tests[] = { + .errstr = "invalid bpf_context access", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_SK_MSG, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "invalid read past end of SK_MSG", +@@ -1799,6 +1801,7 @@ static struct bpf_test tests[] = { + .errstr = "invalid bpf_context access", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_SK_MSG, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "direct packet read for SK_MSG", +@@ -2175,6 +2178,7 @@ static struct bpf_test tests[] = { + }, + .errstr = "invalid bpf_context access", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "check skb->hash half load not permitted, unaligned 3", +@@ -2191,6 +2195,7 @@ static struct bpf_test tests[] = { + }, + .errstr = "invalid bpf_context access", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "check cb access: half, wrong type", +@@ -2986,6 +2991,8 @@ static struct bpf_test tests[] = { + .fixup_prog1 = { 2 }, + .result = ACCEPT, + .retval = 42, ++ /* Verifier rewrite for unpriv skips tail call here. */ ++ .retval_unpriv = 2, + }, + { + "stack pointer arithmetic", +@@ -3149,6 +3156,7 @@ static struct bpf_test tests[] = { + .result = REJECT, + .errstr = "R0 invalid mem access 'inv'", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "raw_stack: skb_load_bytes, spilled regs corruption 2", +@@ -3179,6 +3187,7 @@ static struct bpf_test tests[] = { + .result = REJECT, + .errstr = "R3 invalid mem access 'inv'", + .prog_type = BPF_PROG_TYPE_SCHED_CLS, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "raw_stack: skb_load_bytes, spilled regs + data", +@@ -3678,6 +3687,7 @@ static struct bpf_test tests[] = { + .errstr = "R2 invalid mem access 'inv'", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "direct packet access: test16 (arith on data_end)", +@@ -3780,6 +3790,7 @@ static struct bpf_test tests[] = { + }, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = ACCEPT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "direct packet access: test21 (x += pkt_ptr, 2)", +@@ -3805,6 +3816,7 @@ static struct bpf_test tests[] = { + }, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = ACCEPT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "direct packet access: test22 (x += pkt_ptr, 3)", +@@ -3835,6 +3847,7 @@ static struct bpf_test tests[] = { + }, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = ACCEPT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "direct packet access: test23 (x += pkt_ptr, 4)", +@@ -3861,6 +3874,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = REJECT, + .errstr = "invalid access to packet, off=0 size=8, R5(id=1,off=0,r=0)", ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "direct packet access: test24 (x += pkt_ptr, 5)", +@@ -3886,6 +3900,7 @@ static struct bpf_test tests[] = { + }, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = ACCEPT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "direct packet access: test25 (marking on <, good access)", +@@ -4765,6 +4780,7 @@ static struct bpf_test tests[] = { + .result = REJECT, + .errstr = "invalid access to map value, value_size=64 off=-2 size=4", + .prog_type = BPF_PROG_TYPE_CGROUP_SKB, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "invalid cgroup storage access 5", +@@ -4798,6 +4814,7 @@ static struct bpf_test tests[] = { + .fixup_cgroup_storage = { 1 }, + .result = REJECT, + .errstr = "get_local_storage() doesn't support non-zero flags", ++ .errstr_unpriv = "R2 leaks addr into helper function", + .prog_type = BPF_PROG_TYPE_CGROUP_SKB, + }, + { +@@ -6430,6 +6447,7 @@ static struct bpf_test tests[] = { + .errstr = "invalid mem access 'inv'", + .result = REJECT, + .result_unpriv = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "map element value illegal alu op, 5", +@@ -6452,6 +6470,7 @@ static struct bpf_test tests[] = { + .fixup_map2 = { 3 }, + .errstr = "R0 invalid mem access 'inv'", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "map element value is preserved across register spilling", +@@ -6945,6 +6964,7 @@ static struct bpf_test tests[] = { + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .retval = 0 /* csum_diff of 64-byte packet */, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "helper access to variable memory: size = 0 not allowed on NULL (!ARG_PTR_TO_MEM_OR_NULL)", +@@ -8911,6 +8931,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data' > pkt_end, bad access 1", +@@ -8948,6 +8969,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_end > pkt_data', good access", +@@ -8986,6 +9008,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_end > pkt_data', bad access 2", +@@ -9004,6 +9027,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data' < pkt_end, good access", +@@ -9042,6 +9066,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data' < pkt_end, bad access 2", +@@ -9060,6 +9085,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_end < pkt_data', good access", +@@ -9077,6 +9103,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_end < pkt_data', bad access 1", +@@ -9114,6 +9141,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data' >= pkt_end, good access", +@@ -9150,6 +9178,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data' >= pkt_end, bad access 2", +@@ -9187,6 +9216,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_end >= pkt_data', bad access 1", +@@ -9225,6 +9255,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data' <= pkt_end, good access", +@@ -9243,6 +9274,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data' <= pkt_end, bad access 1", +@@ -9281,6 +9313,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_end <= pkt_data', good access", +@@ -9317,6 +9350,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_end <= pkt_data', bad access 2", +@@ -9353,6 +9387,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_meta' > pkt_data, bad access 1", +@@ -9390,6 +9425,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data > pkt_meta', good access", +@@ -9428,6 +9464,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data > pkt_meta', bad access 2", +@@ -9446,6 +9483,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_meta' < pkt_data, good access", +@@ -9484,6 +9522,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_meta' < pkt_data, bad access 2", +@@ -9502,6 +9541,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data < pkt_meta', good access", +@@ -9519,6 +9559,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data < pkt_meta', bad access 1", +@@ -9556,6 +9597,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_meta' >= pkt_data, good access", +@@ -9592,6 +9634,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_meta' >= pkt_data, bad access 2", +@@ -9629,6 +9672,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data >= pkt_meta', bad access 1", +@@ -9667,6 +9711,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_meta' <= pkt_data, good access", +@@ -9685,6 +9730,7 @@ static struct bpf_test tests[] = { + }, + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_meta' <= pkt_data, bad access 1", +@@ -9723,6 +9769,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data <= pkt_meta', good access", +@@ -9759,6 +9806,7 @@ static struct bpf_test tests[] = { + .errstr = "R1 offset is outside of the packet", + .result = REJECT, + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "XDP pkt read, pkt_data <= pkt_meta', bad access 2", +@@ -9873,6 +9921,7 @@ static struct bpf_test tests[] = { + .errstr_unpriv = "R1 has pointer with unsupported alu operation", + .errstr = "dereference of modified ctx ptr", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "check deducing bounds from const, 8", +@@ -9887,6 +9936,7 @@ static struct bpf_test tests[] = { + .errstr_unpriv = "R1 has pointer with unsupported alu operation", + .errstr = "dereference of modified ctx ptr", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "check deducing bounds from const, 9", +@@ -10362,6 +10412,7 @@ static struct bpf_test tests[] = { + .result = REJECT, + .errstr = "R6 invalid mem access 'inv'", + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: two calls with args", +@@ -11227,6 +11278,7 @@ static struct bpf_test tests[] = { + .fixup_map1 = { 12, 22 }, + .result = REJECT, + .errstr = "invalid access to map value, value_size=8 off=2 size=8", ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: two calls that receive map_value via arg=ptr_stack_of_caller. test2", +@@ -11370,6 +11422,7 @@ static struct bpf_test tests[] = { + .fixup_map1 = { 12, 22 }, + .result = REJECT, + .errstr = "invalid access to map value, value_size=8 off=2 size=8", ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: two calls that receive map_value_ptr_or_null via arg. test1", +@@ -11541,6 +11594,7 @@ static struct bpf_test tests[] = { + .result = ACCEPT, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .retval = POINTER_VALUE, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 2", +@@ -11572,6 +11626,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .errstr = "invalid access to packet", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 3", +@@ -11607,6 +11662,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = ACCEPT, + .retval = 1, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 4", +@@ -11641,6 +11697,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = ACCEPT, + .retval = 1, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 5", +@@ -11674,6 +11731,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .errstr = "same insn cannot be used with different", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 6", +@@ -11709,6 +11767,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .errstr = "R4 invalid mem access", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 7", +@@ -11743,6 +11802,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .errstr = "R4 invalid mem access", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 8", +@@ -11783,6 +11843,7 @@ static struct bpf_test tests[] = { + }, + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .result = ACCEPT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: pkt_ptr spill into caller stack 9", +@@ -11824,6 +11885,7 @@ static struct bpf_test tests[] = { + .prog_type = BPF_PROG_TYPE_SCHED_CLS, + .errstr = "invalid access to packet", + .result = REJECT, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "calls: caller stack init to zero or map_value_or_null", +@@ -12189,6 +12251,7 @@ static struct bpf_test tests[] = { + .result = REJECT, + .errstr = "BPF_XADD stores into R2 packet", + .prog_type = BPF_PROG_TYPE_XDP, ++ .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, + }, + { + "xadd/w check whether src/dst got mangled, 1", +@@ -12628,18 +12691,18 @@ static int create_map(uint32_t type, uint32_t size_key, + return fd; + } + +-static int create_prog_dummy1(void) ++static int create_prog_dummy1(enum bpf_map_type prog_type) + { + struct bpf_insn prog[] = { + BPF_MOV64_IMM(BPF_REG_0, 42), + BPF_EXIT_INSN(), + }; + +- return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, ++ return bpf_load_program(prog_type, prog, + ARRAY_SIZE(prog), "GPL", 0, NULL, 0); + } + +-static int create_prog_dummy2(int mfd, int idx) ++static int create_prog_dummy2(enum bpf_map_type prog_type, int mfd, int idx) + { + struct bpf_insn prog[] = { + BPF_MOV64_IMM(BPF_REG_3, idx), +@@ -12650,11 +12713,12 @@ static int create_prog_dummy2(int mfd, int idx) + BPF_EXIT_INSN(), + }; + +- return bpf_load_program(BPF_PROG_TYPE_SOCKET_FILTER, prog, ++ return bpf_load_program(prog_type, prog, + ARRAY_SIZE(prog), "GPL", 0, NULL, 0); + } + +-static int create_prog_array(uint32_t max_elem, int p1key) ++static int create_prog_array(enum bpf_map_type prog_type, uint32_t max_elem, ++ int p1key) + { + int p2key = 1; + int mfd, p1fd, p2fd; +@@ -12666,8 +12730,8 @@ static int create_prog_array(uint32_t max_elem, int p1key) + return -1; + } + +- p1fd = create_prog_dummy1(); +- p2fd = create_prog_dummy2(mfd, p2key); ++ p1fd = create_prog_dummy1(prog_type); ++ p2fd = create_prog_dummy2(prog_type, mfd, p2key); + if (p1fd < 0 || p2fd < 0) + goto out; + if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0) +@@ -12722,8 +12786,8 @@ static int create_cgroup_storage(void) + + static char bpf_vlog[UINT_MAX >> 8]; + +-static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog, +- int *map_fds) ++static void do_test_fixup(struct bpf_test *test, enum bpf_map_type prog_type, ++ struct bpf_insn *prog, int *map_fds) + { + int *fixup_map1 = test->fixup_map1; + int *fixup_map2 = test->fixup_map2; +@@ -12778,7 +12842,7 @@ static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog, + } + + if (*fixup_prog1) { +- map_fds[4] = create_prog_array(4, 0); ++ map_fds[4] = create_prog_array(prog_type, 4, 0); + do { + prog[*fixup_prog1].imm = map_fds[4]; + fixup_prog1++; +@@ -12786,7 +12850,7 @@ static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog, + } + + if (*fixup_prog2) { +- map_fds[5] = create_prog_array(8, 7); ++ map_fds[5] = create_prog_array(prog_type, 8, 7); + do { + prog[*fixup_prog2].imm = map_fds[5]; + fixup_prog2++; +@@ -12810,54 +12874,90 @@ static void do_test_fixup(struct bpf_test *test, struct bpf_insn *prog, + } + } + ++static int set_admin(bool admin) ++{ ++ cap_t caps; ++ const cap_value_t cap_val = CAP_SYS_ADMIN; ++ int ret = -1; ++ ++ caps = cap_get_proc(); ++ if (!caps) { ++ perror("cap_get_proc"); ++ return -1; ++ } ++ if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val, ++ admin ? CAP_SET : CAP_CLEAR)) { ++ perror("cap_set_flag"); ++ goto out; ++ } ++ if (cap_set_proc(caps)) { ++ perror("cap_set_proc"); ++ goto out; ++ } ++ ret = 0; ++out: ++ if (cap_free(caps)) ++ perror("cap_free"); ++ return ret; ++} ++ + static void do_test_single(struct bpf_test *test, bool unpriv, + int *passes, int *errors) + { +- int fd_prog, expected_ret, reject_from_alignment; ++ int fd_prog, expected_ret, alignment_prevented_execution; + int prog_len, prog_type = test->prog_type; + struct bpf_insn *prog = test->insns; + int map_fds[MAX_NR_MAPS]; + const char *expected_err; ++ uint32_t expected_val; + uint32_t retval; ++ __u32 pflags; + int i, err; + + for (i = 0; i < MAX_NR_MAPS; i++) + map_fds[i] = -1; + +- do_test_fixup(test, prog, map_fds); ++ if (!prog_type) ++ prog_type = BPF_PROG_TYPE_SOCKET_FILTER; ++ do_test_fixup(test, prog_type, prog, map_fds); + prog_len = probe_filter_length(prog); + +- fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER, +- prog, prog_len, test->flags & F_LOAD_WITH_STRICT_ALIGNMENT, ++ pflags = 0; ++ if (test->flags & F_LOAD_WITH_STRICT_ALIGNMENT) ++ pflags |= BPF_F_STRICT_ALIGNMENT; ++ if (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) ++ pflags |= BPF_F_ANY_ALIGNMENT; ++ fd_prog = bpf_verify_program(prog_type, prog, prog_len, pflags, + "GPL", 0, bpf_vlog, sizeof(bpf_vlog), 1); + + expected_ret = unpriv && test->result_unpriv != UNDEF ? + test->result_unpriv : test->result; + expected_err = unpriv && test->errstr_unpriv ? + test->errstr_unpriv : test->errstr; ++ expected_val = unpriv && test->retval_unpriv ? ++ test->retval_unpriv : test->retval; ++ ++ alignment_prevented_execution = 0; + +- reject_from_alignment = fd_prog < 0 && +- (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) && +- strstr(bpf_vlog, "misaligned"); +-#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS +- if (reject_from_alignment) { +- printf("FAIL\nFailed due to alignment despite having efficient unaligned access: '%s'!\n", +- strerror(errno)); +- goto fail_log; +- } +-#endif + if (expected_ret == ACCEPT) { +- if (fd_prog < 0 && !reject_from_alignment) { ++ if (fd_prog < 0) { + printf("FAIL\nFailed to load prog '%s'!\n", + strerror(errno)); + goto fail_log; + } ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ if (fd_prog >= 0 && ++ (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS)) { ++ alignment_prevented_execution = 1; ++ goto test_ok; ++ } ++#endif + } else { + if (fd_prog >= 0) { + printf("FAIL\nUnexpected success to load!\n"); + goto fail_log; + } +- if (!strstr(bpf_vlog, expected_err) && !reject_from_alignment) { ++ if (!strstr(bpf_vlog, expected_err)) { + printf("FAIL\nUnexpected error message!\n\tEXP: %s\n\tRES: %s\n", + expected_err, bpf_vlog); + goto fail_log; +@@ -12868,22 +12968,29 @@ static void do_test_single(struct bpf_test *test, bool unpriv, + __u8 tmp[TEST_DATA_LEN << 2]; + __u32 size_tmp = sizeof(tmp); + ++ if (unpriv) ++ set_admin(true); + err = bpf_prog_test_run(fd_prog, 1, test->data, + sizeof(test->data), tmp, &size_tmp, + &retval, NULL); ++ if (unpriv) ++ set_admin(false); + if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { + printf("Unexpected bpf_prog_test_run error\n"); + goto fail_log; + } +- if (!err && retval != test->retval && +- test->retval != POINTER_VALUE) { +- printf("FAIL retval %d != %d\n", retval, test->retval); ++ if (!err && retval != expected_val && ++ expected_val != POINTER_VALUE) { ++ printf("FAIL retval %d != %d\n", retval, expected_val); + goto fail_log; + } + } ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++test_ok: ++#endif + (*passes)++; +- printf("OK%s\n", reject_from_alignment ? +- " (NOTE: reject due to unknown alignment)" : ""); ++ printf("OK%s\n", alignment_prevented_execution ? ++ " (NOTE: not executed due to unknown alignment)" : ""); + close_fds: + close(fd_prog); + for (i = 0; i < MAX_NR_MAPS; i++) +@@ -12920,33 +13027,6 @@ static bool is_admin(void) + return (sysadmin == CAP_SET); + } + +-static int set_admin(bool admin) +-{ +- cap_t caps; +- const cap_value_t cap_val = CAP_SYS_ADMIN; +- int ret = -1; +- +- caps = cap_get_proc(); +- if (!caps) { +- perror("cap_get_proc"); +- return -1; +- } +- if (cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_val, +- admin ? CAP_SET : CAP_CLEAR)) { +- perror("cap_set_flag"); +- goto out; +- } +- if (cap_set_proc(caps)) { +- perror("cap_set_proc"); +- goto out; +- } +- ret = 0; +-out: +- if (cap_free(caps)) +- perror("cap_free"); +- return ret; +-} +- + static void get_unpriv_disabled() + { + char buf[2]; +@@ -12963,6 +13043,26 @@ static void get_unpriv_disabled() + fclose(fd); + } + ++static bool test_as_unpriv(struct bpf_test *test) ++{ ++#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ++ /* Some architectures have strict alignment requirements. In ++ * that case, the BPF verifier detects if a program has ++ * unaligned accesses and rejects them. A user can pass ++ * BPF_F_ANY_ALIGNMENT to a program to override this ++ * check. That, however, will only work when a privileged user ++ * loads a program. An unprivileged user loading a program ++ * with this flag will be rejected prior entering the ++ * verifier. ++ */ ++ if (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS) ++ return false; ++#endif ++ return !test->prog_type || ++ test->prog_type == BPF_PROG_TYPE_SOCKET_FILTER || ++ test->prog_type == BPF_PROG_TYPE_CGROUP_SKB; ++} ++ + static int do_test(bool unpriv, unsigned int from, unsigned int to) + { + int i, passes = 0, errors = 0, skips = 0; +@@ -12973,10 +13073,10 @@ static int do_test(bool unpriv, unsigned int from, unsigned int to) + /* Program types that are not supported by non-root we + * skip right away. + */ +- if (!test->prog_type && unpriv_disabled) { ++ if (test_as_unpriv(test) && unpriv_disabled) { + printf("#%d/u %s SKIP\n", i, test->descr); + skips++; +- } else if (!test->prog_type) { ++ } else if (test_as_unpriv(test)) { + if (!unpriv) + set_admin(false); + printf("#%d/u %s ", i, test->descr);