On 8/20/24 2:29 AM, Tze-nan Wu wrote:
The return value from `cgroup_bpf_enabled(CGROUP_GETSOCKOPT)` can change between the invocations of `BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN` and `BPF_CGROUP_RUN_PROG_GETSOCKOPT`. If `cgroup_bpf_enabled(CGROUP_GETSOCKOPT)` changes from "false" to "true" between the invocations of `BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN` and `BPF_CGROUP_RUN_PROG_GETSOCKOPT`, `BPF_CGROUP_RUN_PROG_GETSOCKOPT` will receive an -EFAULT from `__cgroup_bpf_run_filter_getsockopt(max_optlen=0)` due to `get_user()` was not reached in `BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN`. Scenario shown as below: `process A` `process B` ----------- ------------ BPF_CGROUP_GETSOCKOPT_MAX_OPTLEN enable CGROUP_GETSOCKOPT BPF_CGROUP_RUN_PROG_GETSOCKOPT (-EFAULT) To prevent this, invoke `cgroup_bpf_enabled()` only once and cache the result in a newly added local variable `enabled`. Both `BPF_CGROUP_*` macros in `do_sock_getsockopt` will then check their condition using the same `enabled` variable as the condition variable, instead of using the return values from `cgroup_bpf_enabled` called by themselves as the condition variable(which could yield different results). This ensures that either both `BPF_CGROUP_*` macros pass the condition or neither does. Co-developed-by: Yanghui Li <yanghui.li@xxxxxxxxxxxx> Signed-off-by: Yanghui Li <yanghui.li@xxxxxxxxxxxx> Co-developed-by: Cheng-Jui Wang <cheng-jui.wang@xxxxxxxxxxxx> Signed-off-by: Cheng-Jui Wang <cheng-jui.wang@xxxxxxxxxxxx> Signed-off-by: Tze-nan Wu <Tze-nan.Wu@xxxxxxxxxxxx>
Please tag bpf in the subject and add a Fixes tag. [cc: Stanislav] pw-bot: cr