Merge 5.10.41 into android12-5.10

Changes in 5.10.41
	bpf: Wrap aux data inside bpf_sanitize_info container
	bpf: Fix mask direction swap upon off reg sign change
	bpf: No need to simulate speculative domain for immediates
	context_tracking: Move guest exit context tracking to separate helpers
	context_tracking: Move guest exit vtime accounting to separate helpers
	KVM: x86: Defer vtime accounting 'til after IRQ handling
	perf unwind: Fix separate debug info files when using elfutils' libdw's unwinder
	perf unwind: Set userdata for all __report_module() paths
	NFC: nci: fix memory leak in nci_allocate_device
	Linux 5.10.41

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: Ie9f14d4b9960fb923eb01303517012fe6274d5ef
This commit is contained in:
Greg Kroah-Hartman
2021-05-28 13:28:25 +02:00
10 changed files with 103 additions and 33 deletions

View File

@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 5
PATCHLEVEL = 10
SUBLEVEL = 40
SUBLEVEL = 41
EXTRAVERSION =
NAME = Dare mighty things

View File

@@ -3532,15 +3532,15 @@ static noinstr void svm_vcpu_enter_exit(struct kvm_vcpu *vcpu,
* have them in state 'on' as recorded before entering guest mode.
* Same as enter_from_user_mode().
*
* guest_exit_irqoff() restores host context and reinstates RCU if
* enabled and required.
* context_tracking_guest_exit() restores host context and reinstates
* RCU if enabled and required.
*
* This needs to be done before the below as native_read_msr()
* contains a tracepoint and x86_spec_ctrl_restore_host() calls
* into world and some more.
*/
lockdep_hardirqs_off(CALLER_ADDR0);
guest_exit_irqoff();
context_tracking_guest_exit();
instrumentation_begin();
trace_hardirqs_off_finish();

View File

@@ -6640,15 +6640,15 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
* have them in state 'on' as recorded before entering guest mode.
* Same as enter_from_user_mode().
*
* guest_exit_irqoff() restores host context and reinstates RCU if
* enabled and required.
* context_tracking_guest_exit() restores host context and reinstates
* RCU if enabled and required.
*
* This needs to be done before the below as native_read_msr()
* contains a tracepoint and x86_spec_ctrl_restore_host() calls
* into world and some more.
*/
lockdep_hardirqs_off(CALLER_ADDR0);
guest_exit_irqoff();
context_tracking_guest_exit();
instrumentation_begin();
trace_hardirqs_off_finish();

View File

@@ -9063,6 +9063,15 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
local_irq_disable();
kvm_after_interrupt(vcpu);
/*
* Wait until after servicing IRQs to account guest time so that any
* ticks that occurred while running the guest are properly accounted
* to the guest. Waiting until IRQs are enabled degrades the accuracy
* of accounting via context tracking, but the loss of accuracy is
* acceptable for all known use cases.
*/
vtime_account_guest_exit();
if (lapic_in_kernel(vcpu)) {
s64 delta = vcpu->arch.apic->lapic_timer.advance_expire_delta;
if (delta != S64_MIN) {

View File

@@ -129,16 +129,26 @@ static __always_inline void guest_enter_irqoff(void)
}
}
static __always_inline void guest_exit_irqoff(void)
static __always_inline void context_tracking_guest_exit(void)
{
if (context_tracking_enabled())
__context_tracking_exit(CONTEXT_GUEST);
}
instrumentation_begin();
static __always_inline void vtime_account_guest_exit(void)
{
if (vtime_accounting_enabled_this_cpu())
vtime_guest_exit(current);
else
current->flags &= ~PF_VCPU;
}
static __always_inline void guest_exit_irqoff(void)
{
context_tracking_guest_exit();
instrumentation_begin();
vtime_account_guest_exit();
instrumentation_end();
}
@@ -157,12 +167,19 @@ static __always_inline void guest_enter_irqoff(void)
instrumentation_end();
}
static __always_inline void context_tracking_guest_exit(void) { }
static __always_inline void vtime_account_guest_exit(void)
{
vtime_account_kernel(current);
current->flags &= ~PF_VCPU;
}
static __always_inline void guest_exit_irqoff(void)
{
instrumentation_begin();
/* Flush the guest cputime we spent on the guest */
vtime_account_kernel(current);
current->flags &= ~PF_VCPU;
vtime_account_guest_exit();
instrumentation_end();
}
#endif /* CONFIG_VIRT_CPU_ACCOUNTING_GEN */

View File

@@ -298,6 +298,7 @@ int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len,
struct sk_buff **resp);
struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev);
void nci_hci_deallocate(struct nci_dev *ndev);
int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
const u8 *param, size_t param_len);
int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate,

View File

