Modified gobpf perf.go, change from monitor fchown syscall to socket related syscall, try to read the socket detail like PORT or Addr. For example 'connect' syscall. As I understand the pt_regs* ctx have syscall parameter, I can either use PT_REGS_PARM2 or directly list out, they get samething in my test.
in net/socket.c defined
int __sys_connect(int fd, struct sockaddr __user *uservaddr, int addrlen)
so I expect 1st parameter as socket_fd and second as sockaddr defined in include/linux/socket.h
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
The sa_data is what I wish to read out from kernel and send to userspace.
Below is the kernel part.
#include <uapi/linux/ptrace.h>
#include <bcc/proto.h>
#include <linux/net.h>
typedef struct {
u32 pid;
int fd;
char comm[64];
int ret;
} syscall_event_t;
BPF_PERF_OUTPUT(syscall_events);
BPF_HASH(syscall, u64, syscall_event_t);
int kprobe__sys_fsyscallat(struct pt_regs *ctx, int socket_fd, struct sockaddr *socketadd, int len)
{
u64 pid = bpf_get_current_pid_tgid();
syscall_event_t event = {
.pid = pid >> 32,
.fd = socket_fd,
};
bpf_probe_read(&event.comm,14,(void *)(&(socketadd->sa_data)));
syscall.update(&pid, &event);
return 0;
}
int kretprobe__sys_fsyscallat(struct pt_regs *ctx)
{
int ret = PT_REGS_RC(ctx);
u64 pid = bpf_get_current_pid_tgid();
syscall_event_t *eventp = syscall.lookup(&pid);
if (eventp == 0) {
return 0;
}
syscall_event_t event = *eventp;
event.ret = ret;
syscall_events.perf_submit(ctx, &event, sizeof(event));
syscall.delete(&pid);
return 0;
};
In user space part is just what perf.go do
type syscallEvent struct {
Pid uint32
Socket_fd int32
Filename [64]byte
ReturnValue int32
}
..........................
..........................
go func() {
var event syscallEvent
for {
data := <-channel
err := binary.Read(bytes.NewBuffer(data), binary.LittleEndian, &event)
if err != nil {
fmt.Printf("failed to decode received data: %s
", err)
continue
}
filename := (*C.char)(unsafe.Pointer(&event.Filename))
fmt.Printf("pid %d fd %d sock %s listen (return value: %d)
",
event.Pid, event.Socket_fd, C.GoString(filename),event.ReturnValue)
}
}()
After issue some connect syscall, I didn't get anything related to socket info
$ sudo ./syscall
pid 2024 fd 15859544 sock listen (return value: 0)
I also tried in kenerl part another way to read parameter, with same result.
void * socketin;
int socket_fd = PT_REGS_PARM1(ctx);
socketin = (void *)PT_REGS_PARM2(ctx);
Both fd and sock info not read right. Where my understanding or cod is wrong?
Also tried listen syscall as it defined easier
int __sys_listen(int fd, int backlog)
so just read these two integer by
int socket_fd = PT_REGS_PARM1(ctx);
int pa2 = PT_REGS_PARM2(ctx);
the ouptut indicate they are same , what is it, an address ?
$ sudo ./syscall_socket
pid 3644 fd 15597400 parameter2 15597400 sock listen (return value: 0)