When tracing the incoming events, if a bpf program is already loaded, the next bpf program will see the potentially changed data. Add a flag to BPF_LINK_CREATE that allows to chose the position of the inserted program: at the beginning or at the end. This way, we can have a tracing program that compare the raw event from the device and the transformed stream from all the other bpf programs. Signed-off-by: Benjamin Tissoires <benjamin.tissoires@xxxxxxxxxx> --- new in v2 --- include/uapi/linux/bpf.h | 10 ++++++++++ kernel/bpf/hid.c | 11 +++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 417cf1c31579..23ebe5e96d69 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -1123,6 +1123,16 @@ enum bpf_link_type { */ #define BPF_F_XDP_HAS_FRAGS (1U << 5) +/* HID flag used in BPF_LINK_CREATE command + * + * NONE(default): The bpf program will be added at the tail of the list + * of existing bpf program for this type. + * + * BPF_F_INSERT_HEAD: The bpf program will be added at the beginning + * of the list of existing bpf program for this type.. + */ +#define BPF_F_INSERT_HEAD (1U << 0) + /* When BPF ldimm64's insn[0].src_reg != 0 then this can have * the following extensions: * diff --git a/kernel/bpf/hid.c b/kernel/bpf/hid.c index b3dc1cd37a3e..141eb4169079 100644 --- a/kernel/bpf/hid.c +++ b/kernel/bpf/hid.c @@ -416,7 +416,7 @@ static int bpf_hid_max_progs(enum bpf_hid_attach_type type) } static int bpf_hid_link_attach(struct hid_device *hdev, struct bpf_link *link, - enum bpf_hid_attach_type type) + enum bpf_hid_attach_type type, u32 flags) { struct bpf_hid_link *hid_link = container_of(link, struct bpf_hid_link, link); @@ -443,7 +443,10 @@ static int bpf_hid_link_attach(struct hid_device *hdev, struct bpf_link *link, goto out_unlock; } - list_add_tail(&hid_link->node, &hdev->bpf.links[type]); + if (flags & BPF_F_INSERT_HEAD) + list_add(&hid_link->node, &hdev->bpf.links[type]); + else + list_add_tail(&hid_link->node, &hdev->bpf.links[type]); fill_prog_array(hdev, type, run_array); run_array = rcu_replace_pointer(hdev->bpf.run_array[type], run_array, @@ -467,7 +470,7 @@ int bpf_hid_link_create(const union bpf_attr *attr, struct bpf_prog *prog) struct hid_device *hdev; int err; - if (attr->link_create.flags || !hid_hooks.hdev_from_fd) + if ((attr->link_create.flags & ~BPF_F_INSERT_HEAD) || !hid_hooks.hdev_from_fd) return -EINVAL; type = attr->link_create.attach_type; @@ -495,7 +498,7 @@ int bpf_hid_link_create(const union bpf_attr *attr, struct bpf_prog *prog) return err; } - err = bpf_hid_link_attach(hdev, &hid_link->link, hid_type); + err = bpf_hid_link_attach(hdev, &hid_link->link, hid_type, attr->link_create.flags); if (err) { bpf_link_cleanup(&link_primer); return err; -- 2.35.1