Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(capture): Enrich capture output with user information #230

Merged
merged 3 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions bpf/bpf_arm64_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified bpf/bpf_arm64_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_legacy_arm64_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_legacy_x86_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_no_tracing_arm64_bpfel.o
Binary file not shown.
Binary file modified bpf/bpf_no_tracing_x86_bpfel.o
Binary file not shown.
2 changes: 2 additions & 0 deletions bpf/bpf_x86_bpfel.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Binary file modified bpf/bpf_x86_bpfel.o
Binary file not shown.
12 changes: 12 additions & 0 deletions bpf/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ struct process_meta_t {
u32 mntns_id;
u32 netns_id;
u32 tid;
u32 uid;
u32 gid;
char tname[TASK_COMM_LEN];
char cgroup_name[MAX_CGROUP_NAME_LEN];
};
Expand Down Expand Up @@ -251,6 +253,14 @@ static __always_inline void fill_process_meta(struct task_struct *task, struct p
BPF_CORE_READ_INTO(&meta->pid, task, tgid);
BPF_CORE_READ_INTO(&meta->ppid, task, real_parent, tgid);

// u64 uid_gid = bpf_get_current_uid_gid();
// meta->uid = uid_gid & 0xFFFFFFFF;
// meta->gid = uid_gid >> 32;
BPF_CORE_READ_INTO(&meta->uid, task, cred, uid);
BPF_CORE_READ_INTO(&meta->gid, task, cred, gid);

// debug_log("uid %lld, gid %lld\n", meta->uid, meta->gid);

const char *cname = BPF_CORE_READ(task, cgroups, subsys[0], cgroup, kn, name);
int size = bpf_core_read_str(&meta->cgroup_name, sizeof(meta->cgroup_name), cname);
if (size < MIN_CGROUP_NAME_LEN) {
Expand Down Expand Up @@ -368,6 +378,8 @@ static __always_inline void clone_process_meta(struct process_meta_t *origin, st
target->mntns_id = origin->mntns_id;
target->netns_id = origin->netns_id;
target->pidns_id = origin->pidns_id;
target->uid = origin->uid;
target->gid = origin->gid;
__builtin_memcpy(&target->cgroup_name, &origin->cgroup_name, sizeof(origin->cgroup_name));
}

Expand Down
6 changes: 5 additions & 1 deletion cmd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
extPcap = ".pcap"
extPcapNG = ".pcapng"

contextUser = "user"
contextProcess = "process"
contextThread = "thread"
contextParentProc = "parentproc"
Expand Down Expand Up @@ -155,14 +156,17 @@ func prepareOptions(opts *Options, rawArgs []string, args []string) {

if len(opts.enhancedContexts) == 0 {
opts.enhancedContext = types.EnhancedContextProcess | types.EnhancedContextParentProc |
types.EnhancedContextContainer | types.EnhancedContextPod | types.EnhancedContextThread
types.EnhancedContextContainer | types.EnhancedContextPod |
types.EnhancedContextThread | types.EnhancedContextUser
}
for _, c := range opts.enhancedContexts {
switch c {
case contextProcess:
opts.enhancedContext |= types.EnhancedContextProcess
case contextThread:
opts.enhancedContext |= types.EnhancedContextThread
case contextUser:
opts.enhancedContext |= types.EnhancedContextUser
case contextParentProc:
opts.enhancedContext |= types.EnhancedContextParentProc
case contextContainer:
Expand Down
15 changes: 15 additions & 0 deletions cmd/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,21 @@ func TestFormat(t *testing.T) {
},
expectedOutFile: "../testdata/format/curl-thread.pcapng.-v.out.txt",
},
{
name: "user",
opts: &Options{
readFilePath: "../testdata/format/curl-user.pcapng",
},
expectedOutFile: "../testdata/format/curl-user.pcapng.out.txt",
},
{
name: "user -v",
opts: &Options{
readFilePath: "../testdata/format/curl-user.pcapng",
verbose: 1,
},
expectedOutFile: "../testdata/format/curl-user.pcapng.-v.out.txt",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down
3 changes: 2 additions & 1 deletion cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ func init() {
rootCmd.Flags().BoolVarP(&opts.quiet, "quiet", "q", false,
"Quiet output. Print less protocol information so output lines are shorter")
rootCmd.Flags().StringSliceVar(&opts.enhancedContexts, "context",
[]string{contextProcess, contextThread, contextParentProc, contextContainer, contextPod},
[]string{contextProcess, contextThread, contextParentProc, contextUser,
contextContainer, contextPod},
"Specify which context information to include in the output")
rootCmd.Flags().StringVar(&opts.backend, "backend", string(types.NetHookBackendTc),
"Specify the backend to use for capturing packets. "+
Expand Down
8 changes: 6 additions & 2 deletions internal/event/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type Packet struct {
Device types.Device
Pid int
Tid int
Uid int
Gid int
TName string
MntNs int
NetNs int
Expand All @@ -53,14 +55,16 @@ func ParsePacketEvent(deviceCache *metadata.DeviceCache, event bpf.BpfPacketEven
}
p.Pid = int(event.Meta.Process.Pid)
p.Tid = int(event.Meta.Process.Tid)
p.Uid = int(event.Meta.Process.Uid)
p.Gid = int(event.Meta.Process.Gid)
p.TName = utils.GoString(event.Meta.Process.Tname[:])
p.MntNs = int(event.Meta.Process.MntnsId)
p.NetNs = int(event.Meta.Process.NetnsId)
p.CgroupName = utils.GoString(event.Meta.Process.CgroupName[:])
p.Device, _ = deviceCache.GetByIfindex(int(event.Meta.Ifindex), event.Meta.Process.NetnsId)

log.Infof("new packet event, thread: %s.%d, pid: %d mntns: %d, netns: %d, cgroupName: %s",
p.TName, p.Tid, p.Pid, p.MntNs, p.NetNs, p.CgroupName)
log.Infof("new packet event, thread: %s.%d, pid: %d, uid: %d, gid: %d, mntns: %d, netns: %d, cgroupName: %s",
p.TName, p.Tid, p.Pid, p.Uid, p.Gid, p.MntNs, p.NetNs, p.CgroupName)

p.L3Protocol = event.Meta.L3Protocol
p.FirstLayer = firstLayerType(event.Meta.FirstLayer)
Expand Down
11 changes: 10 additions & 1 deletion internal/event/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,21 @@ func ParseProcessExecEvent(event bpf.BpfExecEventT) (*types.ProcessExec, error)

func FromPacketOptions(opts pcapgo.NgPacketOptions) (types.ProcessExec, types.PacketContext) {
p := &types.ProcessExec{}
pctx := &types.PacketContext{}
pctx := &types.PacketContext{
Process: types.Process{
ProcessBase: types.ProcessBase{
UserId: -1,
GroupId: -1,
},
},
}

pctx.FromPacketComments(opts.Comments)
p.PPid = pctx.Parent.Pid
p.Pid = pctx.Pid
p.Tid = pctx.Tid
p.Uid = pctx.UserId
p.Gid = pctx.GroupId
p.TName = pctx.TName
p.Filename = pctx.Cmd
p.FilenameTruncated = pctx.CmdTruncated
Expand Down
21 changes: 21 additions & 0 deletions internal/metadata/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func (c *ProcessCache) fillRunningProcesses(ctx context.Context) error {
<-pool
wg.Done()
}()

ppid := 0
if parent, err := p.ParentWithContext(ctx); err == nil {
ppid = int(parent.Pid)
Expand All @@ -91,9 +92,20 @@ func (c *ProcessCache) fillRunningProcesses(ctx context.Context) error {
filename, _ = p.Name()
}
args, _ := p.CmdlineSlice()
uid := -1
gid := -1
if uids, _ := p.Uids(); len(uids) > 0 {
uid = int(uids[0])
}
if gids, _ := p.Gids(); len(gids) > 0 {
gid = int(gids[0])
}

e := types.ProcessExec{
PPid: ppid,
Pid: int(p.Pid),
Uid: uid,
Gid: gid,
Filename: filename,
FilenameTruncated: false,
Args: args,
Expand Down Expand Up @@ -187,6 +199,11 @@ func (c *ProcessCache) AddItemWithContext(exec types.ProcessExec, rawCtx types.P
ProcessBase: types.ProcessBase{
Pid: exec.Pid,
Cmd: exec.FilenameStr(),
CmdTruncated: false,
Tid: 0,
TName: "",
UserId: exec.Uid,
GroupId: exec.Gid,
Args: exec.Args,
ArgsTruncated: exec.ArgsTruncated,
},
Expand Down Expand Up @@ -235,6 +252,10 @@ func (c *ProcessCache) getProcessBase(pid int) types.ProcessBase {
Pid: pid,
Cmd: cmd,
CmdTruncated: false,
Tid: 0,
TName: "",
UserId: -1,
GroupId: -1,
Args: args,
ArgsTruncated: false,
}
Expand Down
2 changes: 2 additions & 0 deletions internal/parser/pcapng.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func (p *PcapNGParser) Parse() (*event.Packet, error) {
exec, ctx := event.FromPacketOptions(opts)
e.Pid = exec.Pid
e.Tid = exec.Tid
e.Uid = exec.Uid
e.Gid = exec.Gid
e.TName = exec.TName
p.pcache.AddItemWithContext(exec, ctx)

Expand Down
4 changes: 4 additions & 0 deletions internal/types/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ func (c *PacketContext) FromPacketComments(comments []string) {
c.Tid, _ = strconv.Atoi(value)
case "ThreadName":
c.TName = value
case "UserId":
c.UserId, _ = strconv.Atoi(value)
case "GroupId":
c.GroupId, _ = strconv.Atoi(value)
case "ParentPID":
c.Parent.Pid, _ = strconv.Atoi(value)
case "Command", "Cmd", "ParentCommand", "ParentCmd":
Expand Down
5 changes: 5 additions & 0 deletions internal/types/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,17 @@ const (
EnhancedContextContainer
EnhancedContextPod
EnhancedContextThread
EnhancedContextUser
)

func (c EnhancedContext) ProcessContext() bool {
return c == 0 || c&EnhancedContextProcess != 0
}

func (c EnhancedContext) UserContext() bool {
return c == 0 || c&EnhancedContextUser != 0
}

func (c EnhancedContext) ThreadContext() bool {
return c == 0 || c&EnhancedContextThread != 0
}
Expand Down
5 changes: 5 additions & 0 deletions internal/types/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ type ProcessBase struct {
CmdTruncated bool
Tid int
TName string
UserId int
GroupId int

Args []string
ArgsTruncated bool
Expand All @@ -36,6 +38,9 @@ type ProcessExec struct {
Tid int
TName string

Uid int
Gid int

Filename string
FilenameTruncated bool

Expand Down
12 changes: 12 additions & 0 deletions internal/writer/pcapng.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ func (w *PcapNGWriter) Write(e *event.Packet) error {
p := w.pcache.Get(e.Pid, e.MntNs, e.NetNs, e.CgroupName)
p.Tid = e.Tid
p.TName = e.TName
if p.UserId == 0 && e.Uid != 0 {
p.UserId = e.Uid
}
if p.GroupId == 0 && e.Gid != 0 {
p.GroupId = e.Gid
}

opts := pcapgo.NgPacketOptions{}
if w.enhancedContext.ProcessContext() && p.Pid > 0 {
Expand All @@ -62,6 +68,12 @@ func (w *PcapNGWriter) Write(e *event.Packet) error {
p.Tid, p.TName),
)
}
if w.enhancedContext.UserContext() && p.UserId >= 0 {
opts.Comments = append(opts.Comments,
fmt.Sprintf("UserId: %d\nGroupId: %d",
p.UserId, p.GroupId),
)
}
if w.enhancedContext.ParentProcContext() && p.Parent.Pid > 0 {
opts.Comments = append(opts.Comments,
fmt.Sprintf("ParentPID: %d\nParentCmd: %s\nParentArgs: %s",
Expand Down
16 changes: 16 additions & 0 deletions internal/writer/stdout.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,16 @@ func (w *StdoutWriter) Write(e *event.Packet) error {
p := w.pcache.Get(e.Pid, e.MntNs, e.NetNs, e.CgroupName)
p.Tid = e.Tid
p.TName = e.TName
if p.UserId == 0 && e.Uid != 0 {
p.UserId = e.Uid
}
if p.GroupId == 0 && e.Gid != 0 {
p.GroupId = e.Gid
}

processInfo := ""
threadInfo := ""
userInfo := ""
parentProcInfo := ""
containerInfo := ""
PodInfo := ""
Expand All @@ -77,6 +84,9 @@ func (w *StdoutWriter) Write(e *event.Packet) error {
if w.enhancedContext.ProcessContext() && p.Tid > 0 {
threadInfo = fmt.Sprintf("Thread (tid %d, name %s)", p.Tid, p.TName)
}
if w.enhancedContext.UserContext() && p.UserId >= 0 {
userInfo = fmt.Sprintf("User (uid %d, gid %d)", p.UserId, p.GroupId)
}
if w.enhancedContext.ParentProcContext() && p.Parent.Pid > 0 {
parentProcInfo = fmt.Sprintf("ParentProc (pid %d, cmd %s, args %s)",
p.Parent.Pid, p.Parent.Cmd, p.Parent.FormatArgs())
Expand Down Expand Up @@ -151,6 +161,9 @@ func (w *StdoutWriter) Write(e *event.Packet) error {
if threadInfo != "" {
builder.WriteString(fmt.Sprintf(" %s\n", threadInfo))
}
if userInfo != "" {
builder.WriteString(fmt.Sprintf(" %s\n", userInfo))
}
if parentProcInfo != "" {
builder.WriteString(fmt.Sprintf(" %s\n", parentProcInfo))
}
Expand All @@ -167,6 +180,9 @@ func (w *StdoutWriter) Write(e *event.Packet) error {
if threadInfo != "" {
builder.WriteString(fmt.Sprintf(", %s", threadInfo))
}
if userInfo != "" {
builder.WriteString(fmt.Sprintf(", %s", userInfo))
}
if parentProcInfo != "" {
builder.WriteString(fmt.Sprintf(", %s", parentProcInfo))
}
Expand Down
Binary file added testdata/format/curl-user.pcapng
Binary file not shown.
25 changes: 25 additions & 0 deletions testdata/format/curl-user.pcapng.-v.out.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
14:40:20.276349 ens33 Out IP (tos 0x0, ttl 64, id 54926, offset 0, flags [DF], proto TCP (6), length 60)
10.0.2.15.43950 > 139.178.84.217.443: Flags [S], cksum 0xecc8, seq 2716706921, win 64240, options [mss 1460,sackOK,TS val 3379641114 ecr 0,nop,wscale 7], length 0
Process (pid 23592, cmd /usr/bin/curl, args curl https://kernel.org)
User (uid 1000, gid 1000)
ParentProc (pid 6007, cmd /usr/bin/bash, args -bash)
14:40:20.780518 ens33 In IP (tos 0x0, ttl 128, id 7878, offset 0, flags [none], proto TCP (6), length 44)
139.178.84.217.443 > 10.0.2.15.43950: Flags [S.], cksum 0x65a7, seq 676670157, ack 2716706922, win 64240, options [mss 1460], length 0
Process (pid 23592, cmd /usr/bin/curl, args curl https://kernel.org)
User (uid 1000, gid 1000)
ParentProc (pid 6007, cmd /usr/bin/bash, args -bash)
14:40:20.780771 ens33 Out IP (tos 0x0, ttl 64, id 54927, offset 0, flags [DF], proto TCP (6), length 40)
10.0.2.15.43950 > 139.178.84.217.443: Flags [.], cksum 0xecb4, seq 2716706922, ack 676670158, win 64240, length 0
Process (pid 23592, cmd /usr/bin/curl, args curl https://kernel.org)
User (uid 1000, gid 1000)
ParentProc (pid 6007, cmd /usr/bin/bash, args -bash)
14:40:20.790480 ens33 In IP (tos 0x0, ttl 128, id 7880, offset 0, flags [none], proto TCP (6), length 40)
139.178.84.217.443 > 10.0.2.15.43950: Flags [.], cksum 0x7b5f, seq 676670158, ack 2716707439, win 64240, length 0
Process (pid 23592, cmd /usr/bin/curl, args curl https://kernel.org)
User (uid 1000, gid 1000)
ParentProc (pid 6007, cmd /usr/bin/bash, args -bash)
14:40:20.790422 ens33 Out IP (tos 0x0, ttl 64, id 54928, offset 0, flags [DF], proto TCP (6), length 557)
10.0.2.15.43950 > 139.178.84.217.443: Flags [P.], cksum 0xeeb9, seq 2716706922:2716707439, ack 676670158, win 64240, length 517
Process (pid 23592, cmd /usr/bin/curl, args curl https://kernel.org)
User (uid 1000, gid 1000)
ParentProc (pid 6007, cmd /usr/bin/bash, args -bash)
5 changes: 5 additions & 0 deletions testdata/format/curl-user.pcapng.out.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
14:40:20.276349 ens33 curl.23592 Out IP 10.0.2.15.43950 > 139.178.84.217.443: Flags [S], seq 2716706921, win 64240, options [mss 1460,sackOK,TS val 3379641114 ecr 0,nop,wscale 7], length 0, ParentProc [bash.6007]
14:40:20.780518 ens33 curl.23592 In IP 139.178.84.217.443 > 10.0.2.15.43950: Flags [S.], seq 676670157, ack 2716706922, win 64240, options [mss 1460], length 0, ParentProc [bash.6007]
14:40:20.780771 ens33 curl.23592 Out IP 10.0.2.15.43950 > 139.178.84.217.443: Flags [.], seq 2716706922, ack 676670158, win 64240, length 0, ParentProc [bash.6007]
14:40:20.790480 ens33 curl.23592 In IP 139.178.84.217.443 > 10.0.2.15.43950: Flags [.], seq 676670158, ack 2716707439, win 64240, length 0, ParentProc [bash.6007]
14:40:20.790422 ens33 curl.23592 Out IP 10.0.2.15.43950 > 139.178.84.217.443: Flags [P.], seq 2716706922:2716707439, ack 676670158, win 64240, length 517, ParentProc [bash.6007]
2 changes: 1 addition & 1 deletion testdata/test_run_with_docker.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export TMP="/tmp/"
function test_ptcpdump() {
timeout 60s ${CMD} -c 1 -v -i any --print -w "${FNAME}" \
'dst host 1.1.1.1 and tcp[tcpflags] = tcp-syn' | tee "${LNAME}" &
sleep 10
sleep 30
curl -m 10 1.1.1.1 &>/dev/null || true
wait

Expand Down
Loading