[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20251031075908.1472249-4-jianyungao89@gmail.com>
Date: Fri, 31 Oct 2025 15:59:05 +0800
From: Jianyun Gao <jianyungao89@...il.com>
To: linux-kernel@...r.kernel.org
Cc: Jianyun Gao <jianyungao89@...il.com>,
	Alexei Starovoitov <ast@...nel.org>,
	Daniel Borkmann <daniel@...earbox.net>,
	Andrii Nakryiko <andrii@...nel.org>,
	Martin KaFai Lau <martin.lau@...ux.dev>,
	Eduard Zingerman <eddyz87@...il.com>,
	Song Liu <song@...nel.org>,
	Yonghong Song <yonghong.song@...ux.dev>,
	John Fastabend <john.fastabend@...il.com>,
	KP Singh <kpsingh@...nel.org>,
	Stanislav Fomichev <sdf@...ichev.me>,
	Hao Luo <haoluo@...gle.com>,
	Jiri Olsa <jolsa@...nel.org>,
	"David S. Miller" <davem@...emloft.net>,
	Jakub Kicinski <kuba@...nel.org>,
	Jesper Dangaard Brouer <hawk@...nel.org>,
	bpf@...r.kernel.org (open list:BPF [GENERAL] (Safe Dynamic Programs and Tools)),
	netdev@...r.kernel.org (open list:XDP (eXpress Data Path):Keyword:(?:\b|_)xdp(?:\b|_))
Subject: [PATCH v2 3/5] libbpf: Add doxygen documentation for bpf_link_* APIs in bpf.h
Add doxygen comment blocks for all public bpf_link_* APIs in
tools/lib/bpf/bpf.h. These doc comments are for:
-bpf_link_create()
-bpf_link_detach()
-bpf_link_update()
-bpf_link_get_next_id()
-bpf_link_get_fd_by_id()
-bpf_link_get_fd_by_id_opts()
Signed-off-by: Jianyun Gao <jianyungao89@...il.com>
---
v1->v2:
 - Fixed the non-ASCII characters in this patch.
The v1 is here:
https://lore.kernel.org/lkml/20251031032627.1414462-4-jianyungao89@gmail.com/
 tools/lib/bpf/bpf.h | 482 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 479 insertions(+), 3 deletions(-)
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index cd96d7afed6b..9040fc891b81 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -1208,11 +1208,195 @@ struct bpf_link_create_opts {
 	size_t :0;
 };
 #define bpf_link_create_opts__last_field uprobe_multi.pid
-
+/**
+ * @brief Create a persistent BPF link that attaches a loaded BPF program to a
+ *        kernel hook or target object.
+ *
+ * bpf_link_create() wraps the BPF_LINK_CREATE syscall command and establishes
+ * a first-class in-kernel "link" object representing the attachment of
+ * @p prog_fd to @p target_fd (or to a kernel entity implied by @p attach_type).
+ * The returned FD (>= 0) owns the lifetime of that attachment: closing it
+ * cleanly detaches the program without requiring a separate detach syscall.
+ *
+ * Compared to legacy bpf_prog_attach()/bpf_raw_tracepoint_open(), link-based
+ * attachment:
+ *   - Provides explicit lifetime control (close(link_fd) == detach).
+ *   - Enables richer introspection via bpf_link_get_info_by_fd().
+ *   - Avoids ambiguous detach semantics and races inherent in "implicit detach
+ *     on last program FD close" patterns.
+ *
+ * Typical usage:
+ *   struct bpf_link_create_opts opts = {
+ *       .sz = sizeof(opts),
+ *       .flags = 0,
+ *   };
+ *   int link_fd = bpf_link_create(prog_fd, target_fd, BPF_TRACE_FENTRY, &opts);
+ *   if (link_fd < 0) {
+ *       // handle error
+ *   }
+ *   // ... use link_fd; close(link_fd) to detach later.
+ *
+ * @param prog_fd
+ *        File descriptor of a previously loaded BPF program (from bpf_prog_load()
+ *        or libbpf higher-level loader). Must be valid and compatible with
+ *        @p attach_type.
+ *
+ * @param target_fd
+ *        File descriptor of the attach target, when required by @p attach_type
+ *        (e.g. a cgroup FD, perf event FD, network interface, or another BPF
+ *        object). For some attach types (e.g. certain tracing variants) this may
+ *        be -1 or ignored; passing an inappropriate FD yields -EINVAL.
+ *
+ * @param attach_type
+ *        Enumeration value (enum bpf_attach_type) describing the hook/context
+ *        at which the program should be executed (e.g. BPF_CGROUP_INET_INGRESS,
+ *        BPF_TRACE_FENTRY, BPF_PERF_EVENT, BPF_NETFILTER, etc.). The program's
+ *        bpf_prog_type and expected_attach_type must be compatible; otherwise
+ *        verification will fail or the syscall returns -EINVAL/-EOPNOTSUPP.
+ *
+ * @param opts
+ *        Optional pointer to a zero-initialized struct bpf_link_create_opts
+ *        extended options; may be NULL for defaults. Must set opts->sz to
+ *        sizeof(struct bpf_link_create_opts) when non-NULL.
+ *
+ *        Common fields:
+ *          - .flags: Link creation flags (most callers set 0; future kernels
+ *            may define bits for pinning behaviors, exclusivity, etc.).
+ *          - .target_btf_id: For BTF-enabled tracing/fentry/fexit/kprobe multi
+ *            scenarios, identifies a BTF entity (function/type) this link
+ *            targets.
+ *          - .iter_info / .iter_info_len: Provide iterator-specific metadata
+ *            for BPF iter programs.
+ *
+ *        Attach-type specific nested unions:
+ *          - .perf_event.bpf_cookie: User-defined cookie visible to program via
+ *            bpf_get_attach_cookie() for PERF_EVENT and some tracing types.
+ *          - .kprobe_multi: Batch (multi) kprobe attachment:
+ *                * flags: KPROBE_MULTI_* flags controlling semantics.
+ *                * cnt: Number of symbols/addresses.
+ *                * syms / addrs: Symbol names or raw addresses (one of them
+ *                  used depending on kernel capabilities).
+ *                * cookies: Optional per-probe cookies.
+ *          - .uprobe_multi: Batch uprobes:
+ *                * path: Target binary path.
+ *                * offsets / ref_ctr_offsets: Instruction/file offsets and
+ *                  optional reference counter offsets.
+ *                * pid: Target PID (0 for any or to let kernel decide).
+ *                * cookies: Per-uprobe cookies.
+ *          - .tracing.cookie: Generic tracing cookie for newer tracing types.
+ *          - .netfilter: Attaching to Netfilter with:
+ *                * pf (protocol family), hooknum, priority, flags.
+ *          - .tcx / .netkit / .cgroup: Relative attachment variants allowing
+ *            multi-attach ordering and revision consistency:
+ *                * relative_fd / relative_id: Anchor or neighbor link/program.
+ *                * expected_revision: Revision check to avoid races (fail with
+ *                  -ESTALE if mismatch).
+ *
+ *        Zero any fields you do not explicitly use for forward compatibility.
+ *
+ * @return
+ *   >= 0 : Link file descriptor (attachment active).
+ *   < 0  : Negative error code (attachment failed; program not attached).
+ *
+ * Error Handling (negative libbpf-style codes; errno also set):
+ *   - -EINVAL: Invalid prog_fd/target_fd/attach_type combination, malformed
+ *              opts, bad sizes, unsupported flags, or missing required union
+ *              fields.
+ *   - -EOPNOTSUPP / -ENOTSUP: Attach type or creation mode unsupported by
+ *              running kernel.
+ *   - -EPERM / -EACCES: Insufficient privileges (CAP_BPF/CAP_SYS_ADMIN) or
+ *              blocked by LSM/lockdown.
+ *   - -ENOENT: Target object no longer exists (race) or unresolved symbol for
+ *              kprobe/uprobes multi-attach.
+ *   - -EBADF: Invalid file descriptor(s).
+ *   - -ENOMEM: Kernel memory/resource exhaustion.
+ *   - -ESTALE: Revision mismatch when using expected_revision (atomicity guard).
+ *   - Other negative codes: Propagated from underlying bpf() syscall failures.
+ *
+ * Lifetime & Ownership:
+ *   - Success returns a link FD. Caller must close() it to detach.
+ *   - Closing the original program FD does NOT detach the link; only closing
+ *     the link FD (or explicit bpf_link_detach()) does.
+ *   - Link FDs can be pinned to bpffs via bpf_obj_pin() for persistence.
+ *
+ * Concurrency & Races:
+ *   - Linking can fail if another concurrent operation changes target's state
+ *     (revision checks can mitigate using expected_revision).
+ *   - Multi-attach environments may reorder relative attachments if not using
+ *     relative_* fields; always inspect returned link state if ordering matters.
+ *
+ * Introspection:
+ *   - Use bpf_link_get_info_by_fd(link_fd, ...) to query link metadata
+ *     (program ID, attach type, target, cookies, multi-probe details).
+ *   - Enumerate existing links via bpf_link_get_next_id() then open with
+ *     bpf_link_get_fd_by_id().
+ *
+ */
 LIBBPF_API int bpf_link_create(int prog_fd, int target_fd,
 			       enum bpf_attach_type attach_type,
 			       const struct bpf_link_create_opts *opts);
-
+/**
+ * @brief Detach (tear down) an existing BPF link represented by a link file descriptor.
+ *
+ * bpf_link_detach() issues the BPF_LINK_DETACH command to the kernel, breaking
+ * the association between a previously created BPF link (see bpf_link_create())
+ * and its target (cgroup, tracing hook, perf event, netfilter hook, etc.). After
+ * a successful call the program will no longer be invoked at that attach point.
+ *
+ * In most cases you do not need to call bpf_link_detach() explicitly; simply
+ * closing the link FD (close(link_fd)) also detaches the link. This helper is
+ * useful when you want to explicitly detach early while keeping the FD open for
+ * introspection (e.g., querying link info after detachment) or when building
+ * higher-level lifecycle abstractions.
+ *
+ * Semantics:
+ *   - Success makes the in-kernel link inactive; subsequent events at the hook
+ *     no longer trigger the program.
+ *   - The link FD itself does NOT automatically close; you are still responsible
+ *     for close(link_fd) to release user space resources.
+ *   - Repeated calls after a successful detach will fail (idempotency: only the
+ *     first detach succeeds).
+ *
+ * Typical usage:
+ *   int link_fd = bpf_link_create(prog_fd, target_fd, attach_type, &opts);
+ *   ...
+ *   if (bpf_link_detach(link_fd) < 0)
+ *       perror("bpf_link_detach");
+ *   close(link_fd); // optional: now just releases the FD
+ *
+ * Concurrency & races:
+ *   - Detaching can race with another thread closing or detaching the same link.
+ *     In such cases you may observe -EBADF or -ENOENT.
+ *   - Once detached, the program can be safely re-attached elsewhere if desired
+ *     (requires a new link via bpf_link_create()).
+ *
+ * Privileges:
+ *   - Usually requires CAP_BPF and/or CAP_SYS_ADMIN depending on kernel
+ *     configuration, LSM, and lockdown mode. Lack of privileges yields -EPERM
+ *     or -EACCES.
+ *
+ * Post-detach:
+ *   - The program object remains loaded; its own FD is still valid and can be
+ *     attached again.
+ *   - Maps referenced by the program are unaffected.
+ *
+ * @param link_fd File descriptor of the active BPF link to detach; must have
+ *                been obtained via bpf_link_create() or equivalent.
+ *
+ * @return 0 on success; < 0 on failure (negative error code as described above).
+ *
+ * Error handling (negative libbpf-style return codes, errno also set):
+ *   - -EBADF: link_fd is not a valid open file descriptor.
+ *   - -EINVAL: link_fd does not refer to a BPF link, or the kernel does not
+ *              support BPF_LINK_DETACH for this link type.
+ *   - -ENOENT: Link already detached or no longer exists (race with close()).
+ *   - -EPERM / -EACCES: Insufficient privileges or denied by security policy.
+ *   - -EOPNOTSUPP / -ENOTSUP: Kernel lacks support for link detachment of this
+ *                             specific attach type.
+ *   - -ENOMEM: Transient kernel resource exhaustion (rare in this path).
+ *   - Other negative codes may be propagated from the underlying bpf() syscall.
+ *
+ */
 LIBBPF_API int bpf_link_detach(int link_fd);
 
 struct bpf_link_update_opts {
@@ -1222,7 +1406,89 @@ struct bpf_link_update_opts {
 	__u32 old_map_fd;  /* expected old map FD */
 };
 #define bpf_link_update_opts__last_field old_map_fd
-
+/**
+ * @brief Atomically replace (update) the BPF program or map referenced by an
+ *        existing link with a new program.
+ *
+ * bpf_link_update() wraps the BPF_LINK_UPDATE command of the bpf(2) syscall.
+ * It allows retargeting an already established BPF link (identified by
+ * link_fd) to point at a different loaded BPF program (new_prog_fd) without
+ * having to tear the link down (detach) and recreate it. This is typically
+ * used for hot-swapping a program while preserving:
+ *   - Link pinning (bpffs path remains valid).
+ *   - Relative ordering in multi-attach contexts (TC/XDP/cgroup revisions).
+ *   - Existing references held by other processes.
+ *
+ * Consistency & safety:
+ *   - The update is performed atomically: events arriving at the hook will
+ *     either see the old program before the call, or the new one after the
+ *     call; no window exists with an unattached link.
+ *   - Optional expectations can be enforced via @p opts to avoid races:
+ *       * old_prog_fd: Fail with -ESTALE if the link does not currently
+ *         reference that program.
+ *       * old_map_fd:  (Kernel dependent) Can be used when links encapsulate
+ *         a map association; if set and mismatched, update fails.
+ *       * flags: Future extension bits (must be 0 on current kernels).
+ *
+ * Typical usage:
+ *   struct bpf_link_update_opts u = {
+ *       .sz = sizeof(u),
+ *       .flags = 0,
+ *       .old_prog_fd = old_fd, // set to 0 to skip validation
+ *   };
+ *   if (bpf_link_update(link_fd, new_prog_fd, &u) < 0)
+ *       perror("bpf_link_update");
+ *
+ * Preconditions:
+ *   - link_fd must refer to a valid, updatable BPF link. Not all link types
+ *     support in-place program replacement; unsupported types return -EOPNOTSUPP.
+ *   - new_prog_fd must be a loaded BPF program whose type and expected attach
+ *     type are compatible with the link's attach context.
+ *   - If @p opts is non-NULL, opts->sz MUST be set to sizeof(*opts).
+ *
+ * @param link_fd
+ *        File descriptor of the existing BPF link to be updated.
+ * @param new_prog_fd
+ *        File descriptor of the newly loaded BPF program that should replace
+ *        the currently attached program.
+ * @param opts
+ *        Optional pointer to bpf_link_update_opts controlling validation:
+ *          - sz: Structure size for forward/backward compatibility.
+ *          - flags: Reserved; must be 0 (unsupported bits yield -EINVAL).
+ *          - old_prog_fd: Expected current program FD (0 to skip check).
+ *          - old_map_fd:  Expected current map FD (0 to skip; kernel-specific).
+ *        Pass NULL for default (no expectation checks).
+ *
+ * @return
+ *   0        on success (link now points to new_prog_fd).
+ *  <0        negative libbpf-style error code (typically -errno):
+ *              - -EBADF: Invalid link_fd or new_prog_fd.
+ *              - -EINVAL: Malformed opts (bad sz/flags) or incompatible program type.
+ *              - -EOPNOTSUPP: Link type does not support updates.
+ *              - -EPERM / -EACCES: Insufficient privileges (CAP_BPF/CAP_SYS_ADMIN) or blocked by LSM.
+ *              - -ENOENT: Link no longer exists (race) or old_prog_fd refers to a non-existent program.
+ *              - -ESTALE: Expectation mismatch (old_prog_fd / old_map_fd differs).
+ *              - -ENOMEM: Kernel resource allocation failure.
+ *              - Other -errno codes propagated from the bpf() syscall.
+ *
+ * Postconditions:
+ *   - On success, the old program remains loaded; caller should close its FD
+ *     if no longer needed.
+ *   - Pinning status and link ID are preserved.
+ *   - Maps referenced by the new program must be valid; no automatic rebinding
+ *     occurs beyond program substitution.
+ *
+ * Caveats:
+ *   - If verifier features differ (e.g., CO-RE relocations) ensure the new
+ *     program was loaded with compatible expectations for the same hook.
+ *   - Updating to a program of a strictly different attach semantics (e.g.,
+ *     sleepable vs non-sleepable) is rejected if the link type disallows it.
+ *
+ * Thread safety:
+ *   - Safe to call concurrently with other update attempts; only one succeeds.
+ *   - Consumers of the link see either old or new program; intermediate states
+ *     are not observable.
+ */
 LIBBPF_API int bpf_link_update(int link_fd, int new_prog_fd,
 			       const struct bpf_link_update_opts *opts);
 
@@ -1338,6 +1604,72 @@ LIBBPF_API int bpf_prog_get_next_id(__u32 start_id, __u32 *next_id);
  */
 LIBBPF_API int bpf_map_get_next_id(__u32 start_id, __u32 *next_id);
 LIBBPF_API int bpf_btf_get_next_id(__u32 start_id, __u32 *next_id);
+/**
+ * @brief Retrieve the next existing BPF link ID after a given starting ID.
+ *
+ * This helper wraps the kernel's BPF_LINK_GET_NEXT_ID command and enumerates
+ * system-wide BPF link objects (each representing a persistent attachment of
+ * a BPF program) in strictly ascending order of their kernel-assigned IDs.
+ * It is typically used to iterate over all currently existing BPF links from
+ * user space.
+ *
+ * Enumeration pattern:
+ *   1. Initialize start_id to 0 to obtain the first (lowest) existing link ID.
+ *   2. On success, *next_id is set to the first link ID strictly greater than start_id.
+ *   3. Use the returned *next_id as the new start_id for the subsequent call.
+ *   4. Repeat until the function returns -ENOENT, indicating there is no link
+ *      with ID greater than start_id (end of enumeration).
+ *
+ * Concurrency & races:
+ *   - Links can be created or detached concurrently with enumeration. A link ID
+ *     you just retrieved might become invalid before you convert it to an FD
+ *     (via bpf_link_get_fd_by_id()). Always handle failures when opening by ID.
+ *   - Enumeration does not provide a consistent snapshot; links created after
+ *     you pass their predecessor ID may appear in later iterations.
+ *
+ * Lifetime considerations:
+ *   - Link IDs are monotonically increasing and not reused until wraparound
+ *     (effectively unreachable in normal operation).
+ *   - Successfully retrieving an ID does not pin or otherwise prevent link
+ *     detachment; obtain an FD immediately if you need to interact with the link.
+ *
+ * Usage example:
+ *   __u32 id = 0, next;
+ *   while (bpf_link_get_next_id(id, &next) == 0) {
+ *       int link_fd = bpf_link_get_fd_by_id(next);
+ *       if (link_fd >= 0) {
+ *           // Inspect link (e.g., bpf_link_get_info_by_fd(link_fd))
+ *           close(link_fd);
+ *       }
+ *       id = next;
+ *   }
+ *   // Loop terminates when -ENOENT is returned.
+ *
+ * @param start_id
+ *        Starting point for the search. The helper finds the first link ID
+ *        strictly greater than start_id. Use 0 to begin enumeration.
+ * @param next_id
+ *        Pointer to a __u32 that receives the next link ID on success.
+ *        Must not be NULL.
+ *
+ * @return
+ *        0        on success (next_id populated);
+ *        -ENOENT  if there is no link ID greater than start_id (end of iteration);
+ *        -EINVAL  if next_id is NULL or invalid arguments were supplied;
+ *        -EPERM / -EACCES if denied by security policy or lacking required privileges;
+ *        Other negative libbpf-style errors (-errno) on transient or system failures.
+ *
+ * Error handling notes:
+ *   - Treat -ENOENT as normal termination (not an error condition).
+ *   - For other negative returns, errno will also be set to the underlying cause.
+ *
+ * After enumeration:
+ *   - Convert retrieved IDs to FDs with bpf_link_get_fd_by_id() for introspection
+ *     or detachment (via bpf_link_detach()).
+ *   - Closing the FD does not destroy the link if other references remain (e.g.,
+ *     pinned in bpffs); the link persists until explicitly detached or all
+ *     references are released.
+ */
 LIBBPF_API int bpf_link_get_next_id(__u32 start_id, __u32 *next_id);
 
 struct bpf_get_fd_by_id_opts {
@@ -1548,9 +1880,153 @@ LIBBPF_API int bpf_map_get_fd_by_id_opts(__u32 id,
 LIBBPF_API int bpf_btf_get_fd_by_id(__u32 id);
 LIBBPF_API int bpf_btf_get_fd_by_id_opts(__u32 id,
 				const struct bpf_get_fd_by_id_opts *opts);
+/**
+ * @brief Obtain a file descriptor for an existing BPF link given its kernel-assigned ID.
+ *
+ * bpf_link_get_fd_by_id() wraps the BPF_LINK_GET_FD_BY_ID command of the bpf(2)
+ * syscall. A BPF "link" is a persistent in-kernel object representing an
+ * attachment of a BPF program to some hook (cgroup, tracing point, perf event,
+ * netfilter hook, tc/xdp chain, etc.). Each link has a unique, monotonically
+ * increasing ID. This helper converts such an ID into a process-local file
+ * descriptor, allowing user space to inspect, pin, update, or detach the link.
+ *
+ * Typical enumeration + open pattern:
+ *   __u32 id = 0, next;
+ *   while (bpf_link_get_next_id(id, &next) == 0) {
+ *       int link_fd = bpf_link_get_fd_by_id(next);
+ *       if (link_fd >= 0) {
+ *           // Use link_fd (e.g. bpf_link_get_info_by_fd(), bpf_link_detach(), pin)
+ *           close(link_fd);
+ *       }
+ *       id = next;
+ *   }
+ *   // Loop terminates when bpf_link_get_next_id() returns -ENOENT.
+ *
+ * Concurrency & races:
+ *   - A link may be detached (or otherwise invalidated) between discovering its ID
+ *     and calling this function. In that case the call fails with -ENOENT.
+ *   - Successfully retrieving a file descriptor does not prevent later detachment
+ *     by other processes; always handle subsequent operation failures gracefully.
+ *
+ * Lifetime & ownership:
+ *   - On success, the caller owns the returned FD and must close() it when done.
+ *   - Closing the FD decreases the user space reference count; the underlying link
+ *     persists while any references (FDs or pinned bpffs path) remain.
+ *   - Detaching the link (via bpf_link_detach() or closing the last active FD)
+ *     invalidates future operations on that FD.
+ *
+ * Privileges / access control:
+ *   - May require CAP_BPF and/or CAP_SYS_ADMIN depending on kernel configuration,
+ *     LSM policy, or lockdown mode. Lack of privileges yields -EPERM / -EACCES.
+ *   - Security policies can deny access even if the link ID exists.
+ *
+ * Error handling (negative libbpf-style codes; errno is also set):
+ *   - -ENOENT: No link with the specified ID (never existed or already detached).
+ *   - -EPERM / -EACCES: Insufficient privilege or blocked by security policy.
+ *   - -EINVAL: Invalid ID (e.g., 0) or kernel rejected the request (rare).
+ *   - -ENOMEM: Transient kernel resource exhaustion while creating the FD.
+ *   - -EBADF, -EFAULT, or other -errno values: Propagated from the underlying syscall.
+ *
+ * Usage notes:
+ *   - Immediately call bpf_link_get_info_by_fd() after acquiring the FD if you need
+ *     metadata (program ID, attach type, target, cookie, etc.).
+ *   - To keep a link across process restarts, pin it to bpffs via bpf_obj_pin().
+ *   - Prefer using bpf_link_get_fd_by_id_opts() if you need extended open semantics
+ *     (e.g., token-based delegated permissions) on newer kernels.
+ *
+ * @param id
+ *        Kernel-assigned unique ID of the target BPF link (must be > 0). Usually
+ *        obtained via bpf_link_get_next_id() or from a prior info query.
+ *
+ * @return
+ *        >= 0 : File descriptor referring to the BPF link (caller must close()).
+ *        < 0  : Negative error code (libbpf-style, typically -errno) on failure.
+ */
 LIBBPF_API int bpf_link_get_fd_by_id(__u32 id);
+/**
+ * @brief Obtain a file descriptor for an existing BPF link by kernel-assigned link ID
+ *        with extended open options.
+ *
+ * bpf_link_get_fd_by_id_opts() is an extended variant of bpf_link_get_fd_by_id().
+ * It wraps the BPF_LINK_GET_FD_BY_ID command of the bpf(2) syscall and converts a
+ * stable, monotonically increasing BPF link ID into a process-local file descriptor
+ * while honoring optional attributes supplied via @p opts.
+ *
+ * A BPF "link" represents a persistent attachment of a BPF program to some kernel
+ * hook (cgroup, tracing point, perf event, netfilter, tc/xdp chain, etc.). Links can
+ * be enumerated system-wide by first calling bpf_link_get_next_id().
+ *
+ * Typical enumeration + open pattern:
+ *   __u32 id = 0, next;
+ *   while (bpf_link_get_next_id(id, &next) == 0) {
+ *       struct bpf_get_fd_by_id_opts o = {
+ *           .sz = sizeof(o),
+ *           .open_flags = 0,
+ *           .token_fd = 0,
+ *       };
+ *       int link_fd = bpf_link_get_fd_by_id_opts(next, &o);
+ *       if (link_fd >= 0) {
+ *           // inspect link (e.g. bpf_link_get_info_by_fd(link_fd))
+ *           close(link_fd);
+ *       }
+ *       id = next;
+ *   }
+ *   // Loop ends when bpf_link_get_next_id() returns -ENOENT (no more links).
+ *
+ * Concurrency & races:
+ *   - A link may detach between enumeration and opening; handle -ENOENT gracefully.
+ *   - Successfully obtaining a FD does not prevent future detachment by other processes;
+ *     subsequent operations (e.g., bpf_link_get_info_by_fd()) can still fail.
+ *
+ * Lifetime & ownership:
+ *   - The returned FD holds a user-space reference; close() decrements it.
+ *   - The underlying link persists while any references remain (FDs or bpffs pin).
+ *   - Use bpf_obj_pin() to make the link persistent across process lifetimes.
+ *
+ * Security:
+ *   - CAP_BPF and/or CAP_SYS_ADMIN may be required depending on kernel configuration.
+ *   - Token-based access (token_fd) can allow operations in sandboxed environments.
+ *
+ * Follow-up introspection:
+ *   - Call bpf_link_get_info_by_fd(link_fd, ...) to retrieve program ID, attach type,
+ *     target info, cookies, and other metadata.
+ *   - Detach via bpf_link_detach(link_fd) or simply close(link_fd).
+ *
+ * Recommended usage notes:
+ *   - Always zero-initialize the opts struct before setting fields.
+ *   - Treat -ENOENT after enumeration as normal termination, not an error condition.
+ *   - Avoid relying on stable ordering beyond ascending ID sequence; links created
+ *     during enumeration may appear after you pass their predecessor ID.
+ *
+ * @param id
+ *   Kernel-assigned unique (non-zero) BPF link ID. Usually obtained from
+ *   bpf_link_get_next_id() or from a prior info query. Must be > 0.
+ *
+ * @param opts
+ *   Optional pointer to a zero-initialized struct bpf_get_fd_by_id_opts:
+ *     - sz: MUST be set to sizeof(struct bpf_get_fd_by_id_opts) if @p opts
+ *           is non-NULL (enables fwd/backward compatibility).
+ *     - open_flags: Additional open/access flags (currently most callers set 0;
+ *                   unsupported bits yield -EINVAL; semantics are kernel-specific).
+ *     - token_fd: File descriptor of a BPF token granting delegated permissions
+ *                 (set 0 or -1 if unused). Allows restricted environments to
+ *                 open the link without elevated global capabilities.
+ *   Pass NULL for defaults (equivalent to open_flags=0, no token).
+ *
+ * @return
+ *   >= 0 : File descriptor referencing the BPF link (caller owns it; close() when done).
+ *   < 0  : Negative libbpf-style error code (typically -errno):
+ *            - -ENOENT  : Link with @p id does not exist (detached or never created).
+ *            - -EPERM / -EACCES : Insufficient privilege or blocked by LSM/lockdown.
+ *            - -EINVAL  : Invalid @p id (0), malformed @p opts (bad sz / flags), or
+ *                         unsupported open_flags.
+ *            - -ENOMEM  : Transient kernel memory/resource exhaustion.
+ *            - Other negative codes: Propagated from underlying bpf() syscall.
+ *
+ */
 LIBBPF_API int bpf_link_get_fd_by_id_opts(__u32 id,
 				const struct bpf_get_fd_by_id_opts *opts);
+
 LIBBPF_API int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len);
 
 /**
-- 
2.34.1
Powered by blists - more mailing lists
 
