Skip to content

Commit e443f46

Browse files
yinjipingsharang
authored andcommitted
feat: agent - eBPF Add mntnsID prefix to distinguish cross-namespace
1 parent b86c11d commit e443f46

7 files changed

Lines changed: 142 additions & 31 deletions

File tree

agent/src/ebpf/user/mount.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -640,12 +640,20 @@ static int replace_suffix_prefix(const char *str1, const char *str2,
640640
}
641641

642642
u32 copy_file_metrics(int pid, void *dst, void *src, int len,
643-
const char *mount_point, const char *mount_source,
644-
fs_type_t file_type)
643+
u32 mntns_id, const char *mount_point,
644+
const char *mount_source, fs_type_t file_type)
645645
{
646+
#define MNTNS_ID_BUF_SZ 12
646647
if (len <= 0)
647648
return 0;
648649

650+
char mntns_str[MNTNS_ID_BUF_SZ] = { 0 };
651+
if (mntns_id > 0) {
652+
int len;
653+
len = u32_to_str_safe(mntns_id, mntns_str, sizeof(mntns_str));
654+
mntns_str[len] = ':';
655+
}
656+
649657
struct user_io_event_buffer *u_event;
650658
struct __io_event_buffer *event = (struct __io_event_buffer *)src;
651659
char *buffer = event->filename;
@@ -708,6 +716,8 @@ u32 copy_file_metrics(int pid, void *dst, void *src, int len,
708716
sizeof(u_event->file_dir));
709717
}
710718

