> Second, I don't understand your explanation. WDYM by "after the access
> permission check"? It gets invoked for BPF_WRITE, so should be rejecting
> res->key = 42 if 'res' is a pointer with PTR_UNTRUSTED flag set. What am I
> missing?
The direct write will pass this earlier permission check since
type_is_ptr_alloc_obj does not check PTR_UNTRUSTED:
if (atype != BPF_READ && !type_is_ptr_alloc_obj(reg->type))
return -EACCES;
The later PTR_UNTRUSTED branch is not a rejection check. It means when
accessing a pointer field through an untrusted parent pointer,
propagate PTR_UNTRUSTED to the child pointer.
if (ret != PTR_TO_BTF_ID) {
/* just mark; */
} else if (type_flag(reg->type) & PTR_UNTRUSTED) {
/* If this is an untrusted pointer, all pointers formed by walking it
* also inherit the untrusted flag.
*/
flag = PTR_UNTRUSTED;
}
For res->key = 42, key is a scalar, so ret != PTR_TO_BTF_ID. Therefore
the second branch is skipped and has no effect.