123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- package netlink
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "os"
- "syscall"
- "github.com/vishvananda/netlink/nl"
- "github.com/vishvananda/netns"
- "golang.org/x/sys/unix"
- )
- const CN_IDX_PROC = 0x1
- const (
- PROC_EVENT_NONE = 0x00000000
- PROC_EVENT_FORK = 0x00000001
- PROC_EVENT_EXEC = 0x00000002
- PROC_EVENT_UID = 0x00000004
- PROC_EVENT_GID = 0x00000040
- PROC_EVENT_SID = 0x00000080
- PROC_EVENT_PTRACE = 0x00000100
- PROC_EVENT_COMM = 0x00000200
- PROC_EVENT_COREDUMP = 0x40000000
- PROC_EVENT_EXIT = 0x80000000
- )
- const (
- CN_VAL_PROC = 0x1
- PROC_CN_MCAST_LISTEN = 0x1
- )
- type ProcEventMsg interface {
- Pid() uint32
- Tgid() uint32
- }
- type ProcEventHeader struct {
- What uint32
- CPU uint32
- Timestamp uint64
- }
- type ProcEvent struct {
- ProcEventHeader
- Msg ProcEventMsg
- }
- func (pe *ProcEvent) setHeader(h ProcEventHeader) {
- pe.What = h.What
- pe.CPU = h.CPU
- pe.Timestamp = h.Timestamp
- }
- type ExitProcEvent struct {
- ProcessPid uint32
- ProcessTgid uint32
- ExitCode uint32
- ExitSignal uint32
- ParentPid uint32
- ParentTgid uint32
- }
- type ExitProcEvent2 struct {
- ProcessPid uint32
- ProcessTgid uint32
- ExitCode uint32
- ExitSignal uint32
- ParentPid uint32
- ParentTgid uint32
- }
- func (e *ExitProcEvent) Pid() uint32 {
- return e.ProcessPid
- }
- func (e *ExitProcEvent) Tgid() uint32 {
- return e.ProcessTgid
- }
- type ExecProcEvent struct {
- ProcessPid uint32
- ProcessTgid uint32
- }
- func (e *ExecProcEvent) Pid() uint32 {
- return e.ProcessPid
- }
- func (e *ExecProcEvent) Tgid() uint32 {
- return e.ProcessTgid
- }
- type ForkProcEvent struct {
- ParentPid uint32
- ParentTgid uint32
- ChildPid uint32
- ChildTgid uint32
- }
- func (e *ForkProcEvent) Pid() uint32 {
- return e.ParentPid
- }
- func (e *ForkProcEvent) Tgid() uint32 {
- return e.ParentTgid
- }
- type CommProcEvent struct {
- ProcessPid uint32
- ProcessTgid uint32
- Comm [16]byte
- }
- func (e *CommProcEvent) Pid() uint32 {
- return e.ProcessPid
- }
- func (e *CommProcEvent) Tgid() uint32 {
- return e.ProcessTgid
- }
- func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error {
- h, err := NewHandle()
- if err != nil {
- return err
- }
- defer h.Delete()
- s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC)
- if err != nil {
- return err
- }
- var nlmsg nl.NetlinkRequest
- nlmsg.Pid = uint32(os.Getpid())
- nlmsg.Type = unix.NLMSG_DONE
- nlmsg.Len = uint32(unix.SizeofNlMsghdr)
- cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN)
- nlmsg.AddData(cm)
- s.Send(&nlmsg)
- if done != nil {
- go func() {
- <-done
- s.Close()
- }()
- }
- go func() {
- defer close(ch)
- for {
- msgs, from, err := s.Receive()
- if err != nil {
- errorChan <- err
- return
- }
- if from.Pid != nl.PidKernel {
- errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
- return
- }
- for _, m := range msgs {
- e := parseNetlinkMessage(m)
- if e != nil {
- ch <- *e
- }
- }
- }
- }()
- return nil
- }
- func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent {
- if m.Header.Type == unix.NLMSG_DONE {
- buf := bytes.NewBuffer(m.Data)
- msg := &nl.CnMsg{}
- hdr := &ProcEventHeader{}
- binary.Read(buf, nl.NativeEndian(), msg)
- binary.Read(buf, nl.NativeEndian(), hdr)
- pe := &ProcEvent{}
- pe.setHeader(*hdr)
- switch hdr.What {
- case PROC_EVENT_EXIT:
- event := &ExitProcEvent{}
- binary.Read(buf, nl.NativeEndian(), event)
- pe.Msg = event
- return pe
- case PROC_EVENT_FORK:
- event := &ForkProcEvent{}
- binary.Read(buf, nl.NativeEndian(), event)
- pe.Msg = event
- return pe
- case PROC_EVENT_EXEC:
- event := &ExecProcEvent{}
- binary.Read(buf, nl.NativeEndian(), event)
- pe.Msg = event
- return pe
- case PROC_EVENT_COMM:
- event := &CommProcEvent{}
- binary.Read(buf, nl.NativeEndian(), event)
- pe.Msg = event
- return pe
- }
- return nil
- }
- return nil
- }
|