@@ -5666,18 +5666,10 @@ enum {
};
static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
const struct bpf_reg_state *off_reg,
u32 *alu_limit, u8 opcode)
u32 *alu_limit, bool mask_to_left)
{
bool off_is_neg = off_reg->smin_value < 0;
bool mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
(opcode == BPF_SUB && !off_is_neg);
u32 max = 0, ptr_limit = 0;
if (!tnum_is_const(off_reg->var_off) &&
(off_reg->smin_value < 0) != (off_reg->smax_value < 0))
return REASON_BOUNDS;
switch (ptr_reg->type) {
case PTR_TO_STACK:
/* Offset 0 is out-of-bounds, but acceptable start for the
@@ -5743,15 +5735,20 @@ static bool sanitize_needed(u8 opcode)
return opcode == BPF_ADD || opcode == BPF_SUB;
}
struct bpf_sanitize_info {
struct bpf_insn_aux_data aux;
bool mask_to_left;
};
static int sanitize_ptr_alu(struct bpf_verifier_env *env,
struct bpf_insn *insn,
const struct bpf_reg_state *ptr_reg,
const struct bpf_reg_state *off_reg,
struct bpf_reg_state *dst_reg,
struct bpf_insn_aux_data *tmp_aux,
struct bpf_sanitize_info *info,
const bool commit_window)
{
struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : tmp_aux;
struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : &info->aux;
struct bpf_verifier_state *vstate = env->cur_state;
bool off_is_imm = tnum_is_const(off_reg->var_off);
bool off_is_neg = off_reg->smin_value < 0;
@@ -5772,7 +5769,16 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
if (vstate->speculative)
goto do_sim;
err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode);
if (!commit_window) {
if (!tnum_is_const(off_reg->var_off) &&
(off_reg->smin_value < 0) != (off_reg->smax_value < 0))
return REASON_BOUNDS;
info->mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
(opcode == BPF_SUB && !off_is_neg);
}
err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left);
if (err < 0)
return err;
@@ -5780,8 +5786,8 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
/* In commit phase we narrow the masking window based on
* the observed pointer move after the simulated operation.
*/
alu_state = tmp_aux->alu_state;
alu_limit = abs(tmp_aux->alu_limit - alu_limit);
alu_state = info->aux.alu_state;
alu_limit = abs(info->aux.alu_limit - alu_limit);
} else {
alu_state = off_is_neg ? BPF_ALU_NEG_VALUE : 0;
alu_state |= off_is_imm ? BPF_ALU_IMMEDIATE : 0;
@@ -5796,8 +5802,12 @@ do_sim:
/* If we're in commit phase, we're done here given we already
* pushed the truncated dst_reg into the speculative verification
* stack.
*
* Also, when register is a known constant, we rewrite register-based
* operation to immediate-based, and thus do not need masking (and as
* a consequence, do not need to simulate the zero-truncation either).
*/
if (commit_window)
if (commit_window || off_is_imm)
return 0;
/* Simulate and find potential out-of-bounds access under
@@ -5942,7 +5952,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value;
u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value,
umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value;
struct bpf_insn_aux_data tmp_aux = {};
struct bpf_sanitize_info info = {};
u8 opcode = BPF_OP(insn->code);
u32 dst = insn->dst_reg;
int ret;
@@ -6011,7 +6021,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
if (sanitize_needed(opcode)) {
ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,
&tmp_aux, false);
&info, false);
if (ret < 0)
return sanitize_err(env, insn, ret, off_reg, dst_reg);
}
@@ -6152,7 +6162,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
return -EACCES;
if (sanitize_needed(opcode)) {
ret = sanitize_ptr_alu(env, insn, dst_reg, off_reg, dst_reg,
&tmp_aux, true);
&info, true);
if (ret < 0)
return sanitize_err(env, insn, ret, off_reg, dst_reg);
}

View File

@@ -1175,6 +1175,7 @@ EXPORT_SYMBOL(nci_allocate_device);
void nci_free_device(struct nci_dev *ndev)
{
nfc_free_device(ndev->nfc_dev);
nci_hci_deallocate(ndev);
kfree(ndev);
}
EXPORT_SYMBOL(nci_free_device);

View File

@@ -795,3 +795,8 @@ struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev)
return hdev;
}
void nci_hci_deallocate(struct nci_dev *ndev)
{
kfree(ndev->hci_dev);
}

View File

@@ -20,10 +20,24 @@
static char *debuginfo_path;
static int __find_debuginfo(Dwfl_Module *mod __maybe_unused, void **userdata,
const char *modname __maybe_unused, Dwarf_Addr base __maybe_unused,
const char *file_name, const char *debuglink_file __maybe_unused,
GElf_Word debuglink_crc __maybe_unused, char **debuginfo_file_name)
{
const struct dso *dso = *userdata;
assert(dso);
if (dso->symsrc_filename && strcmp (file_name, dso->symsrc_filename))
*debuginfo_file_name = strdup(dso->symsrc_filename);
return -1;
}
static const Dwfl_Callbacks offline_callbacks = {
.find_debuginfo = dwfl_standard_find_debuginfo,
.find_debuginfo = __find_debuginfo,
.debuginfo_path = &debuginfo_path,
.section_address = dwfl_offline_section_address,
// .find_elf is not set as we use dwfl_report_elf() instead.
};
static int __report_module(struct addr_location *al, u64 ip,
@@ -53,9 +67,22 @@ static int __report_module(struct addr_location *al, u64 ip,
}
if (!mod)
mod = dwfl_report_elf(ui->dwfl, dso->short_name,
(dso->symsrc_filename ? dso->symsrc_filename : dso->long_name), -1, al->map->start - al->map->pgoff,
false);
mod = dwfl_report_elf(ui->dwfl, dso->short_name, dso->long_name, -1,
al->map->start - al->map->pgoff, false);
if (!mod) {
char filename[PATH_MAX];
if (dso__build_id_filename(dso, filename, sizeof(filename), false))
mod = dwfl_report_elf(ui->dwfl, dso->short_name, filename, -1,
al->map->start - al->map->pgoff, false);
}
if (mod) {
void **userdatap;
dwfl_module_info(mod, &userdatap, NULL, NULL, NULL, NULL, NULL, NULL);
*userdatap = dso;
}
return mod && dwfl_addrmodule(ui->dwfl, ip) == mod ? 0 : -1;
}