return -EACCES;
}
- if (type_is_alloc(reg->type) && !type_is_non_owning_ref(reg->type) &&
+ /*
+ * A fault-prone allocated object may still be read through a
+ * BPF_PROBE_MEM load after its lifetime protection ends. Writes
+ * through such pointers were rejected above.
+ */
+ if (type_is_alloc(reg->type) && !bpf_may_fault_on_deref(reg->type) &&
+ !type_is_non_owning_ref(reg->type) &&
!(reg->type & MEM_RCU) && !reg_is_referenced(env, reg)) {
verifier_bug(env, "allocated object must have a referenced id");
return -EFAULT;
lock);
return -EINVAL;
}
+ /*
+ * Invalidate non-owning refs before RCU demotion clears their
+ * NON_OWN_REF flag.
+ */
+ invalidate_non_owning_refs(env);
+
if (!in_rcu_cs(env))
invalidate_rcu_protected_refs(env);
-
- invalidate_non_owning_refs(env);
}
return 0;
}
bpf_for_each_reg_in_vstate_mask(env->cur_state, state, reg, stack, clear_mask, ({
if (reg->type & MEM_RCU) {
bpf_diag_mod_begin(env, reg, NULL, BPF_DIAG_MOD_WRITE);
- reg->type &= ~(MEM_RCU | PTR_MAYBE_NULL);
+ reg->type &= ~(MEM_RCU | PTR_MAYBE_NULL | NON_OWN_REF);
reg->type |= PTR_UNTRUSTED;
bpf_diag_mod_end(env);
}