719+
prepend_prefix_safe(buffer, sizeof(u_event->file_dir), mntns_str);
720+
711721
u_event->bytes_count = event->bytes_count;
712722
u_event->operation = event->operation;
713723
u_event->latency = event->latency;
@@ -717,8 +727,8 @@ u32 copy_file_metrics(int pid, void *dst, void *src, int len,
717727
u_event->mntns_id = event->mntns_id;
718728
strcpy_s_inline(u_event->mount_source, sizeof(u_event->mount_source),
719729
mount_source, strlen(mount_source));
720-
strcpy_s_inline(u_event->mount_point, sizeof(u_event->mount_point),
721-
mount_point, strlen(mount_point));
730+
fast_strncat_trunc(mntns_str, mount_point, u_event->mount_point,
731+
sizeof(u_event->mount_point));
722732
strcpy_s_inline(u_event->filename, sizeof(u_event->filename),
723733
event->filename, strlen(event->filename));
724734
return sizeof(*u_event);

agent/src/ebpf/user/mount.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,14 @@ void get_mount_info(pid_t pid, int mnt_id, u32 mntns_id,
175175
* @param[out] dst Destination buffer
176176
* @param[in] src Source buffer (raw eBPF event)
177177
* @param[in] len Length of destination buffer
178+
* @param[in] mntns_id The mount namespace ID of the file
178179
* @param[in] mount_point Mount point path
179180
* @param[in] mount_source Mount source path
180181
* @param[in] file_type File type (FS_TYPE_REGULAR, FS_TYPE_VIRTUAL, FS_TYPE_NETWORK)
181182
* @return Number of bytes written to dst
182183
*/
183184
uint32_t copy_file_metrics(int pid, void *dst, void *src, int len,
184-
const char *mount_point,
185+
u32 mntns_id, const char *mount_point,
185186
const char *mount_source, fs_type_t file_type);
186187
/**
187188
* @brief Check for changes in the host root mount namespace's mount information.

agent/src/ebpf/user/proc.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,17 @@ static int del_proc_info_from_cache(struct symbolizer_cache_kvp *kv)
287287

288288
int get_proc_info_from_cache(pid_t pid, uint8_t * cid, int cid_size,
289289
uint8_t * name, int name_size, int mnt_id,
290-
uint32_t mntns_id, kern_dev_t s_dev,
291-
char *mount_point, char *mount_source,
292-
int mount_size, fs_type_t *file_type)
290+
uint32_t mntns_id, uint32_t *self_mntns_id,
291+
kern_dev_t s_dev, char *mount_point,
292+
char *mount_source, int mount_size,
293+
fs_type_t *file_type)
293294
{
294295
int ret = -1;
295296
symbol_caches_hash_t *h = &syms_cache_hash;
296297
struct symbolizer_cache_kvp kv;
297298
kv.k.pid = (u64) pid;
298299
kv.v.proc_info_p = 0;
300+
*self_mntns_id = 0;
299301
memset(cid, 0, cid_size);
300302
memset(name, 0, name_size);
301303
memset(mount_point, 0, mount_size);
@@ -314,6 +316,7 @@ int get_proc_info_from_cache(pid_t pid, uint8_t * cid, int cid_size,
314316
memcpy_s_inline((void *)name, name_size, p->comm,
315317
sizeof(p->comm));
316318
}
319+
*self_mntns_id = p->mntns_id;
317320
AO_DEC(&p->use);
318321
ret = 0;
319322
}
@@ -1015,10 +1018,12 @@ void check_and_update_proc_info(bool output_log)
10151018

10161019
int get_proc_info_from_cache(pid_t pid, uint8_t * cid, int cid_size,
10171020
uint8_t * name, int name_size, int mnt_id,
1018-
uint32_t mntns_id, kern_dev_t s_dev,
1019-
char *mount_point, char *mount_source,
1020-
int mount_size, fs_type_t *file_type)
1021+
uint32_t mntns_id, uint32_t *self_mntns_id,
1022+
kern_dev_t s_dev, char *mount_point,
1023+
char *mount_source, int mount_size,
1024+
fs_type_t *file_type)
10211025
{
1026+
*self_mntns_id = 0;
10221027
memset(cid, 0, cid_size);
10231028
memset(name, 0, name_size);
10241029
memset(mount_point, 0, mount_size);

agent/src/ebpf/user/proc.h

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -201,18 +201,19 @@ int create_and_init_proc_info_caches(void);
201201
* If the process is not found in the cache, all output buffers (`cid`, `name`, `mount_point`)
202202
* will be zeroed.
203203
*
204-
* @param pid The process ID to look up.
205-
* @param cid Output buffer to store the container ID.
206-
* @param cid_size Size of the `cid` buffer in bytes.
207-
* @param name Output buffer to store the process name (comm).
208-
* @param name_size Size of the `name` buffer in bytes.
209-
* @param mnt_id Mount ID
210-
* @param mntns_id Mount namespace ID
211-
* @param s_dev Device number to be resolved into a mount point path.
212-
* @param mount_point Output buffer to store the mount point path matching `s_dev`.
213-
* @param mount_source Output buffer to store the mount source path.
214-
* @param mount_size Size of the `mount_point` buffer in bytes.
215-
* @param file_type File type
204+
* @param pid The process ID to look up.
205+
* @param cid Output buffer to store the container ID.
206+
* @param cid_size Size of the `cid` buffer in bytes.
207+
* @param name Output buffer to store the process name (comm).
208+
* @param name_size Size of the `name` buffer in bytes.
209+
* @param mnt_id Mount ID
210+
* @param mntns_id Mount namespace ID
211+
* @param self_mntns_id The mount namespace ID of the process.
212+
* @param s_dev Device number to be resolved into a mount point path.
213+
* @param mount_point Output buffer to store the mount point path matching `s_dev`.
214+
* @param mount_source Output buffer to store the mount source path.
215+
* @param mount_size Size of the `mount_point` buffer in bytes.
216+
* @param file_type File type
216217
*
217218
* @return
218219
* 0 : Successfully found process info in cache and retrieved data.
@@ -225,9 +226,10 @@ int create_and_init_proc_info_caches(void);
225226
*/
226227
int get_proc_info_from_cache(pid_t pid, uint8_t *cid, int cid_size,
227228
uint8_t *name, int name_size, int mnt_id,
228-
uint32_t mntns_id, kern_dev_t s_dev,
229-
char *mount_point, char *mount_source,
230-
int mount_size, fs_type_t *file_type);
229+
uint32_t mntns_id, uint32_t *self_mntns_id,
230+
kern_dev_t s_dev, char *mount_point,
231+
char *mount_source, int mount_size,
232+
fs_type_t *file_type);
231233
void update_proc_info_cache(pid_t pid, enum proc_act_type type);
232234

233235
// Lower version kernels do not support hooking so files in containers

agent/src/ebpf/user/socket.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,6 +1193,9 @@ static void reader_raw_cb(void *cookie, void *raw, int raw_size)
11931193
submit_data->syscall_len = sd->syscall_len;
11941194
submit_data->l7_protocal_hint = sd->data_type;
11951195
submit_data->batch_last_data = false;
1196+
1197+
u32 mntns_id = 0;
1198+
u32 self_mntns_id = 0;
11961199
if (sd->source != DATA_SOURCE_DPDK) {
11971200
submit_data->socket_id = sd->socket_id;
11981201
submit_data->tuple = sd->tuple;
@@ -1226,7 +1229,6 @@ static void reader_raw_cb(void *cookie, void *raw, int raw_size)
12261229
int ret = 0;
12271230
kern_dev_t s_dev = DEV_INVALID;
12281231
int mnt_id = 0;
1229-
u32 mntns_id = 0;
12301232
if (sd->source == DATA_SOURCE_IO_EVENT) {
12311233
struct __io_event_buffer *event =
12321234
(struct __io_event_buffer *)sd->data;
@@ -1238,8 +1240,9 @@ static void reader_raw_cb(void *cookie, void *raw, int raw_size)
12381240
sizeof(submit_data->container_id),
12391241
submit_data->process_kname,
12401242
sizeof(submit_data->process_kname),
1241-
mnt_id, mntns_id, s_dev, mount_point,
1242-
mount_source, sizeof(mount_point), &file_type);
1243+
mnt_id, mntns_id, &self_mntns_id,
1244+
s_dev, mount_point, mount_source,
1245+
sizeof(mount_point), &file_type);
12431246

12441247
// Not found in the process cache, attempting to retrieve from procfs.
12451248
if (ret) {
@@ -1294,10 +1297,13 @@ static void reader_raw_cb(void *cookie, void *raw, int raw_size)
12941297
offset = sd->extra_data_count;
12951298
}
12961299
if (sd->source == DATA_SOURCE_IO_EVENT) {
1300+
u32 display_mntns_id = 0;
1301+
if (self_mntns_id > 0 && mntns_id != self_mntns_id)
1302+
display_mntns_id = mntns_id;
12971303
len =
12981304
copy_file_metrics(sd->tgid, submit_data->cap_data
1299-
+ offset, sd->data,
1300-
len, mount_point,
1305+
+ offset, sd->data, len,
1306+
display_mntns_id, mount_point,
13011307
mount_source, file_type);
13021308
} else {
13031309
memcpy_fast(submit_data->cap_data + offset,

agent/src/ebpf/user/utils.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1771,3 +1771,64 @@ uint32_t murmurhash(const void *key, size_t len, uint32_t seed)
17711771

17721772
return h1;
17731773
}
1774+
1775+
size_t u32_to_str_safe(uint32_t value, char *buf, size_t bufsize)
1776+
{
1777+
char temp[10]; // Maximum digits for uint32_t: 4294967295 -> 10 digits
1778+
int i = 0;
1779+
1780+
if (bufsize == 0) return 0; // Buffer size must be at least 1
1781+
1782+
// Handle zero explicitly
1783+
if (value == 0) {
1784+
if (bufsize < 2) return 0; // Need space for '0' + '\0'
1785+
buf[0] = '0';
1786+
buf[1] = '\0';
1787+
return 1;
1788+
}
1789+
1790+
// Convert number to string in reverse order
1791+
while (value > 0) {
1792+
temp[i++] = '0' + (value % 10);
1793+
value /= 10;
1794+
}
1795+
1796+
// Check if buffer is large enough
1797+
if (bufsize <= (size_t)i) return 0;
1798+
1799+
// Reverse copy to output buffer
1800+
for (int j = 0; j < i; j++) {
1801+
buf[j] = temp[i - j - 1];
1802+
}
1803+
1804+
buf[i] = '\0';
1805+
return i;
1806+
}
1807+
1808+
int prepend_prefix_safe(char *buffer, size_t bufsize, const char *prefix)
1809+
{
1810+
if (!buffer || !prefix || bufsize == 0) {
1811+
return -1; // invalid input
1812+
}
1813+
1814+
size_t len_prefix = strlen(prefix);
1815+
if (len_prefix == 0)
1816+
return 0; // empty prefix, nothing to do
1817+
1818+
size_t len_buffer = strlen(buffer);
1819+
1820+
// Check if buffer has enough space
1821+
if (len_prefix + len_buffer + 1 > bufsize) {
1822+
return -1; // not enough space
1823+
}
1824+
1825+
if (len_prefix > 0) {
1826+
// Move existing string to make room for prefix
1827+
memmove(buffer + len_prefix, buffer, len_buffer + 1); // +1 to move '\0'
1828+
1829+
// Copy prefix to the start
1830+
memcpy(buffer, prefix, len_prefix);
1831+
}
1832+
1833+
return 0;
1834+
}

agent/src/ebpf/user/utils.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,32 @@ void format_port_ranges(uint16_t *ports, size_t size, char *ret_str, int str_sz)
342342
* @return 32-bit hash value computed over the input data.
343343
*/
344344
uint32_t murmurhash(const void *key, size_t len, uint32_t seed);
345+
346+
/*
347+
* Convert uint32_t to decimal string safely
348+
*
349+
* @param value The input number to convert
350+
* @param buf Output buffer to store the string
351+
* @param bufsize Size of the output buffer
352+
* @return Number of characters written (excluding '\0'), or 0 on failure (e.g., buffer too small)
353+
*/
354+
size_t u32_to_str_safe(uint32_t value, char *buf, size_t bufsize);
355+
356+
/*
357+
* Safely prepend a prefix to a string buffer
358+
*
359+
* @param buffer The string buffer to modify
360+
* @param bufsize Total size of the buffer (including space for '\0')
361+
* @param prefix The prefix to prepend
362+
* @return 0 on success, -1 if buffer is too small
363+
*
364+
* Features:
365+
* - Fully safe: checks buffer size
366+
* - Uses memmove to handle overlapping memory
367+
* - Supports empty prefix or empty buffer
368+
* - Always null-terminates on success
369+
*/
370+
int prepend_prefix_safe(char *buffer, size_t bufsize, const char *prefix);
345371
#if !defined(AARCH64_MUSL) && !defined(JAVA_AGENT_ATTACH_TOOL)
346372
int create_work_thread(const char *name, pthread_t *t, void *fn, void *arg);
347373
#endif /* !defined(AARCH64_MUSL) && !defined(JAVA_AGENT_ATTACH_TOOL) */

0 commit comments

Comments
 (0)