Skip to content

Commit

Permalink
Merge pull request #2 from Andreagit97/support_cmdline
Browse files Browse the repository at this point in the history
new: support cmdline arguments
  • Loading branch information
Andreagit97 authored Mar 23, 2024
2 parents 85cff79 + 14effac commit e2c3b6a
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 8 deletions.
47 changes: 39 additions & 8 deletions pkg/task/bpf/iter.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@

/* Extracted from the kernel */
#define MAX_PID_NS_LEVEL 32

#define UINT32_MAX (4294967295U)
#define EXE_PATH_MAX_LEN 1024
#define CMDLINE_MAX_LEN 1024
#define SAFE_1024_ACCESS(x) x &(1024 - 1)

char _license[] SEC("license") = "GPL";

Expand All @@ -32,6 +34,7 @@ struct exported_task_info
char exe_path[EXE_PATH_MAX_LEN];
int64_t loginuid;
int64_t euid;
char cmdline[CMDLINE_MAX_LEN];
} typedef exported_task_info;

/* If necessary we could expand this header */
Expand All @@ -52,14 +55,12 @@ header h;
/* Keep the number of task struct visited */
uint64_t counter = 0;

#define UINT32_MAX (4294967295U)

/* used to check the endianness */
const uint16_t magic = 0xeB9F;
/* Initial version equals to 0 */
const uint32_t header_version = 0;

SEC("iter/task")
SEC("iter.s/task")
int dump_task(struct bpf_iter__task *ctx)
{
struct seq_file *seq = ctx->meta->seq;
Expand Down Expand Up @@ -165,18 +166,31 @@ int dump_task(struct bpf_iter__task *ctx)
struct file *exe_file = task->mm->exe_file;
if(exe_file != NULL)
{
/* Right now we don't care about the return value */
bpf_d_path(&(exe_file->f_path), data.exe_path, EXE_PATH_MAX_LEN);
// According to the manual if the path is too long the helper
// doesn't populate the path so we return a too-long.
if(bpf_d_path(&(exe_file->f_path), data.exe_path,
EXE_PATH_MAX_LEN) < 0)
{
// The path was too long `TL`
data.exe_path[0] = 'T';
data.exe_path[1] = 'L';
data.exe_path[2] = '\0';
}
}
}
else
{
data.exe_path[0] = '\0';
// The path is not available `NA`, we cannot recover it!
data.exe_path[0] = 'N';
data.exe_path[1] = 'A';
data.exe_path[2] = '\0';
}
}
else
{
data.exe_path[0] = '\0';
data.exe_path[0] = 'N';
data.exe_path[1] = 'A';
data.exe_path[2] = '\0';
}

/* `loginuid` is an uint32_t but we use 64 bit in this way we can provide the user with a
Expand All @@ -203,6 +217,23 @@ int dump_task(struct bpf_iter__task *ctx)
data.euid = -1;
}

// todo!: we need to manage the `set_proctitle` issue
unsigned long arg_start_pointer = task->mm->arg_start;
unsigned long arg_end_pointer = task->mm->arg_end;
const uint16_t cmdline_len = arg_end_pointer - arg_start_pointer >= CMDLINE_MAX_LEN
? CMDLINE_MAX_LEN - 1
: arg_end_pointer - arg_start_pointer;

int ret = bpf_copy_from_user_task(&data.cmdline[0], SAFE_1024_ACCESS(cmdline_len),
(void *)arg_start_pointer, task, 0);
if(ret != 0)
{
bpf_printk("[BPFTREE] cmdline read error(%d)!", ret);
data.cmdline[0] = 'N';
data.cmdline[1] = 'A';
data.cmdline[2] = '\0';
}

bpf_seq_write(seq, &data, sizeof(data));
return 0;
}
12 changes: 12 additions & 0 deletions pkg/task/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const (
exePathField
loginUIDField
eUIDField
cmdLineField
maxField
)

Expand Down Expand Up @@ -246,6 +247,17 @@ var allowedFieldsSlice = [maxField]fieldInfo{
return fmt.Sprintf("%d", t.getEUID())
},
},

cmdLineField: {
allowedNames: []string{"cmdline", "cmd"},
description: "command line of the current task",
displayField: func(t *task) string {
return fmt.Sprintf("cmd: %s, ", t.getCmdLine())
},
stringField: func(t *task) string {
return t.getCmdLine()
},
},
}

var (
Expand Down
11 changes: 11 additions & 0 deletions pkg/task/task.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,17 @@ func (t *task) getEUIDName() string {
return ""
}

// todo!: this is simple scratch implementation it doesn't cover all the cases.
// Moreover we need to address the `set_proctitle` call in the kernel code.
func (t *task) getCmdLine() string {
// remove all the extra bytes at the end, if we have them
fullCmdLine := bytes.Split(t.Info.CmdLine[:], []byte{0, 0})
// we obtain a slice of slices with single arguments
singleArgs := bytes.Split(fullCmdLine[0], []byte{0})
joinedArgs := bytes.Join(singleArgs, []byte(","))
return string(joinedArgs)
}

func init() {
userList = make(map[string]string)
}
7 changes: 7 additions & 0 deletions pkg/task/task_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var (
const (
commLen uint32 = 16
exePathLen uint32 = 1024
cmdLineLen uint32 = 1024
)

// TaskInfo is the struct sent by BPF side for each task.
Expand All @@ -39,6 +40,7 @@ type TaskInfo struct {
ExePath [exePathLen]byte
LoginUID int64
EUID int64
CmdLine [cmdLineLen]byte
}

func obtainTaskInfoField(reader io.ReadCloser, fieldSize uint32, data any) error {
Expand Down Expand Up @@ -158,6 +160,11 @@ func parseTaskInfo(reader io.ReadCloser) (TaskInfo, error) {
return t, err
}

/* cmdline */
if err := obtainTaskInfoField(reader, cmdLineLen, &t.CmdLine); err != nil {
return t, err
}

/*
* Add all new fields here...
*/
Expand Down
12 changes: 12 additions & 0 deletions pkg/task/task_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,18 @@ func TestGetFieldMatrix(t *testing.T) {
}},
"-1",
func(t task) string { return fmt.Sprint(t.getEUID()) }},
{"GetCmdLine",
task{Info: TaskInfo{
CmdLine: [exePathLen]byte{'e', 'x', 'e', 0, 'a', 'r', 'g', '1', 0, 'a', 'r', 'g', '2', 0},
}},
"exe,arg1,arg2",
func(t task) string { return t.getCmdLine() }},
{"GetCmdLineExtra0",
task{Info: TaskInfo{
CmdLine: [exePathLen]byte{'e', 'x', 'e', 0, 'a', 'r', 'g', '1', 0, 'a', 'r', 'g', '2', 0, 0, 0},
}},
"exe,arg1,arg2",
func(t task) string { return t.getCmdLine() }},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions testdata/script/cmd_fields/cmd_fields.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ cmp stdout fields/supported_fields.txt
| exepath,e | full executable path of the current task |
| loginuid,lu | UID of the user that interacted with a login service |
| euid,eu | Effective UID |
| cmdline,cmd | command line of the current task |

0 comments on commit e2c3b6a

Please sign in to comment.