From 4360f6d218c3cb32e3f9fd1c0841022fd0560be0 Mon Sep 17 00:00:00 2001 From: Yunwei 123 Date: Thu, 3 Sep 2026 11:44:48 -0700 Subject: [PATCH 1/6] fix: keep GnuTLS and NSS probing enabled by default in sslsniff Commit 337af70 (add hook of ssl_ex version) flipped the default provider flags to off. The --no-gnutls and --no-nss options only clear the same flags, so GnuTLS and NSS probing became unreachable and the documented default behavior (sniff OpenSSL and GnuTLS functions) stopped holding. Restore the gnutls/nss defaults to on, and warn instead of attaching against a NULL library path when a provider library is not present on the system. --- src/30-sslsniff/sslsniff.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/30-sslsniff/sslsniff.c b/src/30-sslsniff/sslsniff.c index 29949119..5a2eaed0 100644 --- a/src/30-sslsniff/sslsniff.c +++ b/src/30-sslsniff/sslsniff.c @@ -90,8 +90,8 @@ struct env { .uid = INVALID_UID, .pid = INVALID_PID, .openssl = true, - .gnutls = false, - .nss = false, + .gnutls = true, + .nss = true, .comm = NULL, }; @@ -399,18 +399,30 @@ int main(int argc, char **argv) { if (env.openssl) { char *openssl_path = find_library_path("libssl.so"); - printf("OpenSSL path: %s\n", openssl_path); - attach_openssl(obj, openssl_path); + if (!openssl_path) { + warn("libssl.so not found; skipping OpenSSL probing\n"); + } else { + printf("OpenSSL path: %s\n", openssl_path); + attach_openssl(obj, openssl_path); + } } if (env.gnutls) { char *gnutls_path = find_library_path("libgnutls.so"); - printf("GnuTLS path: %s\n", gnutls_path); - attach_gnutls(obj, gnutls_path); + if (!gnutls_path) { + warn("libgnutls.so not found; skipping GnuTLS probing\n"); + } else { + printf("GnuTLS path: %s\n", gnutls_path); + attach_gnutls(obj, gnutls_path); + } } if (env.nss) { char *nss_path = find_library_path("libnspr4.so"); - printf("NSS path: %s\n", nss_path); - attach_nss(obj, nss_path); + if (!nss_path) { + warn("libnspr4.so not found; skipping NSS probing\n"); + } else { + printf("NSS path: %s\n", nss_path); + attach_nss(obj, nss_path); + } } pb = perf_buffer__new(bpf_map__fd(obj->maps.perf_SSL_events), From 0b0fb160b40c62253ed10d220b52ee30da6cb1f8 Mon Sep 17 00:00:00 2001 From: Yunwei 123 Date: Thu, 3 Sep 2026 17:43:14 -0700 Subject: [PATCH 2/6] docs: sync lesson 30 provider-attach excerpt with sslsniff source Update the lesson-30 README code excerpts (English and Chinese) to the current sslsniff.c provider-attach block, which now warns and skips a provider whose library is not present instead of attaching against a NULL path. --- src/30-sslsniff/README.md | 26 +++++++++++++++++++------- src/30-sslsniff/README.zh.md | 26 +++++++++++++++++++------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/30-sslsniff/README.md b/src/30-sslsniff/README.md index 8b6fcaf1..999a340a 100644 --- a/src/30-sslsniff/README.md +++ b/src/30-sslsniff/README.md @@ -321,23 +321,35 @@ In the eBPF ecosystem, user-space and kernel-space code often work in collaborat In the provided code snippet, based on the setting of the `env` environment variable, the program can choose to attach to three common encryption libraries (OpenSSL, GnuTLS, and NSS). This means that we can trace calls to multiple libraries within the same tool. -To achieve this functionality, the `find_library_path` function is first used to determine the library's path. Then, depending on the library type, the corresponding `attach_` function is called to attach the eBPF program to the library function. +To achieve this functionality, the `find_library_path` function is first used to determine the library's path. Then, depending on the library type, the corresponding `attach_` function is called to attach the eBPF program to the library function. If `find_library_path` cannot locate a library (for example, because it is not installed on the system), the tool prints a warning to stderr and skips probing that provider instead of attaching against an invalid path. ```c if (env.openssl) { char *openssl_path = find_library_path("libssl.so"); - printf("OpenSSL path: %s\n", openssl_path); - attach_openssl(obj, openssl_path); + if (!openssl_path) { + warn("libssl.so not found; skipping OpenSSL probing\n"); + } else { + printf("OpenSSL path: %s\n", openssl_path); + attach_openssl(obj, openssl_path); + } } if (env.gnutls) { char *gnutls_path = find_library_path("libgnutls.so"); - printf("GnuTLS path: %s\n", gnutls_path); - attach_gnutls(obj, gnutls_path); + if (!gnutls_path) { + warn("libgnutls.so not found; skipping GnuTLS probing\n"); + } else { + printf("GnuTLS path: %s\n", gnutls_path); + attach_gnutls(obj, gnutls_path); + } } if (env.nss) { char *nss_path = find_library_path("libnspr4.so"); - printf("NSS path: %s\n", nss_path); - attach_nss(obj, nss_path); + if (!nss_path) { + warn("libnspr4.so not found; skipping NSS probing\n"); + } else { + printf("NSS path: %s\n", nss_path); + attach_nss(obj, nss_path); + } } ``` diff --git a/src/30-sslsniff/README.zh.md b/src/30-sslsniff/README.zh.md index bab55776..b4df7022 100644 --- a/src/30-sslsniff/README.zh.md +++ b/src/30-sslsniff/README.zh.md @@ -309,23 +309,35 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { 上述代码片段中,根据环境变量 `env` 的设定,程序可以选择针对三种常见的加密库(OpenSSL、GnuTLS 和 NSS)进行挂载。这意味着我们可以在同一个工具中对多种库的调用进行追踪。 -为了实现这一功能,首先利用 `find_library_path` 函数确定库的路径。然后,根据库的类型,调用对应的 `attach_` 函数来将 eBPF 程序挂载到库函数上。 +为了实现这一功能,首先利用 `find_library_path` 函数确定库的路径。然后,根据库的类型,调用对应的 `attach_` 函数来将 eBPF 程序挂载到库函数上。如果 `find_library_path` 找不到某个库(例如系统中没有安装该库),工具会向 stderr 打印一条警告并跳过该库的探测,而不是挂载到无效的路径上。 ```c if (env.openssl) { char *openssl_path = find_library_path("libssl.so"); - printf("OpenSSL path: %s\n", openssl_path); - attach_openssl(obj, openssl_path); + if (!openssl_path) { + warn("libssl.so not found; skipping OpenSSL probing\n"); + } else { + printf("OpenSSL path: %s\n", openssl_path); + attach_openssl(obj, openssl_path); + } } if (env.gnutls) { char *gnutls_path = find_library_path("libgnutls.so"); - printf("GnuTLS path: %s\n", gnutls_path); - attach_gnutls(obj, gnutls_path); + if (!gnutls_path) { + warn("libgnutls.so not found; skipping GnuTLS probing\n"); + } else { + printf("GnuTLS path: %s\n", gnutls_path); + attach_gnutls(obj, gnutls_path); + } } if (env.nss) { char *nss_path = find_library_path("libnspr4.so"); - printf("NSS path: %s\n", nss_path); - attach_nss(obj, nss_path); + if (!nss_path) { + warn("libnspr4.so not found; skipping NSS probing\n"); + } else { + printf("NSS path: %s\n", nss_path); + attach_nss(obj, nss_path); + } } ``` From 83c1e9b741b5fc65b52b21c448ad03333a40de0f Mon Sep 17 00:00:00 2001 From: Yunwei 123 Date: Thu, 3 Sep 2026 20:57:37 -0700 Subject: [PATCH 3/6] fix: match SSL library names literally --- src/30-sslsniff/sslsniff.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/30-sslsniff/sslsniff.c b/src/30-sslsniff/sslsniff.c index 5a2eaed0..10975a34 100644 --- a/src/30-sslsniff/sslsniff.c +++ b/src/30-sslsniff/sslsniff.c @@ -240,8 +240,9 @@ char *find_library_path(const char *libname) { static char path[512]; FILE *fp; - // Construct the ldconfig command with grep - snprintf(cmd, sizeof(cmd), "ldconfig -p | grep %s", libname); + // Match the SONAME prefix literally; dots in library names must not be + // interpreted as regular-expression wildcards. + snprintf(cmd, sizeof(cmd), "ldconfig -p | grep -F -- '%s'", libname); // Execute the command and read the output fp = popen(cmd, "r"); From aaa4e7affa74dc0e54d86701cc829ad9569f344e Mon Sep 17 00:00:00 2001 From: Yunwei 123 Date: Thu, 3 Sep 2026 21:02:58 -0700 Subject: [PATCH 4/6] fix: retain all sslsniff provider links --- src/30-sslsniff/README.md | 16 +++++++--- src/30-sslsniff/README.zh.md | 16 +++++++--- src/30-sslsniff/sslsniff.c | 61 +++++++++++++++++++++++++++--------- 3 files changed, 69 insertions(+), 24 deletions(-) diff --git a/src/30-sslsniff/README.md b/src/30-sslsniff/README.md index 999a340a..33da99ad 100644 --- a/src/30-sslsniff/README.md +++ b/src/30-sslsniff/README.md @@ -321,7 +321,7 @@ In the eBPF ecosystem, user-space and kernel-space code often work in collaborat In the provided code snippet, based on the setting of the `env` environment variable, the program can choose to attach to three common encryption libraries (OpenSSL, GnuTLS, and NSS). This means that we can trace calls to multiple libraries within the same tool. -To achieve this functionality, the `find_library_path` function is first used to determine the library's path. Then, depending on the library type, the corresponding `attach_` function is called to attach the eBPF program to the library function. If `find_library_path` cannot locate a library (for example, because it is not installed on the system), the tool prints a warning to stderr and skips probing that provider instead of attaching against an invalid path. +To achieve this functionality, the `find_library_path` function is first used to determine the library's path. Then, depending on the library type, the corresponding `attach_` function is called to attach the eBPF program to the library function. If `find_library_path` cannot locate a library (for example, because it is not installed on the system), the tool prints a warning to stderr and skips probing that provider instead of attaching against an invalid path. Each successful attachment is tracked separately so that multiple libraries can share the same eBPF program without losing link handles. Incompatible provider symbols produce a warning, and the tool exits if no probe could be attached. ```c if (env.openssl) { @@ -330,7 +330,8 @@ To achieve this functionality, the `find_library_path` function is first used to warn("libssl.so not found; skipping OpenSSL probing\n"); } else { printf("OpenSSL path: %s\n", openssl_path); - attach_openssl(obj, openssl_path); + if (attach_openssl(obj, openssl_path)) + warn("OpenSSL probing is incomplete\n"); } } if (env.gnutls) { @@ -339,7 +340,8 @@ To achieve this functionality, the `find_library_path` function is first used to warn("libgnutls.so not found; skipping GnuTLS probing\n"); } else { printf("GnuTLS path: %s\n", gnutls_path); - attach_gnutls(obj, gnutls_path); + if (attach_gnutls(obj, gnutls_path)) + warn("GnuTLS probing is incomplete\n"); } } if (env.nss) { @@ -348,7 +350,8 @@ To achieve this functionality, the `find_library_path` function is first used to warn("libnspr4.so not found; skipping NSS probing\n"); } else { printf("NSS path: %s\n", nss_path); - attach_nss(obj, nss_path); + if (attach_nss(obj, nss_path)) + warn("NSS probing is incomplete\n"); } } ``` @@ -364,8 +367,11 @@ The specific `attach` functions are as follows: do { \ LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, .func_name = #sym_name, \ .retprobe = is_retprobe); \ - skel->links.prog_name = bpf_program__attach_uprobe_opts( \ + struct bpf_link *link = bpf_program__attach_uprobe_opts( \ skel->progs.prog_name, env.pid, binary_path, 0, &uprobe_opts); \ + int attach_err = track_attached_link(link, #prog_name); \ + if (attach_err) \ + return attach_err; \ } while (false) int attach_openssl(struct sslsniff_bpf *skel, const char *lib) { diff --git a/src/30-sslsniff/README.zh.md b/src/30-sslsniff/README.zh.md index b4df7022..8587cf3a 100644 --- a/src/30-sslsniff/README.zh.md +++ b/src/30-sslsniff/README.zh.md @@ -309,7 +309,7 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { 上述代码片段中,根据环境变量 `env` 的设定,程序可以选择针对三种常见的加密库(OpenSSL、GnuTLS 和 NSS)进行挂载。这意味着我们可以在同一个工具中对多种库的调用进行追踪。 -为了实现这一功能,首先利用 `find_library_path` 函数确定库的路径。然后,根据库的类型,调用对应的 `attach_` 函数来将 eBPF 程序挂载到库函数上。如果 `find_library_path` 找不到某个库(例如系统中没有安装该库),工具会向 stderr 打印一条警告并跳过该库的探测,而不是挂载到无效的路径上。 +为了实现这一功能,首先利用 `find_library_path` 函数确定库的路径。然后,根据库的类型,调用对应的 `attach_` 函数来将 eBPF 程序挂载到库函数上。如果 `find_library_path` 找不到某个库(例如系统中没有安装该库),工具会向 stderr 打印一条警告并跳过该库的探测,而不是挂载到无效的路径上。每次成功挂载都会单独保存 link 句柄,因此多个库可以复用同一个 eBPF 程序而不会丢失句柄;库符号不兼容时会给出警告,如果一个探针都未能挂载,工具会退出。 ```c if (env.openssl) { @@ -318,7 +318,8 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { warn("libssl.so not found; skipping OpenSSL probing\n"); } else { printf("OpenSSL path: %s\n", openssl_path); - attach_openssl(obj, openssl_path); + if (attach_openssl(obj, openssl_path)) + warn("OpenSSL probing is incomplete\n"); } } if (env.gnutls) { @@ -327,7 +328,8 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { warn("libgnutls.so not found; skipping GnuTLS probing\n"); } else { printf("GnuTLS path: %s\n", gnutls_path); - attach_gnutls(obj, gnutls_path); + if (attach_gnutls(obj, gnutls_path)) + warn("GnuTLS probing is incomplete\n"); } } if (env.nss) { @@ -336,7 +338,8 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { warn("libnspr4.so not found; skipping NSS probing\n"); } else { printf("NSS path: %s\n", nss_path); - attach_nss(obj, nss_path); + if (attach_nss(obj, nss_path)) + warn("NSS probing is incomplete\n"); } } ``` @@ -352,8 +355,11 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { do { \ LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, .func_name = #sym_name, \ .retprobe = is_retprobe); \ - skel->links.prog_name = bpf_program__attach_uprobe_opts( \ + struct bpf_link *link = bpf_program__attach_uprobe_opts( \ skel->progs.prog_name, env.pid, binary_path, 0, &uprobe_opts); \ + int attach_err = track_attached_link(link, #prog_name); \ + if (attach_err) \ + return attach_err; \ } while (false) int attach_openssl(struct sslsniff_bpf *skel, const char *lib) { diff --git a/src/30-sslsniff/sslsniff.c b/src/30-sslsniff/sslsniff.c index 10975a34..2101691a 100644 --- a/src/30-sslsniff/sslsniff.c +++ b/src/30-sslsniff/sslsniff.c @@ -20,28 +20,27 @@ #define INVALID_UID -1 #define INVALID_PID -1 #define DEFAULT_BUFFER_SIZE 8192 +#define MAX_ATTACH_LINKS 32 + +static struct bpf_link *attached_links[MAX_ATTACH_LINKS]; +static size_t attached_link_count; +static int track_attached_link(struct bpf_link *link, const char *program_name); #define __ATTACH_UPROBE(skel, binary_path, sym_name, prog_name, is_retprobe) \ do { \ LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts, .func_name = #sym_name, \ .retprobe = is_retprobe); \ - skel->links.prog_name = bpf_program__attach_uprobe_opts( \ + struct bpf_link *link = bpf_program__attach_uprobe_opts( \ skel->progs.prog_name, env.pid, binary_path, 0, &uprobe_opts); \ - } while (false) - -#define __CHECK_PROGRAM(skel, prog_name) \ - do { \ - if (!skel->links.prog_name) { \ - perror("no program attached for " #prog_name); \ - return -errno; \ - } \ + int attach_err = track_attached_link(link, #prog_name); \ + if (attach_err) \ + return attach_err; \ } while (false) #define __ATTACH_UPROBE_CHECKED(skel, binary_path, sym_name, prog_name, \ is_retprobe) \ do { \ __ATTACH_UPROBE(skel, binary_path, sym_name, prog_name, is_retprobe); \ - __CHECK_PROGRAM(skel, prog_name); \ } while (false) #define ATTACH_UPROBE_CHECKED(skel, binary_path, sym_name, prog_name) \ @@ -59,7 +58,7 @@ const char argp_program_doc[] = "USAGE: sslsniff [OPTIONS]\n" "\n" "EXAMPLES:\n" - " ./sslsniff # sniff OpenSSL and GnuTLS functions\n" + " ./sslsniff # sniff OpenSSL, GnuTLS, and NSS functions\n" " ./sslsniff -p 181 # sniff PID 181 only\n" " ./sslsniff -u 1000 # sniff only UID 1000\n" " ./sslsniff -c curl # sniff curl command only\n" @@ -167,6 +166,27 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) { #define PERF_POLL_TIMEOUT_MS 100 #define warn(...) fprintf(stderr, __VA_ARGS__) +static int track_attached_link(struct bpf_link *link, const char *program_name) { + long err = libbpf_get_error(link); + + if (err) { + warn("failed to attach %s: %s\n", program_name, strerror(-err)); + return (int)err; + } + if (attached_link_count == MAX_ATTACH_LINKS) { + bpf_link__destroy(link); + warn("too many SSL probes requested\n"); + return -E2BIG; + } + attached_links[attached_link_count++] = link; + return 0; +} + +static void destroy_attached_links(void) { + while (attached_link_count > 0) + bpf_link__destroy(attached_links[--attached_link_count]); +} + static struct argp argp = { opts, parse_arg, @@ -404,7 +424,9 @@ int main(int argc, char **argv) { warn("libssl.so not found; skipping OpenSSL probing\n"); } else { printf("OpenSSL path: %s\n", openssl_path); - attach_openssl(obj, openssl_path); + err = attach_openssl(obj, openssl_path); + if (err) + warn("OpenSSL probing is incomplete\n"); } } if (env.gnutls) { @@ -413,7 +435,9 @@ int main(int argc, char **argv) { warn("libgnutls.so not found; skipping GnuTLS probing\n"); } else { printf("GnuTLS path: %s\n", gnutls_path); - attach_gnutls(obj, gnutls_path); + err = attach_gnutls(obj, gnutls_path); + if (err) + warn("GnuTLS probing is incomplete\n"); } } if (env.nss) { @@ -422,9 +446,17 @@ int main(int argc, char **argv) { warn("libnspr4.so not found; skipping NSS probing\n"); } else { printf("NSS path: %s\n", nss_path); - attach_nss(obj, nss_path); + err = attach_nss(obj, nss_path); + if (err) + warn("NSS probing is incomplete\n"); } } + if (attached_link_count == 0) { + warn("no SSL provider probes attached\n"); + err = -ENOENT; + goto cleanup; + } + err = 0; pb = perf_buffer__new(bpf_map__fd(obj->maps.perf_SSL_events), PERF_BUFFER_PAGES, handle_event, handle_lost_events, @@ -463,6 +495,7 @@ int main(int argc, char **argv) { cleanup: perf_buffer__free(pb); + destroy_attached_links(); sslsniff_bpf__destroy(obj); return err != 0; } From effdf40b2cd18b4cb99ab6607cf6e7100a1e849e Mon Sep 17 00:00:00 2001 From: Yunwei 123 Date: Thu, 3 Sep 2026 21:07:16 -0700 Subject: [PATCH 5/6] refactor: centralize sslsniff provider setup --- src/30-sslsniff/README.md | 36 ++++------------------- src/30-sslsniff/README.zh.md | 36 ++++------------------- src/30-sslsniff/sslsniff.c | 56 ++++++++++++++---------------------- 3 files changed, 34 insertions(+), 94 deletions(-) diff --git a/src/30-sslsniff/README.md b/src/30-sslsniff/README.md index 33da99ad..d4f7b526 100644 --- a/src/30-sslsniff/README.md +++ b/src/30-sslsniff/README.md @@ -324,36 +324,12 @@ In the provided code snippet, based on the setting of the `env` environment vari To achieve this functionality, the `find_library_path` function is first used to determine the library's path. Then, depending on the library type, the corresponding `attach_` function is called to attach the eBPF program to the library function. If `find_library_path` cannot locate a library (for example, because it is not installed on the system), the tool prints a warning to stderr and skips probing that provider instead of attaching against an invalid path. Each successful attachment is tracked separately so that multiple libraries can share the same eBPF program without losing link handles. Incompatible provider symbols produce a warning, and the tool exits if no probe could be attached. ```c - if (env.openssl) { - char *openssl_path = find_library_path("libssl.so"); - if (!openssl_path) { - warn("libssl.so not found; skipping OpenSSL probing\n"); - } else { - printf("OpenSSL path: %s\n", openssl_path); - if (attach_openssl(obj, openssl_path)) - warn("OpenSSL probing is incomplete\n"); - } - } - if (env.gnutls) { - char *gnutls_path = find_library_path("libgnutls.so"); - if (!gnutls_path) { - warn("libgnutls.so not found; skipping GnuTLS probing\n"); - } else { - printf("GnuTLS path: %s\n", gnutls_path); - if (attach_gnutls(obj, gnutls_path)) - warn("GnuTLS probing is incomplete\n"); - } - } - if (env.nss) { - char *nss_path = find_library_path("libnspr4.so"); - if (!nss_path) { - warn("libnspr4.so not found; skipping NSS probing\n"); - } else { - printf("NSS path: %s\n", nss_path); - if (attach_nss(obj, nss_path)) - warn("NSS probing is incomplete\n"); - } - } + if (env.openssl) + attach_provider(obj, "OpenSSL", "libssl.so", attach_openssl); + if (env.gnutls) + attach_provider(obj, "GnuTLS", "libgnutls.so", attach_gnutls); + if (env.nss) + attach_provider(obj, "NSS", "libnspr4.so", attach_nss); ``` This section primarily covers the attachment logic for the OpenSSL, GnuTLS, and NSS libraries. NSS is a set of security libraries designed for organizations, supporting the creation of secure client and server applications. Originally developed by Netscape, they are now maintained by Mozilla. The other two libraries have been introduced earlier and are not reiterated here. diff --git a/src/30-sslsniff/README.zh.md b/src/30-sslsniff/README.zh.md index 8587cf3a..e23a9c36 100644 --- a/src/30-sslsniff/README.zh.md +++ b/src/30-sslsniff/README.zh.md @@ -312,36 +312,12 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { 为了实现这一功能,首先利用 `find_library_path` 函数确定库的路径。然后,根据库的类型,调用对应的 `attach_` 函数来将 eBPF 程序挂载到库函数上。如果 `find_library_path` 找不到某个库(例如系统中没有安装该库),工具会向 stderr 打印一条警告并跳过该库的探测,而不是挂载到无效的路径上。每次成功挂载都会单独保存 link 句柄,因此多个库可以复用同一个 eBPF 程序而不会丢失句柄;库符号不兼容时会给出警告,如果一个探针都未能挂载,工具会退出。 ```c - if (env.openssl) { - char *openssl_path = find_library_path("libssl.so"); - if (!openssl_path) { - warn("libssl.so not found; skipping OpenSSL probing\n"); - } else { - printf("OpenSSL path: %s\n", openssl_path); - if (attach_openssl(obj, openssl_path)) - warn("OpenSSL probing is incomplete\n"); - } - } - if (env.gnutls) { - char *gnutls_path = find_library_path("libgnutls.so"); - if (!gnutls_path) { - warn("libgnutls.so not found; skipping GnuTLS probing\n"); - } else { - printf("GnuTLS path: %s\n", gnutls_path); - if (attach_gnutls(obj, gnutls_path)) - warn("GnuTLS probing is incomplete\n"); - } - } - if (env.nss) { - char *nss_path = find_library_path("libnspr4.so"); - if (!nss_path) { - warn("libnspr4.so not found; skipping NSS probing\n"); - } else { - printf("NSS path: %s\n", nss_path); - if (attach_nss(obj, nss_path)) - warn("NSS probing is incomplete\n"); - } - } + if (env.openssl) + attach_provider(obj, "OpenSSL", "libssl.so", attach_openssl); + if (env.gnutls) + attach_provider(obj, "GnuTLS", "libgnutls.so", attach_gnutls); + if (env.nss) + attach_provider(obj, "NSS", "libnspr4.so", attach_nss); ``` 这里主要包含 OpenSSL、GnuTLS 和 NSS 三个库的挂载逻辑。NSS 是为组织设计的一套安全库,支持创建安全的客户端和服务器应用程序。它们最初是由 Netscape 开发的,现在由 Mozilla 维护。其他两个库前面已经介绍过了,这里不再赘述。 diff --git a/src/30-sslsniff/sslsniff.c b/src/30-sslsniff/sslsniff.c index 2101691a..63391d2a 100644 --- a/src/30-sslsniff/sslsniff.c +++ b/src/30-sslsniff/sslsniff.c @@ -25,6 +25,7 @@ static struct bpf_link *attached_links[MAX_ATTACH_LINKS]; static size_t attached_link_count; static int track_attached_link(struct bpf_link *link, const char *program_name); +static char *find_library_path(const char *libname); #define __ATTACH_UPROBE(skel, binary_path, sym_name, prog_name, is_retprobe) \ do { \ @@ -252,10 +253,24 @@ int attach_nss(struct sslsniff_bpf *skel, const char *lib) { return 0; } +static void attach_provider(struct sslsniff_bpf *obj, const char *name, + const char *libname, + int (*attach)(struct sslsniff_bpf *, const char *)) { + char *path = find_library_path(libname); + + if (!path) { + warn("%s not found; skipping %s probing\n", libname, name); + return; + } + printf("%s path: %s\n", name, path); + if (attach(obj, path)) + warn("%s probing is incomplete\n", name); +} + /* * Find the path of a library using ldconfig. */ -char *find_library_path(const char *libname) { +static char *find_library_path(const char *libname) { char cmd[128]; static char path[512]; FILE *fp; @@ -418,39 +433,12 @@ int main(int argc, char **argv) { goto cleanup; } - if (env.openssl) { - char *openssl_path = find_library_path("libssl.so"); - if (!openssl_path) { - warn("libssl.so not found; skipping OpenSSL probing\n"); - } else { - printf("OpenSSL path: %s\n", openssl_path); - err = attach_openssl(obj, openssl_path); - if (err) - warn("OpenSSL probing is incomplete\n"); - } - } - if (env.gnutls) { - char *gnutls_path = find_library_path("libgnutls.so"); - if (!gnutls_path) { - warn("libgnutls.so not found; skipping GnuTLS probing\n"); - } else { - printf("GnuTLS path: %s\n", gnutls_path); - err = attach_gnutls(obj, gnutls_path); - if (err) - warn("GnuTLS probing is incomplete\n"); - } - } - if (env.nss) { - char *nss_path = find_library_path("libnspr4.so"); - if (!nss_path) { - warn("libnspr4.so not found; skipping NSS probing\n"); - } else { - printf("NSS path: %s\n", nss_path); - err = attach_nss(obj, nss_path); - if (err) - warn("NSS probing is incomplete\n"); - } - } + if (env.openssl) + attach_provider(obj, "OpenSSL", "libssl.so", attach_openssl); + if (env.gnutls) + attach_provider(obj, "GnuTLS", "libgnutls.so", attach_gnutls); + if (env.nss) + attach_provider(obj, "NSS", "libnspr4.so", attach_nss); if (attached_link_count == 0) { warn("no SSL provider probes attached\n"); err = -ENOENT; From 9ca1d317f0c6c8442d571379503d59c4da8caffb Mon Sep 17 00:00:00 2001 From: Yunwei 123 Date: Thu, 3 Sep 2026 21:11:03 -0700 Subject: [PATCH 6/6] refactor: keep provider branches out of main --- src/30-sslsniff/README.md | 9 +++------ src/30-sslsniff/README.zh.md | 9 +++------ src/30-sslsniff/sslsniff.c | 15 +++++++-------- 3 files changed, 13 insertions(+), 20 deletions(-) diff --git a/src/30-sslsniff/README.md b/src/30-sslsniff/README.md index d4f7b526..5b04128d 100644 --- a/src/30-sslsniff/README.md +++ b/src/30-sslsniff/README.md @@ -324,12 +324,9 @@ In the provided code snippet, based on the setting of the `env` environment vari To achieve this functionality, the `find_library_path` function is first used to determine the library's path. Then, depending on the library type, the corresponding `attach_` function is called to attach the eBPF program to the library function. If `find_library_path` cannot locate a library (for example, because it is not installed on the system), the tool prints a warning to stderr and skips probing that provider instead of attaching against an invalid path. Each successful attachment is tracked separately so that multiple libraries can share the same eBPF program without losing link handles. Incompatible provider symbols produce a warning, and the tool exits if no probe could be attached. ```c - if (env.openssl) - attach_provider(obj, "OpenSSL", "libssl.so", attach_openssl); - if (env.gnutls) - attach_provider(obj, "GnuTLS", "libgnutls.so", attach_gnutls); - if (env.nss) - attach_provider(obj, "NSS", "libnspr4.so", attach_nss); + attach_provider(obj, env.openssl, "OpenSSL", "libssl.so", attach_openssl); + attach_provider(obj, env.gnutls, "GnuTLS", "libgnutls.so", attach_gnutls); + attach_provider(obj, env.nss, "NSS", "libnspr4.so", attach_nss); ``` This section primarily covers the attachment logic for the OpenSSL, GnuTLS, and NSS libraries. NSS is a set of security libraries designed for organizations, supporting the creation of secure client and server applications. Originally developed by Netscape, they are now maintained by Mozilla. The other two libraries have been introduced earlier and are not reiterated here. diff --git a/src/30-sslsniff/README.zh.md b/src/30-sslsniff/README.zh.md index e23a9c36..46788108 100644 --- a/src/30-sslsniff/README.zh.md +++ b/src/30-sslsniff/README.zh.md @@ -312,12 +312,9 @@ int BPF_URETPROBE(probe_SSL_do_handshake_exit) { 为了实现这一功能,首先利用 `find_library_path` 函数确定库的路径。然后,根据库的类型,调用对应的 `attach_` 函数来将 eBPF 程序挂载到库函数上。如果 `find_library_path` 找不到某个库(例如系统中没有安装该库),工具会向 stderr 打印一条警告并跳过该库的探测,而不是挂载到无效的路径上。每次成功挂载都会单独保存 link 句柄,因此多个库可以复用同一个 eBPF 程序而不会丢失句柄;库符号不兼容时会给出警告,如果一个探针都未能挂载,工具会退出。 ```c - if (env.openssl) - attach_provider(obj, "OpenSSL", "libssl.so", attach_openssl); - if (env.gnutls) - attach_provider(obj, "GnuTLS", "libgnutls.so", attach_gnutls); - if (env.nss) - attach_provider(obj, "NSS", "libnspr4.so", attach_nss); + attach_provider(obj, env.openssl, "OpenSSL", "libssl.so", attach_openssl); + attach_provider(obj, env.gnutls, "GnuTLS", "libgnutls.so", attach_gnutls); + attach_provider(obj, env.nss, "NSS", "libnspr4.so", attach_nss); ``` 这里主要包含 OpenSSL、GnuTLS 和 NSS 三个库的挂载逻辑。NSS 是为组织设计的一套安全库,支持创建安全的客户端和服务器应用程序。它们最初是由 Netscape 开发的,现在由 Mozilla 维护。其他两个库前面已经介绍过了,这里不再赘述。 diff --git a/src/30-sslsniff/sslsniff.c b/src/30-sslsniff/sslsniff.c index 63391d2a..31df9232 100644 --- a/src/30-sslsniff/sslsniff.c +++ b/src/30-sslsniff/sslsniff.c @@ -253,9 +253,11 @@ int attach_nss(struct sslsniff_bpf *skel, const char *lib) { return 0; } -static void attach_provider(struct sslsniff_bpf *obj, const char *name, - const char *libname, +static void attach_provider(struct sslsniff_bpf *obj, bool enabled, + const char *name, const char *libname, int (*attach)(struct sslsniff_bpf *, const char *)) { + if (!enabled) + return; char *path = find_library_path(libname); if (!path) { @@ -433,12 +435,9 @@ int main(int argc, char **argv) { goto cleanup; } - if (env.openssl) - attach_provider(obj, "OpenSSL", "libssl.so", attach_openssl); - if (env.gnutls) - attach_provider(obj, "GnuTLS", "libgnutls.so", attach_gnutls); - if (env.nss) - attach_provider(obj, "NSS", "libnspr4.so", attach_nss); + attach_provider(obj, env.openssl, "OpenSSL", "libssl.so", attach_openssl); + attach_provider(obj, env.gnutls, "GnuTLS", "libgnutls.so", attach_gnutls); + attach_provider(obj, env.nss, "NSS", "libnspr4.so", attach_nss); if (attached_link_count == 0) { warn("no SSL provider probes attached\n"); err = -ENOENT;