|
102 | 102 | #include <linux/fcntl.h> |
103 | 103 | #include <linux/sched.h> |
104 | 104 | #ifdef FULLPATH |
105 | | -#include <linux/fs_struct.h> |
106 | | -#include <linux/dcache.h> |
107 | | -#include <linux/fs.h> |
108 | | -#include <linux/mount.h> |
109 | | -
|
110 | | -/* see https://github.com/torvalds/linux/blob/master/fs/mount.h */ |
111 | | -struct mount { |
112 | | - struct hlist_node mnt_hash; |
113 | | - struct mount *mnt_parent; |
114 | | - struct dentry *mnt_mountpoint; |
115 | | - struct vfsmount mnt; |
116 | | - /* ... */ |
117 | | -}; |
| 105 | +INCLUDE_FULL_PATH_H |
| 106 | +INCLUDE_PATH_HELPERS_BPF_H |
118 | 107 | #endif |
119 | 108 |
|
120 | | -#define NAME_MAX 255 |
121 | | -#define MAX_ENTRIES 32 |
122 | | -
|
123 | 109 | struct val_t { |
124 | 110 | u64 id; |
125 | 111 | char comm[TASK_COMM_LEN]; |
|
136 | 122 | char comm[TASK_COMM_LEN]; |
137 | 123 | u32 path_depth; |
138 | 124 | #ifdef FULLPATH |
139 | | - /** |
140 | | - * Example: "/CCCCC/BB/AAAA" |
141 | | - * name[]: "AAAA000000000000BB0000000000CCCCC00000000000" |
142 | | - * |<- NAME_MAX ->| |
143 | | - * |
144 | | - * name[] must be u8, because char [] will be truncated by ctypes.cast(), |
145 | | - * such as above example, will be truncated to "AAAA0". |
146 | | - */ |
147 | | - u8 name[NAME_MAX * MAX_ENTRIES]; |
| 125 | + FULL_PATH_FIELD(name); |
148 | 126 | #else |
149 | 127 | /* If not fullpath, avoid transfer big data */ |
150 | 128 | char name[NAME_MAX]; |
|
418 | 396 | if args.full_path: |
419 | 397 | bpf_text = bpf_text.replace('SUBMIT_DATA', """ |
420 | 398 | if (data->name[0] != '/') { // relative path |
421 | | - struct task_struct *task; |
422 | | - struct dentry *dentry, *parent_dentry, *mnt_root; |
423 | | - struct vfsmount *vfsmnt; |
424 | | - struct fs_struct *fs; |
425 | | - struct path *path; |
426 | | - struct mount *mnt; |
427 | | - size_t filepart_length; |
428 | | - char *payload = data->name; |
429 | | - struct qstr d_name; |
430 | | - int i; |
431 | | -
|
432 | | - task = (struct task_struct *)bpf_get_current_task_btf(); |
433 | | -
|
434 | | - fs = task->fs; |
435 | | - path = &fs->pwd; |
436 | | - dentry = path->dentry; |
437 | | - vfsmnt = path->mnt; |
438 | | -
|
439 | | - mnt = container_of(vfsmnt, struct mount, mnt); |
440 | | -
|
441 | | - for (i = 1, payload += NAME_MAX; i < MAX_ENTRIES; i++) { |
442 | | - bpf_probe_read_kernel(&d_name, sizeof(d_name), &dentry->d_name); |
443 | | - filepart_length = |
444 | | - bpf_probe_read_kernel_str(payload, NAME_MAX, (void *)d_name.name); |
445 | | -
|
446 | | - if (filepart_length < 0 || filepart_length > NAME_MAX) |
447 | | - break; |
448 | | -
|
449 | | - bpf_probe_read_kernel(&mnt_root, sizeof(mnt_root), &vfsmnt->mnt_root); |
450 | | - bpf_probe_read_kernel(&parent_dentry, sizeof(parent_dentry), &dentry->d_parent); |
451 | | -
|
452 | | - if (dentry == parent_dentry || dentry == mnt_root) { |
453 | | - struct mount *mnt_parent; |
454 | | - bpf_probe_read_kernel(&mnt_parent, sizeof(mnt_parent), &mnt->mnt_parent); |
455 | | -
|
456 | | - if (mnt != mnt_parent) { |
457 | | - bpf_probe_read_kernel(&dentry, sizeof(dentry), &mnt->mnt_mountpoint); |
458 | | -
|
459 | | - mnt = mnt_parent; |
460 | | - vfsmnt = &mnt->mnt; |
461 | | -
|
462 | | - bpf_probe_read_kernel(&mnt_root, sizeof(mnt_root), &vfsmnt->mnt_root); |
463 | | -
|
464 | | - data->path_depth++; |
465 | | - payload += NAME_MAX; |
466 | | - continue; |
467 | | - } else { |
468 | | - /* Real root directory */ |
469 | | - break; |
470 | | - } |
471 | | - } |
472 | | -
|
473 | | - payload += NAME_MAX; |
474 | | -
|
475 | | - dentry = parent_dentry; |
476 | | - data->path_depth++; |
477 | | - } |
| 399 | + bpf_getcwd(data->name + NAME_MAX, NAME_MAX, MAX_ENTRIES - 1, |
| 400 | + &data->path_depth); |
478 | 401 | } |
479 | | -
|
480 | 402 | events.ringbuf_submit(data, sizeof(*data)); |
481 | 403 | """) |
| 404 | + |
| 405 | + with open(BPF._find_file("full_path.h")) as fileobj: |
| 406 | + progtxt = fileobj.read() |
| 407 | + bpf_text = bpf_text.replace('INCLUDE_FULL_PATH_H', progtxt) |
| 408 | + |
| 409 | + with open(BPF._find_file("path_helpers.bpf.c")) as fileobj: |
| 410 | + progtxt = fileobj.read() |
| 411 | + bpf_text = bpf_text.replace('INCLUDE_PATH_HELPERS_BPF_H', progtxt) |
482 | 412 | else: |
483 | 413 | bpf_text = bpf_text.replace('SUBMIT_DATA', """ |
484 | 414 | events.ringbuf_submit(data, sizeof(*data)); |
485 | 415 | """) |
| 416 | + bpf_text = bpf_text.replace('INCLUDE_FULL_PATH_H', """""") |
| 417 | + bpf_text = bpf_text.replace('INCLUDE_PATH_HELPERS_BPF_H', """""") |
486 | 418 |
|
487 | 419 | if debug or args.ebpf: |
488 | 420 | print(bpf_text) |
|
517 | 449 |
|
518 | 450 | entries = defaultdict(list) |
519 | 451 |
|
520 | | -def split_names(str): |
521 | | - NAME_MAX = 255 |
522 | | - MAX_ENTRIES = 32 |
523 | | - chunks = [str[i:i + NAME_MAX] for i in range(0, NAME_MAX * MAX_ENTRIES, NAME_MAX)] |
524 | | - return [chunk.split(b'\x00', 1)[0] for chunk in chunks] |
525 | | - |
526 | 452 | # process event |
527 | 453 | def print_event(cpu, data, size): |
528 | 454 | event = b["events"].event(data) |
@@ -569,17 +495,8 @@ def print_event(cpu, data, size): |
569 | 495 | printb(b"%08o %04o " % (event.flags, event.mode), nl="") |
570 | 496 |
|
571 | 497 | if args.full_path: |
572 | | - # see struct data_t::name field comment. |
573 | | - names = split_names(bytes(event.name)) |
574 | | - picked = names[:event.path_depth + 1] |
575 | | - picked_str = [] |
576 | | - for x in picked: |
577 | | - s = x.decode('utf-8', 'ignore') if isinstance(x, bytes) else str(x) |
578 | | - # remove mountpoint '/' and empty string |
579 | | - if s != "/" and s != "": |
580 | | - picked_str.append(s) |
581 | | - joined = '/'.join(picked_str[::-1]) |
582 | | - result = joined if joined.startswith('/') else '/' + joined |
| 498 | + from path_helpers import get_full_path |
| 499 | + result = get_full_path(event.name, event.path_depth) |
583 | 500 | printb(b"%s" % result.encode("utf-8")) |
584 | 501 | else: |
585 | 502 | printb(b"%s" % event.name) |
|
0 commit comments