commit: b8fb76f331e61bb279309ae39b860435aa6748c1 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Sun Aug 15 20:07:18 2021 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Sun Aug 15 20:07:18 2021 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=b8fb76f3
Linux patch 4.19.204 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> 0000_README | 4 + 1203_linux-4.19.204.patch | 434 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 438 insertions(+) diff --git a/0000_README b/0000_README index d01fd15..398311f 100644 --- a/0000_README +++ b/0000_README @@ -851,6 +851,10 @@ Patch: 1202_linux-4.19.203.patch From: https://www.kernel.org Desc: Linux 4.19.203 +Patch: 1203_linux-4.19.204.patch +From: https://www.kernel.org +Desc: Linux 4.19.204 + 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/1203_linux-4.19.204.patch b/1203_linux-4.19.204.patch new file mode 100644 index 0000000..94c62e8 --- /dev/null +++ b/1203_linux-4.19.204.patch @@ -0,0 +1,434 @@ +diff --git a/Documentation/virtual/kvm/mmu.txt b/Documentation/virtual/kvm/mmu.txt +index e507a9e0421ed..851a8abcadce4 100644 +--- a/Documentation/virtual/kvm/mmu.txt ++++ b/Documentation/virtual/kvm/mmu.txt +@@ -152,8 +152,8 @@ Shadow pages contain the following information: + shadow pages) so role.quadrant takes values in the range 0..3. Each + quadrant maps 1GB virtual address space. + role.access: +- Inherited guest access permissions in the form uwx. Note execute +- permission is positive, not negative. ++ Inherited guest access permissions from the parent ptes in the form uwx. ++ Note execute permission is positive, not negative. + role.invalid: + The page is invalid and should not be used. It is a root page that is + currently pinned (by a cpu hardware register pointing to it); once it is +diff --git a/Makefile b/Makefile +index 6d2670300d470..d4ffcafb8efad 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 4 + PATCHLEVEL = 19 +-SUBLEVEL = 203 ++SUBLEVEL = 204 + EXTRAVERSION = + NAME = "People's Front" + +diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h +index 8220190b06050..9e15818de9737 100644 +--- a/arch/x86/kvm/paging_tmpl.h ++++ b/arch/x86/kvm/paging_tmpl.h +@@ -93,8 +93,8 @@ struct guest_walker { + gpa_t pte_gpa[PT_MAX_FULL_LEVELS]; + pt_element_t __user *ptep_user[PT_MAX_FULL_LEVELS]; + bool pte_writable[PT_MAX_FULL_LEVELS]; +- unsigned pt_access; +- unsigned pte_access; ++ unsigned int pt_access[PT_MAX_FULL_LEVELS]; ++ unsigned int pte_access; + gfn_t gfn; + struct x86_exception fault; + }; +@@ -388,13 +388,15 @@ retry_walk: + } + + walker->ptes[walker->level - 1] = pte; ++ ++ /* Convert to ACC_*_MASK flags for struct guest_walker. */ ++ walker->pt_access[walker->level - 1] = FNAME(gpte_access)(pt_access ^ walk_nx_mask); + } while (!is_last_gpte(mmu, walker->level, pte)); + + pte_pkey = FNAME(gpte_pkeys)(vcpu, pte); + accessed_dirty = have_ad ? pte_access & PT_GUEST_ACCESSED_MASK : 0; + + /* Convert to ACC_*_MASK flags for struct guest_walker. */ +- walker->pt_access = FNAME(gpte_access)(pt_access ^ walk_nx_mask); + walker->pte_access = FNAME(gpte_access)(pte_access ^ walk_nx_mask); + errcode = permission_fault(vcpu, mmu, walker->pte_access, pte_pkey, access); + if (unlikely(errcode)) +@@ -433,7 +435,8 @@ retry_walk: + } + + pgprintk("%s: pte %llx pte_access %x pt_access %x\n", +- __func__, (u64)pte, walker->pte_access, walker->pt_access); ++ __func__, (u64)pte, walker->pte_access, ++ walker->pt_access[walker->level - 1]); + return 1; + + error: +@@ -602,7 +605,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, + { + struct kvm_mmu_page *sp = NULL; + struct kvm_shadow_walk_iterator it; +- unsigned direct_access, access = gw->pt_access; ++ unsigned int direct_access, access; + int top_level, ret; + gfn_t gfn, base_gfn; + +@@ -634,6 +637,7 @@ static int FNAME(fetch)(struct kvm_vcpu *vcpu, gpa_t addr, + sp = NULL; + if (!is_shadow_present_pte(*it.sptep)) { + table_gfn = gw->table_gfn[it.level - 2]; ++ access = gw->pt_access[it.level - 2]; + sp = kvm_mmu_get_page(vcpu, table_gfn, addr, it.level-1, + false, access); + } +diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c +index bd463d6842370..72d729f34437d 100644 +--- a/arch/x86/kvm/svm.c ++++ b/arch/x86/kvm/svm.c +@@ -1780,7 +1780,7 @@ static void __sev_asid_free(int asid) + + for_each_possible_cpu(cpu) { + sd = per_cpu(svm_data, cpu); +- sd->sev_vmcbs[pos] = NULL; ++ sd->sev_vmcbs[asid] = NULL; + } + } + +diff --git a/drivers/net/ethernet/xilinx/xilinx_emaclite.c b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +index c77c81eb7ab3b..edb2215f99930 100644 +--- a/drivers/net/ethernet/xilinx/xilinx_emaclite.c ++++ b/drivers/net/ethernet/xilinx/xilinx_emaclite.c +@@ -1177,9 +1177,8 @@ static int xemaclite_of_probe(struct platform_device *ofdev) + } + + dev_info(dev, +- "Xilinx EmacLite at 0x%08X mapped to 0x%08X, irq=%d\n", +- (unsigned int __force)ndev->mem_start, +- (unsigned int __force)lp->base_addr, ndev->irq); ++ "Xilinx EmacLite at 0x%08X mapped to 0x%p, irq=%d\n", ++ (unsigned int __force)ndev->mem_start, lp->base_addr, ndev->irq); + return 0; + + error: +diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c +index 3e014ecffef8e..1af47aaa7ba57 100644 +--- a/drivers/net/ppp/ppp_generic.c ++++ b/drivers/net/ppp/ppp_generic.c +@@ -287,7 +287,7 @@ static struct channel *ppp_find_channel(struct ppp_net *pn, int unit); + static int ppp_connect_channel(struct channel *pch, int unit); + static int ppp_disconnect_channel(struct channel *pch); + static void ppp_destroy_channel(struct channel *pch); +-static int unit_get(struct idr *p, void *ptr); ++static int unit_get(struct idr *p, void *ptr, int min); + static int unit_set(struct idr *p, void *ptr, int n); + static void unit_put(struct idr *p, int n); + static void *unit_find(struct idr *p, int n); +@@ -963,9 +963,20 @@ static int ppp_unit_register(struct ppp *ppp, int unit, bool ifname_is_set) + mutex_lock(&pn->all_ppp_mutex); + + if (unit < 0) { +- ret = unit_get(&pn->units_idr, ppp); ++ ret = unit_get(&pn->units_idr, ppp, 0); + if (ret < 0) + goto err; ++ if (!ifname_is_set) { ++ while (1) { ++ snprintf(ppp->dev->name, IFNAMSIZ, "ppp%i", ret); ++ if (!__dev_get_by_name(ppp->ppp_net, ppp->dev->name)) ++ break; ++ unit_put(&pn->units_idr, ret); ++ ret = unit_get(&pn->units_idr, ppp, ret + 1); ++ if (ret < 0) ++ goto err; ++ } ++ } + } else { + /* Caller asked for a specific unit number. Fail with -EEXIST + * if unavailable. For backward compatibility, return -EEXIST +@@ -3252,9 +3263,9 @@ static int unit_set(struct idr *p, void *ptr, int n) + } + + /* get new free unit number and associate pointer with it */ +-static int unit_get(struct idr *p, void *ptr) ++static int unit_get(struct idr *p, void *ptr, int min) + { +- return idr_alloc(p, ptr, 0, 0, GFP_KERNEL); ++ return idr_alloc(p, ptr, min, 0, GFP_KERNEL); + } + + /* put unit number back to a pool */ +diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c +index fcfad5c298a9f..56e6fd0f04829 100644 +--- a/drivers/usb/host/ehci-pci.c ++++ b/drivers/usb/host/ehci-pci.c +@@ -298,6 +298,9 @@ static int ehci_pci_setup(struct usb_hcd *hcd) + if (pdev->vendor == PCI_VENDOR_ID_STMICRO + && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) + ; /* ConneXT has no sbrn register */ ++ else if (pdev->vendor == PCI_VENDOR_ID_HUAWEI ++ && pdev->device == 0xa239) ++ ; /* HUAWEI Kunpeng920 USB EHCI has no sbrn register */ + else + pci_read_config_byte(pdev, 0x60, &ehci->sbrn); + +diff --git a/fs/namespace.c b/fs/namespace.c +index 741f40cd955ef..edd397fa29913 100644 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@ -1799,6 +1799,20 @@ void drop_collected_mounts(struct vfsmount *mnt) + namespace_unlock(); + } + ++static bool has_locked_children(struct mount *mnt, struct dentry *dentry) ++{ ++ struct mount *child; ++ ++ list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) { ++ if (!is_subdir(child->mnt_mountpoint, dentry)) ++ continue; ++ ++ if (child->mnt.mnt_flags & MNT_LOCKED) ++ return true; ++ } ++ return false; ++} ++ + /** + * clone_private_mount - create a private clone of a path + * +@@ -1813,14 +1827,27 @@ struct vfsmount *clone_private_mount(const struct path *path) + struct mount *old_mnt = real_mount(path->mnt); + struct mount *new_mnt; + ++ down_read(&namespace_sem); + if (IS_MNT_UNBINDABLE(old_mnt)) +- return ERR_PTR(-EINVAL); ++ goto invalid; ++ ++ if (!check_mnt(old_mnt)) ++ goto invalid; ++ ++ if (has_locked_children(old_mnt, path->dentry)) ++ goto invalid; + + new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE); ++ up_read(&namespace_sem); ++ + if (IS_ERR(new_mnt)) + return ERR_CAST(new_mnt); + + return &new_mnt->mnt; ++ ++invalid: ++ up_read(&namespace_sem); ++ return ERR_PTR(-EINVAL); + } + EXPORT_SYMBOL_GPL(clone_private_mount); + +@@ -2136,19 +2163,6 @@ static int do_change_type(struct path *path, int ms_flags) + return err; + } + +-static bool has_locked_children(struct mount *mnt, struct dentry *dentry) +-{ +- struct mount *child; +- list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) { +- if (!is_subdir(child->mnt_mountpoint, dentry)) +- continue; +- +- if (child->mnt.mnt_flags & MNT_LOCKED) +- return true; +- } +- return false; +-} +- + /* + * do loopback mount. + */ +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 4ce032c4acd03..2bf83305e5aba 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2812,6 +2812,27 @@ struct bpf_sanitize_info { + bool mask_to_left; + }; + ++static struct bpf_verifier_state * ++sanitize_speculative_path(struct bpf_verifier_env *env, ++ const struct bpf_insn *insn, ++ u32 next_idx, u32 curr_idx) ++{ ++ struct bpf_verifier_state *branch; ++ struct bpf_reg_state *regs; ++ ++ branch = push_stack(env, next_idx, curr_idx, true); ++ if (branch && insn) { ++ regs = branch->frame[branch->curframe]->regs; ++ if (BPF_SRC(insn->code) == BPF_K) { ++ mark_reg_unknown(env, regs, insn->dst_reg); ++ } else if (BPF_SRC(insn->code) == BPF_X) { ++ mark_reg_unknown(env, regs, insn->dst_reg); ++ mark_reg_unknown(env, regs, insn->src_reg); ++ } ++ } ++ return branch; ++} ++ + static int sanitize_ptr_alu(struct bpf_verifier_env *env, + struct bpf_insn *insn, + const struct bpf_reg_state *ptr_reg, +@@ -2895,12 +2916,26 @@ do_sim: + tmp = *dst_reg; + *dst_reg = *ptr_reg; + } +- ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true); ++ ret = sanitize_speculative_path(env, NULL, env->insn_idx + 1, ++ env->insn_idx); + if (!ptr_is_dst_reg && ret) + *dst_reg = tmp; + return !ret ? REASON_STACK : 0; + } + ++static void sanitize_mark_insn_seen(struct bpf_verifier_env *env) ++{ ++ struct bpf_verifier_state *vstate = env->cur_state; ++ ++ /* If we simulate paths under speculation, we don't update the ++ * insn as 'seen' such that when we verify unreachable paths in ++ * the non-speculative domain, sanitize_dead_code() can still ++ * rewrite/sanitize them. ++ */ ++ if (!vstate->speculative) ++ env->insn_aux_data[env->insn_idx].seen = true; ++} ++ + static int sanitize_err(struct bpf_verifier_env *env, + const struct bpf_insn *insn, int reason, + const struct bpf_reg_state *off_reg, +@@ -4275,14 +4310,28 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env, + tnum_is_const(src_reg->var_off)) + pred = is_branch_taken(dst_reg, src_reg->var_off.value, + opcode); ++ + if (pred == 1) { +- /* only follow the goto, ignore fall-through */ ++ /* Only follow the goto, ignore fall-through. If needed, push ++ * the fall-through branch for simulation under speculative ++ * execution. ++ */ ++ if (!env->allow_ptr_leaks && ++ !sanitize_speculative_path(env, insn, *insn_idx + 1, ++ *insn_idx)) ++ return -EFAULT; + *insn_idx += insn->off; + return 0; + } else if (pred == 0) { +- /* only follow fall-through branch, since +- * that's where the program will go ++ /* Only follow the fall-through branch, since that's where the ++ * program will go. If needed, push the goto branch for ++ * simulation under speculative execution. + */ ++ if (!env->allow_ptr_leaks && ++ !sanitize_speculative_path(env, insn, ++ *insn_idx + insn->off + 1, ++ *insn_idx)) ++ return -EFAULT; + return 0; + } + +@@ -5254,7 +5303,7 @@ static int do_check(struct bpf_verifier_env *env) + } + + regs = cur_regs(env); +- env->insn_aux_data[env->insn_idx].seen = true; ++ sanitize_mark_insn_seen(env); + + if (class == BPF_ALU || class == BPF_ALU64) { + err = check_alu_op(env, insn); +@@ -5472,7 +5521,7 @@ process_bpf_exit: + return err; + + env->insn_idx++; +- env->insn_aux_data[env->insn_idx].seen = true; ++ sanitize_mark_insn_seen(env); + } else { + verbose(env, "invalid BPF_LD mode\n"); + return -EINVAL; +@@ -5690,6 +5739,7 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env, u32 prog_len, + u32 off, u32 cnt) + { + struct bpf_insn_aux_data *new_data, *old_data = env->insn_aux_data; ++ bool old_seen = old_data[off].seen; + int i; + + if (cnt == 1) +@@ -5701,8 +5751,10 @@ static int adjust_insn_aux_data(struct bpf_verifier_env *env, u32 prog_len, + memcpy(new_data, old_data, sizeof(struct bpf_insn_aux_data) * off); + memcpy(new_data + off + cnt - 1, old_data + off, + sizeof(struct bpf_insn_aux_data) * (prog_len - off - cnt + 1)); +- for (i = off; i < off + cnt - 1; i++) +- new_data[i].seen = true; ++ for (i = off; i < off + cnt - 1; i++) { ++ /* Expand insni[off]'s seen count to the patched range. */ ++ new_data[i].seen = old_seen; ++ } + env->insn_aux_data = new_data; + vfree(old_data); + return 0; +diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c +index 6d2a69652c391..bbde8d3d6c8ae 100644 +--- a/kernel/trace/trace_events_hist.c ++++ b/kernel/trace/trace_events_hist.c +@@ -2790,6 +2790,12 @@ static struct hist_field *parse_unary(struct hist_trigger_data *hist_data, + ret = PTR_ERR(operand1); + goto free; + } ++ if (operand1->flags & HIST_FIELD_FL_STRING) { ++ /* String type can not be the operand of unary operator. */ ++ destroy_hist_field(operand1, 0); ++ ret = -EINVAL; ++ goto free; ++ } + + expr->flags |= operand1->flags & + (HIST_FIELD_FL_TIMESTAMP | HIST_FIELD_FL_TIMESTAMP_USECS); +@@ -2890,6 +2896,10 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data, + operand1 = NULL; + goto free; + } ++ if (operand1->flags & HIST_FIELD_FL_STRING) { ++ ret = -EINVAL; ++ goto free; ++ } + + /* rest of string could be another expression e.g. b+c in a+b+c */ + operand_flags = 0; +@@ -2899,6 +2909,10 @@ static struct hist_field *parse_expr(struct hist_trigger_data *hist_data, + operand2 = NULL; + goto free; + } ++ if (operand2->flags & HIST_FIELD_FL_STRING) { ++ ret = -EINVAL; ++ goto free; ++ } + + ret = check_expr_operands(operand1, operand2); + if (ret) +diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c +index b44324530948d..c7d17781dbfee 100644 +--- a/tools/testing/selftests/bpf/test_verifier.c ++++ b/tools/testing/selftests/bpf/test_verifier.c +@@ -2792,6 +2792,8 @@ static struct bpf_test tests[] = { + BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_7, 0), + BPF_EXIT_INSN(), + }, ++ .errstr_unpriv = "R7 invalid mem access 'inv'", ++ .result_unpriv = REJECT, + .result = ACCEPT, + .retval = 0, + },
