Merge 4.19.204 into android-4.19-stable

Changes in 4.19.204
	KVM: SVM: Fix off-by-one indexing when nullifying last used SEV VMCB
	tracing: Reject string operand in the histogram expression
	bpf: Inherit expanded/patched seen count from old aux data
	bpf: Do not mark insn as seen under speculative path verification
	bpf: Fix leakage under speculation on mispredicted branches
	bpf, selftests: Adjust few selftest outcomes wrt unreachable code
	KVM: X86: MMU: Use the correct inherited permissions to get shadow page
	USB:ehci:fix Kunpeng920 ehci hardware problem
	ppp: Fix generating ppp unit id when ifname is not specified
	ovl: prevent private clone if bind mount is not allowed
	net: xilinx_emaclite: Do not print real IOMEM pointer
	Linux 4.19.204

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I976cb68d2906fa68add207bca749a1964378c916
This commit is contained in:
Greg Kroah-Hartman
2021-08-15 14:05:09 +02:00
11 changed files with 137 additions and 38 deletions

View File

@@ -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

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 4
PATCHLEVEL = 19
SUBLEVEL = 203
SUBLEVEL = 204
EXTRAVERSION =
NAME = "People's Front"

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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:

View File

@@ -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
@@ -3300,9 +3311,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 */

View File

@@ -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);

View File

@@ -1817,6 +1817,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
*
@@ -1831,14 +1845,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);
@@ -2154,19 +2181,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.
*/

View File

@@ -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;

View File

@@ -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)

View File

@@ -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,
},