#ifndef __CONTAINER_UTILS_H
#define __CONTAINER_UTILS_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <limits.h>
#include <errno.h>
#include <stdbool.h>
#include <sys/types.h>
#include <bpf/libbpf.h>
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#define MAX_CONTAINER_LIBS 64
struct pid_lib_entry {
pid_t pid;
char lib_path[PATH_MAX];
};
struct dynamic_links {
struct bpf_link **links;
int count;
int capacity;
};
static struct dynamic_links g_extra_links = {
.links = NULL, .count = 0, .capacity = 0
};
static void add_dynamic_link(struct bpf_link *link)
{
if (!link)
return;
if (g_extra_links.count >= g_extra_links.capacity) {
int new_cap = g_extra_links.capacity ? g_extra_links.capacity * 2 : 16;
struct bpf_link **tmp = realloc(g_extra_links.links,
new_cap * sizeof(struct bpf_link *));
if (!tmp) {
fprintf(stderr, "realloc dynamic_links failed\n");
return;
}
g_extra_links.links = tmp;
g_extra_links.capacity = new_cap;
}
g_extra_links.links[g_extra_links.count++] = link;
}
static void cleanup_dynamic_links(void)
{
for (int i = 0; i < g_extra_links.count; i++)
bpf_link__destroy(g_extra_links.links[i]);
free(g_extra_links.links);
g_extra_links.links = NULL;
g_extra_links.count = 0;
g_extra_links.capacity = 0;
}
static char *find_library_path_for_pid(pid_t pid, const char *libname,
bool verbose)
{
static char host_path[PATH_MAX];
char maps_path[64];
char line[4096];
FILE *fp;
snprintf(maps_path, sizeof(maps_path), "/proc/%d/maps", pid);
fp = fopen(maps_path, "r");
if (!fp) {
if (verbose)
fprintf(stderr, "Failed to open %s: %s\n",
maps_path, strerror(errno));
return NULL;
}
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, libname) == NULL)
continue;
if (strstr(line, "r-xp") == NULL && strstr(line, "r--p") == NULL)
continue;
char *path = strchr(line, '/');
if (!path)
continue;
char *nl = strchr(path, '\n');
if (nl)
*nl = '\0';
snprintf(host_path, sizeof(host_path), "/proc/%d/root%s", pid, path);
if (access(host_path, R_OK) == 0) {
fclose(fp);
if (verbose)
fprintf(stderr,
"Found %s for PID %d: %s -> %s\n",
libname, pid, path, host_path);
return host_path;
}
}
fclose(fp);
return NULL;
}
static int find_pids_with_library(const char *libname,
struct pid_lib_entry *entries,
int max_entries,
bool verbose)
{
DIR *proc_dir;
struct dirent *ent;
int count = 0;
char (*seen)[PATH_MAX] = calloc(MAX_CONTAINER_LIBS, PATH_MAX);
int seen_count = 0;
if (!seen) {
fprintf(stderr, "Failed to allocate dedup buffer\n");
return 0;
}
proc_dir = opendir("/proc");
if (!proc_dir) {
free(seen);
return 0;
}
while ((ent = readdir(proc_dir)) && count < max_entries) {
pid_t pid = atoi(ent->d_name);
if (pid <= 0)
continue;
char *path = find_library_path_for_pid(pid, libname, false);
if (!path)
continue;
bool dup = false;
for (int i = 0; i < seen_count; i++) {
if (strcmp(seen[i], path) == 0) {
dup = true;
break;
}
}
if (dup)
continue;
if (seen_count < MAX_CONTAINER_LIBS) {
strncpy(seen[seen_count], path, PATH_MAX - 1);
seen[seen_count][PATH_MAX - 1] = '\0';
seen_count++;
}
entries[count].pid = pid;
strncpy(entries[count].lib_path, path, PATH_MAX - 1);
entries[count].lib_path[PATH_MAX - 1] = '\0';
count++;
if (verbose)
fprintf(stderr, "Discovered container SSL lib: %s (via PID %d)\n",
path, pid);
}
closedir(proc_dir);
free(seen);
return count;
}
#endif