From nobody Thu Apr 2 02:40:41 2026 Received: from mail-pg1-f175.google.com (mail-pg1-f175.google.com [209.85.215.175]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 379D830EF75 for ; Mon, 30 Mar 2026 11:00:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774868458; cv=none; b=ROa9PSkPF8CFWnwP17OesUXdJx8ySluRseF1MCg4M1wHbzMERWMtHrrBJ/OX1mihrMDt4imWYAvjoKjSdJU18aonZOusfF9w36xYAPhG0OHqiIimQrmpDG/Z+DVyxKGOPuhNdchwj+rKFAi2edP9cyAvotKXNPL0+QWylQ4+JL4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774868458; c=relaxed/simple; bh=BeYgyaBVMNH2YkkmIL4dka2nySItV+VavSBb7RGud1Q=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=G+Td1m1xxu+kleoox8oXxB8HHq/63TohgNnNRKdIcPPy6vRrsRE4QEkS2sY4VZVj1mjujg1pj8FrPak3ENbXMJSB2zZOcE4JONxp1R+bbKTg+DmNHhEG2d86E8VJhEYVQysMy2NTy/6crhj87Sgk6C83iXAYxrR46EfN51bxo5A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dI/lEc2/; arc=none smtp.client-ip=209.85.215.175 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dI/lEc2/" Received: by mail-pg1-f175.google.com with SMTP id 41be03b00d2f7-c06cb8004e8so1650517a12.0 for ; Mon, 30 Mar 2026 04:00:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774868455; x=1775473255; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tiAaielosONeq8lfjBldJ8eg8rZvO6xA8Ahk7S8YwtM=; b=dI/lEc2/kBwloVOfEUgc+XnVL7MXykZJ9WuINJQlaDeqfE3dRYI9j9g/jPK61CVyxQ P7C/c3hsBvSr9OKO/ZIIUyo84tBkH8kHTGOsw5Goil7n1EV7WjhuM2MNyuw0dYUq7JtX QOCM0apREQ14H+mrSlUFZ1txa6SwLzIc2Fkfh8o9KXqoH6FCJkNTgOoi/ui5/Ge/5g0w 3F+wBJBGt8At4T4oEE1/IltU6usjM+6eqA2nPzEA2DLYyg76TCBe0yDv9ped6BfgD0/a Hc1QBYZZqi31JLPw6aU/3uO0x8OVSNwMvMDEWNbWPQD25T+b2C7Oo+NE4OjG2I732jxh FcWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774868455; x=1775473255; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=tiAaielosONeq8lfjBldJ8eg8rZvO6xA8Ahk7S8YwtM=; b=O8Xk6dguuCOeO6AsMefaglbPblKHXAvAGKYnYRJLDOJ48epRDJwgUSzi6gMSQvIksn G6r6nWgIb35/oQFDegqWxYImcBcfYK2kREwXWMU8jDSrUnKr1/C9rcaKE27xFOqU64wb f4zPOmz6BcGQiYal5Cupq2o4F9RWxLMn9iTG+50soScZjIrOLMC+MDI53okWbmY0CjtN LuzyO4yWTt4M2OL4VmOrNYUuyDGmdE4yX5TqI5wCvzUaBPgxFP9nXB+Z9bHcKdecgslk E33SoHaLCdhroRFxa4bVeLCEXhNNcK2C14HACxCC+s5XsfPdMkGWglJPBV9ln0d7stAF 7lXA== X-Forwarded-Encrypted: i=1; AJvYcCUDLNC2vWSU52FUzSBZ6YhqTDVCGho0noDh3dILOVqEN0IgbPNtmWGxgb7sIq9nd9fjdVngS4rbtwR4wco=@vger.kernel.org X-Gm-Message-State: AOJu0YwfekXppJNDhOi753XzBWQ6KxBiBPjuWtaCn6xrGKmxyiSNNPXY zJrtxNxyFt2+OBzyiYOJRaGUsmvPg/jzA+XYYAE84a45E4dw2qk9+wwN X-Gm-Gg: ATEYQzyq8F8/U1m/aSKlVyR8IaRlMdje9pjYNkPS/1eCOKFjihhRqdq2ImAy5m3ex1X TQfiNpHEAYeUeKmAJGyMlWWgjcPvvqo6j7MDxx8AaMBapFxFxMWdLUCNmqz8ljpslv7cyEVKJRC HaRNqgZleHVaqLBC35+8/gUMGHxpkgJh1xfH0DzB1HdK8XF1QWw1VYwVsrUvPwTZtEWvRPHtpx9 kKMa+kcgeb5XGRufyJqvqlew60JELY9dWw242W1C2eNW5LJ4MOf3tmsY3xhwO6w1rQmHi+A79i9 xEIbBRcpidN6zhS02hmO/rackhJ52JRUSITXAWeYJeRd5cJWbhiKORxrXNSl9DZyYXcYLpykgRt 8CbTm1yqzZ7SZHTm6hY5bBCX29aB4Ac/sO1v3nej+0Kj71sDFUbyxjVj/fNtj45/64uMB10UkuV nMN7bvEozILMwzKCTA/OfhkdS+XQVxUtYN/+vWThAZU0ZHzoKfdhnG0FDJTsQ8yohYcCa0Zlyd3 w== X-Received: by 2002:a05:6a20:3d06:b0:398:aea8:a9c0 with SMTP id adf61e73a8af0-39c8780d9aamr12405100637.19.1774868455294; Mon, 30 Mar 2026 04:00:55 -0700 (PDT) Received: from eris-fedora.iitr.ac.in ([103.37.201.189]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76917d843esm6806615a12.29.2026.03.30.04.00.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 04:00:54 -0700 (PDT) From: Varun R Mallya To: andrii@kernel.org, alan.maguire@oracle.com, yonghong.song@linux.dev, song@kernel.org, bpf@vger.kernel.org Cc: ast@kernel.org, daniel@iogearbox.net, memxor@gmail.com, eddyz87@gmail.com, martin.lau@linux.dev, jolsa@kernel.org, menglong8.dong@gmail.com, puranjay@kernel.org, bjorn@kernel.org, leon.hwang@linux.dev, varunrmallya@gmail.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH bpf-next v2 1/3] libbpf: Auto-upgrade uprobes to multi-uprobes when supported Date: Mon, 30 Mar 2026 16:30:17 +0530 Message-ID: <20260330110019.549079-2-varunrmallya@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260330110019.549079-1-varunrmallya@gmail.com> References: <20260330110019.549079-1-varunrmallya@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch modifies libbpf to automatically "upgrade" standard SEC("uprobe") and SEC("uretprobe") programs to use the multi-uprobe infrastructure (BPF_TRACE_UPROBE_MULTI) at load time if the kernel supports it, making them compatible with BPF tokens. To maintain backward compatibility and handle rare cases where singular uprobes are required, new SEC("uprobe.single") and SEC("uretprobe.single") section types are introduced. These force libbpf to use the legacy perf_event_open() attachment path. tools/testing/selftests/bpf/progs/test_fill_link_info.c has been modified to use SEC("uprobe.single") as it asserts the program type to be `BPF_LINK_TYPE_PERF_EVENT` and checks properties related to uprobes that use perf. Signed-off-by: Varun R Mallya --- tools/lib/bpf/libbpf.c | 53 +++++++++++++++++-- .../selftests/bpf/progs/test_fill_link_info.c | 2 +- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 1eaa7527d4da..bd7b6f486430 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -8248,6 +8248,23 @@ static int bpf_object_prepare_progs(struct bpf_objec= t *obj) =20 for (i =3D 0; i < obj->nr_programs; i++) { prog =3D &obj->programs[i]; + + if (kernel_supports(obj, FEAT_UPROBE_MULTI_LINK)) { + const char *sec_name =3D prog->sec_name; + /* Here, we filter out for u[ret]probe or "u[ret]probe/" + * but we leave out anything with an '@' + * in it as uprobe_multi does not support versioned + * symbols yet, so we don't upgrade. + */ + if (((strncmp(sec_name, "uprobe", 6) =3D=3D 0 && + (sec_name[6] =3D=3D '/' || sec_name[6] =3D=3D '\0')) || + (strncmp(sec_name, "uretprobe", 9) =3D=3D 0 && + (sec_name[9] =3D=3D '/' || sec_name[9] =3D=3D '\0'))) && + !strchr(sec_name, '@')) { + prog->expected_attach_type =3D BPF_TRACE_UPROBE_MULTI; + } + } + err =3D bpf_object__sanitize_prog(obj, prog); if (err) return err; @@ -9909,9 +9926,11 @@ static const struct bpf_sec_def section_defs[] =3D { SEC_DEF("kprobe+", KPROBE, 0, SEC_NONE, attach_kprobe), SEC_DEF("uprobe+", KPROBE, 0, SEC_NONE, attach_uprobe), SEC_DEF("uprobe.s+", KPROBE, 0, SEC_SLEEPABLE, attach_uprobe), + SEC_DEF("uprobe.single+", KPROBE, 0, SEC_NONE, attach_uprobe), SEC_DEF("kretprobe+", KPROBE, 0, SEC_NONE, attach_kprobe), SEC_DEF("uretprobe+", KPROBE, 0, SEC_NONE, attach_uprobe), SEC_DEF("uretprobe.s+", KPROBE, 0, SEC_SLEEPABLE, attach_uprobe), + SEC_DEF("uretprobe.single+", KPROBE, 0, SEC_NONE, attach_uprobe), SEC_DEF("kprobe.multi+", KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, attach= _kprobe_multi), SEC_DEF("kretprobe.multi+", KPROBE, BPF_TRACE_KPROBE_MULTI, SEC_NONE, att= ach_kprobe_multi), SEC_DEF("kprobe.session+", KPROBE, BPF_TRACE_KPROBE_SESSION, SEC_NONE, at= tach_kprobe_session), @@ -12737,6 +12756,32 @@ bpf_program__attach_uprobe_opts(const struct bpf_p= rogram *prog, pid_t pid, func_offset +=3D sym_off; } =20 + /* This provides backwards compatibility to programs using uprobe, but + * have been auto-upgraded to multi uprobe. + */ + if (prog->expected_attach_type =3D=3D BPF_TRACE_UPROBE_MULTI) { + LIBBPF_OPTS(bpf_uprobe_multi_opts, multi_opts); + unsigned long offsets[1] =3D {func_offset}; + __u64 bpf_cookie; + + multi_opts.retprobe =3D OPTS_GET(opts, retprobe, false); + if (offsets[0] || func_name) { + multi_opts.offsets =3D offsets; + multi_opts.cnt =3D 1; + } + if (ref_ctr_off) { + multi_opts.ref_ctr_offsets =3D &ref_ctr_off; + multi_opts.cnt =3D 1; + } + bpf_cookie =3D OPTS_GET(opts, bpf_cookie, 0); + if (bpf_cookie) { + multi_opts.cookies =3D &bpf_cookie; + multi_opts.cnt =3D 1; + } + + return bpf_program__attach_uprobe_multi(prog, pid, binary_path, + NULL, &multi_opts); + } legacy =3D determine_uprobe_perf_type() < 0; switch (attach_mode) { case PROBE_ATTACH_MODE_LEGACY: @@ -12830,6 +12875,7 @@ static int attach_uprobe(const struct bpf_program *= prog, long cookie, struct bpf char *probe_type =3D NULL, *binary_path =3D NULL, *func_name =3D NULL, *f= unc_off; int n, c, ret =3D -EINVAL; long offset =3D 0; + bool is_retprobe; =20 *link =3D NULL; =20 @@ -12856,13 +12902,14 @@ static int attach_uprobe(const struct bpf_program= *prog, long cookie, struct bpf else offset =3D 0; } - opts.retprobe =3D strcmp(probe_type, "uretprobe") =3D=3D 0 || - strcmp(probe_type, "uretprobe.s") =3D=3D 0; - if (opts.retprobe && offset !=3D 0) { + is_retprobe =3D strcmp(probe_type, "uretprobe") =3D=3D 0 || + strcmp(probe_type, "uretprobe.s") =3D=3D 0; + if (is_retprobe && offset !=3D 0) { pr_warn("prog '%s': uretprobes do not support offset specification\n", prog->name); break; } + opts.retprobe =3D is_retprobe; opts.func_name =3D func_name; *link =3D bpf_program__attach_uprobe_opts(prog, -1, binary_path, offset,= &opts); ret =3D libbpf_get_error(*link); diff --git a/tools/testing/selftests/bpf/progs/test_fill_link_info.c b/tool= s/testing/selftests/bpf/progs/test_fill_link_info.c index fac33a14f200..8e47a818462f 100644 --- a/tools/testing/selftests/bpf/progs/test_fill_link_info.c +++ b/tools/testing/selftests/bpf/progs/test_fill_link_info.c @@ -28,7 +28,7 @@ int BPF_PROG(kprobe_run) return 0; } =20 -SEC("uprobe") +SEC("uprobe.single") int BPF_PROG(uprobe_run) { return 0; --=20 2.52.0 From nobody Thu Apr 2 02:40:41 2026 Received: from mail-pg1-f178.google.com (mail-pg1-f178.google.com [209.85.215.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13E033815E9 for ; Mon, 30 Mar 2026 11:01:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774868471; cv=none; b=RFciCZhT5gQnsB1LjIQNe3qJpUaoaReGc8AOW1cbzj+YmYRz1BAk3wQDo3runqY8FIxzxIjGYevtJfUqvFItaWZ9jFHhkRj2p2ykzH9HUCplYaZ6Bq91cP0+ssYUlYJRLMsG8Z0VP2SwfL0JFUh2vH9Yhh48kQejE/Y+gUwmkZw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774868471; c=relaxed/simple; bh=ykB6GqSoBDVF8sQ3aMY5L/RsBwNhVVVqpjKX0IM3w4A=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kPLJbhfMTecUIAXfAS2SkGOLlLPrNLRx9/5JKc1Dsll42J6HzOgaMQwW2DToTropYbFZeVd+gfLiIaa/9bEDmuEmgY55TIAcNFy3zhsj8QB+MqzCuHxU1nTZ1HIp+xR9FCG8ER6PlZAXcFBqnDrjVg3E+pNDgHpCfMNz8SUKLxs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=cmDkcxLe; arc=none smtp.client-ip=209.85.215.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="cmDkcxLe" Received: by mail-pg1-f178.google.com with SMTP id 41be03b00d2f7-c7358a7a8d1so3005924a12.3 for ; Mon, 30 Mar 2026 04:01:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774868463; x=1775473263; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=NZsO2ED3NriQaWk6RZB1AOBG85387YAVdW0BG1uStGY=; b=cmDkcxLeZm+7kdfglxqXlANRCSG99/UAucFFMt7tCANxpHEa74+7unJFin1bxXdnEP kzyxDpyLkeI01D54cAsH5bcHL6BDzzsu2WjfYVI+/6Nz1xa3RzetTh3zxqUXmXz0f3QG h5yJTux28odn6L7P5lvHnr5KbwBCdOjCU/oRI904c6KqCvsHfT/cCT1klZprLYLsWp7Z 8DktjT7mMn9c2tRgNXjv79klKLb+P4JxPqCvkd9q4vIXIGvtVNywunY2bQZDnT3t3WnJ FQ1cUh1yClLq0ut70wq7OsapOAHldNNx1Y+2UaRTkExrflIQZSYPRrO48kXa1CvjsB9G gN1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774868463; x=1775473263; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=NZsO2ED3NriQaWk6RZB1AOBG85387YAVdW0BG1uStGY=; b=JCoi0F/hq7bSOVf3Vz7xGQofqFxXMqosdddvA8W5SiM93/KEyQysgUkTmhir/2jykv 4eOZ6nXkmZm9lHqCnNTppFWfDInL7JoZdNvoWtm5qAChNZGEmAEFR9GGV7MSp7Vbgosw iTHNws1oQ8DyZZZLJ4ugJ3586OZlMGbl1INr/1HRGp7diq4AWE+jxfeY+I1NI0rljjwC sa2AwAtwFkkUhgAjRmoOnf82q1LP6pq0B9hzmcvM6OS32FQylNL6sIWjooFMjfRfFV1V YSMjn2lDqmNX4bgcjK5FKQm6nWU42uw3F7lqX/ZKfUcmi/GcviWNEyVIWV5t6mNWUVB+ IRyg== X-Forwarded-Encrypted: i=1; AJvYcCVy/lbR3RFttG39+SIkZoNcEqbgbJgvrOAy/PSclxA/FvUurWyh4DXnJpPS0akRZNl011FuvpjQVTnwhZE=@vger.kernel.org X-Gm-Message-State: AOJu0YwytX8SqoCbd+lf2ikF5pWS6N6+x5P/VG2xWnJH61mCptg/91FP fZQ7oxGN9Jo+1+nb/Z9ADMYBAKGMdOa5TSC0TM5ACvqOILAcLeDFwBRo X-Gm-Gg: ATEYQzwNKb327SY8H1YxaWuOi/CUT9bbFRc+UPoN94J0B9IhM2/QxdMFagX65M47ccE TOyQ5767PIc0CqNFOJbpd9+7eewYIdI8mFDHSKGoRnnxe12FVZsxQ3mp6uq+ruA4cwiF79WMEjH fzXbR3kH9xzAoeIUWOroc1utMXHNhzxNOtiIAS2H6RNj1UVcDvO+Yt4Dw7nMvMSy1QTiNs+FLGe 92Z1Yyt9QTpnDkBTnJZI9Amvotunfa++hvuXK53XTqz3s8udz/c+i2A4E3g/HQfiNJIFE/07Obn SEt690kb+/dcMmsOqWZmjbchbL911nRnydYy9i+S0qhO9i8EymeEi1Jb01Q6MTr4PHpWXi6ZFpe gXt7oepNkFMCV+bSWZktPzOMWRPzOLv2MwbO0EZUsuBsNzqRcdU0KilCHAgRIm2nIhZ586JHqro lYDLAQWyA4/6O7HCyLqQ9bgHaSHurCUr27J/4XhvCAbR9XW+ifM/TEkAntDP/6JxNsfMLWfij7L Q== X-Received: by 2002:a05:6a20:a10d:b0:39b:c686:630c with SMTP id adf61e73a8af0-39c878bbaf7mr12969034637.22.1774868463171; Mon, 30 Mar 2026 04:01:03 -0700 (PDT) Received: from eris-fedora.iitr.ac.in ([103.37.201.189]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76917d843esm6806615a12.29.2026.03.30.04.00.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 04:01:02 -0700 (PDT) From: Varun R Mallya To: andrii@kernel.org, alan.maguire@oracle.com, yonghong.song@linux.dev, song@kernel.org, bpf@vger.kernel.org Cc: ast@kernel.org, daniel@iogearbox.net, memxor@gmail.com, eddyz87@gmail.com, martin.lau@linux.dev, jolsa@kernel.org, menglong8.dong@gmail.com, puranjay@kernel.org, bjorn@kernel.org, leon.hwang@linux.dev, varunrmallya@gmail.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH bpf-next v2 2/3] libbpf: Add FEAT_KPROBE_MULTI_LINK feature probe. Date: Mon, 30 Mar 2026 16:30:18 +0530 Message-ID: <20260330110019.549079-3-varunrmallya@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260330110019.549079-1-varunrmallya@gmail.com> References: <20260330110019.549079-1-varunrmallya@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add FEAT_KPROBE_MULTI_LINK, similar to UPROBE_MULTI_LINK by loading and creating a link for a small BPF program with BPF_TRACE_KPROBE_MULTI as the expected attach type, and then checking the success of the operation. Signed-off-by: Varun R Mallya --- tools/lib/bpf/features.c | 37 +++++++++++++++++++++++++++++++++ tools/lib/bpf/libbpf_internal.h | 2 ++ 2 files changed, 39 insertions(+) diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c index adcad221c601..13227c9ea69d 100644 --- a/tools/lib/bpf/features.c +++ b/tools/lib/bpf/features.c @@ -424,6 +424,40 @@ static int probe_uprobe_multi_link(int token_fd) return link_fd < 0 && err =3D=3D -EINVAL; } =20 +static int probe_kprobe_multi_link(int token_fd) +{ + LIBBPF_OPTS(bpf_prog_load_opts, load_opts, + .expected_attach_type =3D BPF_TRACE_KPROBE_MULTI, + .token_fd =3D token_fd, + .prog_flags =3D token_fd ? BPF_F_TOKEN_FD : 0, + ); + LIBBPF_OPTS(bpf_link_create_opts, link_opts); + struct bpf_insn insns[] =3D { + BPF_MOV64_IMM(BPF_REG_0, 0), + BPF_EXIT_INSN(), + }; + int prog_fd, link_fd, err; + const char *sym =3D "bpf_map_lookup_elem"; /* stable, always present */ + + prog_fd =3D bpf_prog_load(BPF_PROG_TYPE_KPROBE, NULL, "GPL", + insns, ARRAY_SIZE(insns), &load_opts); + if (prog_fd < 0) + return -errno; + + /* attaching to a valid symbol should succeed */ + link_opts.kprobe_multi.syms =3D &sym; + link_opts.kprobe_multi.cnt =3D 1; + link_fd =3D bpf_link_create(prog_fd, -1, BPF_TRACE_KPROBE_MULTI, &link_op= ts); + err =3D -errno; + if (link_fd >=3D 0) + close(link_fd); + close(prog_fd); + /* if kprobe_multi is supported, link creation either succeeds or + * fails with something other than -EINVAL due to permissions, + */ + return link_fd >=3D 0 || (err !=3D -EINVAL); +} + static int probe_kern_bpf_cookie(int token_fd) { struct bpf_insn insns[] =3D { @@ -658,6 +692,9 @@ static struct kern_feature_desc { [FEAT_UPROBE_MULTI_LINK] =3D { "BPF multi-uprobe link support", probe_uprobe_multi_link, }, + [FEAT_KPROBE_MULTI_LINK] =3D { + "BPF multi-kprobe link support", probe_kprobe_multi_link, + }, [FEAT_ARG_CTX_TAG] =3D { "kernel-side __arg_ctx tag", probe_kern_arg_ctx_tag, }, diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_interna= l.h index 4bcb6ca69bb1..633106a687c7 100644 --- a/tools/lib/bpf/libbpf_internal.h +++ b/tools/lib/bpf/libbpf_internal.h @@ -388,6 +388,8 @@ enum kern_feature_id { FEAT_SYSCALL_WRAPPER, /* BPF multi-uprobe link support */ FEAT_UPROBE_MULTI_LINK, + /* BPF multi-kprobe link support */ + FEAT_KPROBE_MULTI_LINK, /* Kernel supports arg:ctx tag (__arg_ctx) for global subprogs natively */ FEAT_ARG_CTX_TAG, /* Kernel supports '?' at the front of datasec names */ --=20 2.52.0 From nobody Thu Apr 2 02:40:41 2026 Received: from mail-pg1-f172.google.com (mail-pg1-f172.google.com [209.85.215.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7654D3C5529 for ; Mon, 30 Mar 2026 11:01:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774868475; cv=none; b=SH8AiJjYlzQORy0erxyxyMK9W5ea1hURCO46sA40hSPzfb54i5b7Oo0aKJZDbljjxleGDLeonMd5RXLz0EfFOFQyou2OjbngZ8TfURCxgByQ0b6HXtY57ZMIUK9UKVES6UbHWEprXlH/FGkbnYpe2LNGLis5aHWK/q7+HTsXnA8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774868475; c=relaxed/simple; bh=lqJpTC+I56xQqupGTb+WFFTo6NyZjyNGSBXBDplJRrE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PF+YZEucED/LqwJERvZlPtrR/272da8LGDSb4yXh/qvJHbBytGW04MTRdGVgT81C998JY95PLuVKS9GAdFtIQ77dxh0z5Iy7CbJp6LTu4cGQZGp3Tol6Zp0cfnQIahuD0r4UB4wEwtW87uMfvjzpXjJo9d6WsG3jd9mwMzSumdI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=PF6dYOCa; arc=none smtp.client-ip=209.85.215.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="PF6dYOCa" Received: by mail-pg1-f172.google.com with SMTP id 41be03b00d2f7-c742723c863so2809451a12.0 for ; Mon, 30 Mar 2026 04:01:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1774868472; x=1775473272; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wDv4iYg7IyIBFaVAyL6MvTJiVehOKhgwcTE2u0eTsXI=; b=PF6dYOCa8H0NwpnDB0tFs112nkF7uNcu+Y7pC/QyytKpkFNXGp43irzbmeTfFYBNCI ihwpIbbKRSpV8HXVJF3dI1O8GIdz5wY3pjKKY2a7+PTZBp7q5kgKl5yUpt5p/Q/FcDXo vzs1Ox874YbglgWL3AQ2NOLBW06/xszr+8SuhqkVEaMo5rWicp9k0VBzzEE/NKPjBQwz psXmR4X3Gtms59t9r0rWhf6rLuN6R3JkGoygmE0E0F05+aUsa5CiKMz7h52Nx+twc89E vGS8AK91o3W01dXmYzCTCDPixRMV1jM2NoaHqy8OmY6JCkyKkflyrcHXty3RdzVE4r9K 0UBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774868472; x=1775473272; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=wDv4iYg7IyIBFaVAyL6MvTJiVehOKhgwcTE2u0eTsXI=; b=L2EQK/ovThRABAMGFvMe6vUY2YsZTfhowWQwetL89biXswJ4GhyLfiM+aDGA+POW0k KByOBiOnE3OUueYs796ayE+ohsNkU0/QSlTMx1P22eY+jadmfzqxI5XtLifHe7gLNtCL YetPL+irSQ8+DuumM87jqFaLk/YJ8pNTwGmWMlKHDPeIVAf7nLw2QMkw6Jao3NCyqVLx lMiVJ680xv3m0/zPF8Um0k09j3Dh86J9s1KG+FgZxOCDzVhcB80nHVeqEY7MypR9dJuT nMxmzryd1ISYkirmlo/vn9Pp65r21p/HZxY/sugkYFGDtXuHBHFczWSHob2c3lpwJwYN 7cPQ== X-Forwarded-Encrypted: i=1; AJvYcCUi6JEh9nFHWpsYJtyU761oBsq3iDW3eyE7cRUTCHKxLLX6iM2dI1pn4n0e/FoFSuECxezXLnGnW1rcu78=@vger.kernel.org X-Gm-Message-State: AOJu0Yy+xMoA3ASMM50iRlB3LaGEUEg5A45pFTAE/SytE/pjdCJ1W5UI /HGZrcaA+wwqxXdx1QAqi/RBv4OQ75Ohl7wLAr6QYf+W1OxkTrvkiwyn X-Gm-Gg: ATEYQzzeCc3RjKq4M8lIDIqYteXiJ73h+YSHOUoE6JoN8aYkguaSQtsyRsQ5OuQBscb jon9ayD90Aj7kWBgGNJ1ebdFZlVDB7aYAe8om+WJFsdE+jmPDihUZaTKUzMxTn3ojUMa3tO2EMK XDqiEyRDu8Jufeowgbg8tq5UuCJK7AgCTbqhnpbVgbdyNdJLePv1ObruJoaiZOye7qSklAVDx6v ntv1KX4RNfGYxb4Qs1Fu+EqPqd3a60Oa5S3e40GuoA9CxF8NTCuQZBGYb9m6dLXpoL7EQZevfFw 1BMyITFREm0OgmqrKO8+ohWLssxf/q9N5iQKWOrEOalN1GmLVG3ATSvZ/b53NFRDeQFjdb0Y+Ti 1adEh1kRDRelndFzR53ZLMOeCStTiHgyOshrPNluEfzt2GjRH4jA01TFVMR2WuuOMl4OShJCZcE BPEmxwCi2w+zuaGPJRPDoNGSH765XQ2CVyZfFpIeHEAW0Zu2Y/kw8fuoWVwOLPnDGsVj5lu1pdx nwqmtT7UN9A X-Received: by 2002:a05:6a20:3ca3:b0:398:a33a:71c9 with SMTP id adf61e73a8af0-39c87ac323amr11533305637.43.1774868471401; Mon, 30 Mar 2026 04:01:11 -0700 (PDT) Received: from eris-fedora.iitr.ac.in ([103.37.201.189]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-c76917d843esm6806615a12.29.2026.03.30.04.01.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 30 Mar 2026 04:01:11 -0700 (PDT) From: Varun R Mallya To: andrii@kernel.org, alan.maguire@oracle.com, yonghong.song@linux.dev, song@kernel.org, bpf@vger.kernel.org Cc: ast@kernel.org, daniel@iogearbox.net, memxor@gmail.com, eddyz87@gmail.com, martin.lau@linux.dev, jolsa@kernel.org, menglong8.dong@gmail.com, puranjay@kernel.org, bjorn@kernel.org, leon.hwang@linux.dev, varunrmallya@gmail.com, linux-kernel@vger.kernel.org Subject: [RFC PATCH bpf-next v2 3/3] libbpf: Auto-upgrade kprobes to multi-kprobes when supported Date: Mon, 30 Mar 2026 16:30:19 +0530 Message-ID: <20260330110019.549079-4-varunrmallya@gmail.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260330110019.549079-1-varunrmallya@gmail.com> References: <20260330110019.549079-1-varunrmallya@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable This patch modifies libbpf to automatically upgrade standard SEC("kprobe") and SEC("kretprobe") programs to use the multi-kprobe infrastructure (BPF_TRACE_KPROBE_MULTI) at load time if the kernel supports it, making them compatible with BPF tokens. To maintain backward compatibility and handle cases where singular kprobes are required, new SEC("kprobe.single") and SEC("kretprobe.single") section types are introduced. These force libbpf to use the legacy perf_event_open() attachment path. The following explain the reasoning for changing selftests: - test_fill_link_info.c kprobe=E2=86=92kprobe.single: this test calls bpf_link_get_info_by_fd and asserts BPF_LINK_TYPE_PERF_EVENT and it explicitly needs the perf_event attachment path, which breaks after auto-upgrade to multi. - test_attach_probe_manual.c kprobe=E2=86=92kprobe.single, kretprobe=E2=86=92kretprobe.single: this test exercises all four explicit attachment modes (default, legacy, perf, link) and PROBE_ATTACH_MODE_LINK creates a perf_event BPF link which the kernel rejects for a prog loaded with expected_attach_type =3D BPF_TRACE_KPROBE_MULTI. - missed_kprobe.c kprobe->kprobe.single: The link is explicitly checked in the tests due to which it fails if we do not specifically kprobe.single this. - get_func_ip_test.c ?kprobe=E2=86=92?kprobe.single: the ? is stripped from sec_name by libbpf at init time so the prog still gets auto-upgraded. It is then manually attached with a non-zero body offset, which kprobe_multi doesn't support. Signed-off-by: Varun R Mallya --- tools/lib/bpf/libbpf.c | 61 +++++++++++++++++-- .../selftests/bpf/progs/get_func_ip_test.c | 2 +- .../selftests/bpf/progs/missed_kprobe.c | 4 +- .../bpf/progs/test_attach_probe_manual.c | 4 +- .../selftests/bpf/progs/test_fill_link_info.c | 2 +- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index bd7b6f486430..9d0a36f8279a 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -8265,6 +8265,24 @@ static int bpf_object_prepare_progs(struct bpf_objec= t *obj) } } =20 + if (kernel_supports(obj, FEAT_KPROBE_MULTI_LINK)) { + const char *sec_name =3D prog->sec_name; + /* Here, we filter out for k[ret]probe or "k[ret]probe/" + * but we leave out anything with an '@' + * in it as kprobe_multi does not support versioned + * symbols, so we don't upgrade. Also for '+' as we do not + * support offsets. + */ + if (((strncmp(sec_name, "kprobe", 6) =3D=3D 0 && + (sec_name[6] =3D=3D '/' || sec_name[6] =3D=3D '\0')) || + (strncmp(sec_name, "kretprobe", 9) =3D=3D 0 && + (sec_name[9] =3D=3D '/' || sec_name[9] =3D=3D '\0'))) && + !strchr(sec_name, '@') && + !strchr(sec_name, '+') && + !(prog->prog_flags & BPF_F_SLEEPABLE)) + prog->expected_attach_type =3D BPF_TRACE_KPROBE_MULTI; + } + err =3D bpf_object__sanitize_prog(obj, prog); if (err) return err; @@ -9924,10 +9942,12 @@ static const struct bpf_sec_def section_defs[] =3D { SEC_DEF("sk_reuseport/migrate", SK_REUSEPORT, BPF_SK_REUSEPORT_SELECT_OR_= MIGRATE, SEC_ATTACHABLE), SEC_DEF("sk_reuseport", SK_REUSEPORT, BPF_SK_REUSEPORT_SELECT, SEC_ATTAC= HABLE), SEC_DEF("kprobe+", KPROBE, 0, SEC_NONE, attach_kprobe), + SEC_DEF("kprobe.single+", KPROBE, 0, SEC_NONE, attach_kprobe), SEC_DEF("uprobe+", KPROBE, 0, SEC_NONE, attach_uprobe), SEC_DEF("uprobe.s+", KPROBE, 0, SEC_SLEEPABLE, attach_uprobe), SEC_DEF("uprobe.single+", KPROBE, 0, SEC_NONE, attach_uprobe), SEC_DEF("kretprobe+", KPROBE, 0, SEC_NONE, attach_kprobe), + SEC_DEF("kretprobe.single+", KPROBE, 0, SEC_NONE, attach_kprobe), SEC_DEF("uretprobe+", KPROBE, 0, SEC_NONE, attach_uprobe), SEC_DEF("uretprobe.s+", KPROBE, 0, SEC_SLEEPABLE, attach_uprobe), SEC_DEF("uretprobe.single+", KPROBE, 0, SEC_NONE, attach_uprobe), @@ -11769,6 +11789,25 @@ bpf_program__attach_kprobe_opts(const struct bpf_p= rogram *prog, offset =3D OPTS_GET(opts, offset, 0); pe_opts.bpf_cookie =3D OPTS_GET(opts, bpf_cookie, 0); =20 + /* This provides backwards compatibility to programs using kprobe, but + * have been auto-upgraded to multi kprobe. + */ + if (prog->expected_attach_type =3D=3D BPF_TRACE_KPROBE_MULTI && + offset =3D=3D 0 && attach_mode =3D=3D PROBE_ATTACH_MODE_DEFAULT) { + LIBBPF_OPTS(bpf_kprobe_multi_opts, multi_opts); + const char *syms[1] =3D { func_name }; + __u64 bpf_cookie; + + multi_opts.retprobe =3D OPTS_GET(opts, retprobe, false); + multi_opts.syms =3D syms; + multi_opts.cnt =3D 1; + bpf_cookie =3D OPTS_GET(opts, bpf_cookie, 0); + if (bpf_cookie) + multi_opts.cookies =3D &bpf_cookie; + + return bpf_program__attach_kprobe_multi_opts(prog, NULL, &multi_opts); + } + legacy =3D determine_kprobe_perf_type() < 0; switch (attach_mode) { case PROBE_ATTACH_MODE_LEGACY: @@ -12223,14 +12262,24 @@ static int attach_kprobe(const struct bpf_program= *prog, long cookie, struct bpf *link =3D NULL; =20 /* no auto-attach for SEC("kprobe") and SEC("kretprobe") */ - if (strcmp(prog->sec_name, "kprobe") =3D=3D 0 || strcmp(prog->sec_name, "= kretprobe") =3D=3D 0) + if (strcmp(prog->sec_name, "kprobe") =3D=3D 0 || + strcmp(prog->sec_name, "kretprobe") =3D=3D 0 || + strcmp(prog->sec_name, "kprobe.single") =3D=3D 0 || + strcmp(prog->sec_name, "kretprobe.single") =3D=3D 0) return 0; =20 - opts.retprobe =3D str_has_pfx(prog->sec_name, "kretprobe/"); - if (opts.retprobe) - func_name =3D prog->sec_name + sizeof("kretprobe/") - 1; - else - func_name =3D prog->sec_name + sizeof("kprobe/") - 1; + if (str_has_pfx(prog->sec_name, "kretprobe/") || + str_has_pfx(prog->sec_name, "kretprobe.single/")) { + opts.retprobe =3D true; + func_name =3D str_has_pfx(prog->sec_name, "kretprobe/") + ? prog->sec_name + sizeof("kretprobe/") - 1 + : prog->sec_name + sizeof("kretprobe.single/") - 1; + } else { + opts.retprobe =3D false; + func_name =3D str_has_pfx(prog->sec_name, "kprobe.single/") + ? prog->sec_name + sizeof("kprobe.single/") - 1 + : prog->sec_name + sizeof("kprobe/") - 1; + } =20 n =3D sscanf(func_name, "%m[a-zA-Z0-9_.]+%li", &func, &offset); if (n < 1) { diff --git a/tools/testing/selftests/bpf/progs/get_func_ip_test.c b/tools/t= esting/selftests/bpf/progs/get_func_ip_test.c index 2011cacdeb18..a039760b8516 100644 --- a/tools/testing/selftests/bpf/progs/get_func_ip_test.c +++ b/tools/testing/selftests/bpf/progs/get_func_ip_test.c @@ -73,7 +73,7 @@ int BPF_PROG(test5, int a, int *b, int ret) } =20 __u64 test6_result =3D 0; -SEC("?kprobe") +SEC("?kprobe.single") int test6(struct pt_regs *ctx) { __u64 addr =3D bpf_get_func_ip(ctx); diff --git a/tools/testing/selftests/bpf/progs/missed_kprobe.c b/tools/test= ing/selftests/bpf/progs/missed_kprobe.c index 51a4fe64c917..5f405888ed0b 100644 --- a/tools/testing/selftests/bpf/progs/missed_kprobe.c +++ b/tools/testing/selftests/bpf/progs/missed_kprobe.c @@ -16,14 +16,14 @@ int BPF_PROG(trigger) return 0; } =20 -SEC("kprobe/bpf_fentry_test1") +SEC("kprobe.single/bpf_fentry_test1") int test1(struct pt_regs *ctx) { bpf_kfunc_common_test(); return 0; } =20 -SEC("kprobe/bpf_kfunc_common_test") +SEC("kprobe.single/bpf_kfunc_common_test") int test2(struct pt_regs *ctx) { return 0; diff --git a/tools/testing/selftests/bpf/progs/test_attach_probe_manual.c b= /tools/testing/selftests/bpf/progs/test_attach_probe_manual.c index 7f08bce94596..eb0fa3b39c5f 100644 --- a/tools/testing/selftests/bpf/progs/test_attach_probe_manual.c +++ b/tools/testing/selftests/bpf/progs/test_attach_probe_manual.c @@ -14,14 +14,14 @@ int uretprobe_res =3D 0; int uprobe_byname_res =3D 0; void *user_ptr =3D 0; =20 -SEC("kprobe") +SEC("kprobe.single") int handle_kprobe(struct pt_regs *ctx) { kprobe_res =3D 1; return 0; } =20 -SEC("kretprobe") +SEC("kretprobe.single") int handle_kretprobe(struct pt_regs *ctx) { kretprobe_res =3D 2; diff --git a/tools/testing/selftests/bpf/progs/test_fill_link_info.c b/tool= s/testing/selftests/bpf/progs/test_fill_link_info.c index 8e47a818462f..bc6cfed71fb8 100644 --- a/tools/testing/selftests/bpf/progs/test_fill_link_info.c +++ b/tools/testing/selftests/bpf/progs/test_fill_link_info.c @@ -22,7 +22,7 @@ int unused(void) CONFIG_PPC64 ? 0 : 1; } =20 -SEC("kprobe") +SEC("kprobe.single") int BPF_PROG(kprobe_run) { return 0; --=20 2.52.0