Re: [PATCH bpf-next 1/2] bpf: Migrate release_on_unlock logic to non-owning ref semantics

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/29/22 8:13 PM, Alexei Starovoitov wrote:
> On Thu, Dec 29, 2022 at 5:07 PM Alexei Starovoitov
> <alexei.starovoitov@xxxxxxxxx> wrote:
>> @@ -11959,7 +11956,10 @@ static int check_ld_imm(struct bpf_verifier_env *env, struct bpf_insn *insn)
>>                 dst_reg->type = PTR_TO_MAP_VALUE;
>>                 dst_reg->off = aux->map_off;
>>                 WARN_ON_ONCE(map->max_entries != 1);
>> -               /* We want reg->id to be same (0) as map_value is not distinct */
>> +               /* map->id is positive s32. Negative map->id will not collide with env->id_gen.
>> +                * This lets us track active_lock state as single u32 instead of pair { map|btf, id }
>> +                */
>> +               dst_reg->id = -map->id;
> 
> Here is what I meant in my earlier reply to Dave's patches 1 and 2.
> imo this is a simpler implementation of the same logic.
> The only tricky part is above bit that is necessary
> to use a single u32 in bpf_reg_state to track active_lock.
> We can follow up with clean up of active_lock comparison
> in other places of the verifier.
> Instead of:
>                 if (map)
>                         cur->active_lock.ptr = map;
>                 else
>                         cur->active_lock.ptr = btf;
>                 cur->active_lock.id = reg->id;
> it will be:
>   cur->active_lock_id = reg->id;
> 
> Another cleanup is needed to compare active_lock_id properly
> in regsafe().
> 
> Thoughts?

Before Kumar's commit d0d78c1df9b1d ("bpf: Allow locking bpf_spin_lock global
variables"), setting of dst_reg->id in that code path was guarded by "does
map val have spin_lock check":

  if (btf_record_has_field(map->record, BPF_SPIN_LOCK))
    dst_reg->id = ++env->id_gen;

Should we do that here as well? Not sure what the implications of overzealous
setting of dst_reg->id are.


More generally: I see why doing -map->id will not overlap with env->id_gen
in practice. For PTR_TO_BTF_ID, I'm not sure that we'll always have a nonzero
reg->id here. check_kfunc_call has

  if (reg_may_point_to_spin_lock(&regs[BPF_REG_0]) && !regs[BPF_REG_0].id)
    regs[BPF_REG_0].id = ++env->id_gen;

when checking retval, but there's no such equivalent in check_helper_call,
which instead does

  if (type_may_be_null(regs[BPF_REG_0].type))
    regs[BPF_REG_0].id = ++env->id_gen;

and similar in a few paths.

Should we ensure that "any PTR_TO_BTF_ID reg that has a spin_lock must
have a nonzero id"? If we don't, a helper which returns
PTR_TO_BTF_ID w/ spin_lock that isn't MAYBE_NULL will break this whole scheme.


Some future-proofing concerns:

Kumar's commit above mentions this in the summary:

  Note that this can be extended in the future to also remember offset
  used for locking, so that we can introduce multiple bpf_spin_lock fields
  in the same allocation.

When the above happens we'll need to go back to a struct - or some packed
int - to describe "lock identity" anyways.

IIRC in the long term we wanted to stop overloading reg->id's meaning,
with the ideal end state being reg->id used only for "null id" purposes. If so,
this is moving us back towards the overloaded state.

Happy to take this over and respin once we're done discussing, unless you
want to do it.



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux