github.com/vishvananda/netlink@v1.3.0/proc_event_linux.go (about) 1 package netlink 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "os" 8 "syscall" 9 10 "github.com/vishvananda/netlink/nl" 11 "github.com/vishvananda/netns" 12 "golang.org/x/sys/unix" 13 ) 14 15 const CN_IDX_PROC = 0x1 16 17 const ( 18 PROC_EVENT_NONE = 0x00000000 19 PROC_EVENT_FORK = 0x00000001 20 PROC_EVENT_EXEC = 0x00000002 21 PROC_EVENT_UID = 0x00000004 22 PROC_EVENT_GID = 0x00000040 23 PROC_EVENT_SID = 0x00000080 24 PROC_EVENT_PTRACE = 0x00000100 25 PROC_EVENT_COMM = 0x00000200 26 PROC_EVENT_COREDUMP = 0x40000000 27 PROC_EVENT_EXIT = 0x80000000 28 ) 29 30 const ( 31 CN_VAL_PROC = 0x1 32 PROC_CN_MCAST_LISTEN = 0x1 33 ) 34 35 type ProcEventMsg interface { 36 Pid() uint32 37 Tgid() uint32 38 } 39 40 type ProcEventHeader struct { 41 What uint32 42 CPU uint32 43 Timestamp uint64 44 } 45 46 type ProcEvent struct { 47 ProcEventHeader 48 Msg ProcEventMsg 49 } 50 51 func (pe *ProcEvent) setHeader(h ProcEventHeader) { 52 pe.What = h.What 53 pe.CPU = h.CPU 54 pe.Timestamp = h.Timestamp 55 } 56 57 type ExitProcEvent struct { 58 ProcessPid uint32 59 ProcessTgid uint32 60 ExitCode uint32 61 ExitSignal uint32 62 ParentPid uint32 63 ParentTgid uint32 64 } 65 66 func (e *ExitProcEvent) Pid() uint32 { 67 return e.ProcessPid 68 } 69 70 func (e *ExitProcEvent) Tgid() uint32 { 71 return e.ProcessTgid 72 } 73 74 type ExecProcEvent struct { 75 ProcessPid uint32 76 ProcessTgid uint32 77 } 78 79 func (e *ExecProcEvent) Pid() uint32 { 80 return e.ProcessPid 81 } 82 83 func (e *ExecProcEvent) Tgid() uint32 { 84 return e.ProcessTgid 85 } 86 87 type ForkProcEvent struct { 88 ParentPid uint32 89 ParentTgid uint32 90 ChildPid uint32 91 ChildTgid uint32 92 } 93 94 func (e *ForkProcEvent) Pid() uint32 { 95 return e.ParentPid 96 } 97 98 func (e *ForkProcEvent) Tgid() uint32 { 99 return e.ParentTgid 100 } 101 102 type CommProcEvent struct { 103 ProcessPid uint32 104 ProcessTgid uint32 105 Comm [16]byte 106 } 107 108 func (e *CommProcEvent) Pid() uint32 { 109 return e.ProcessPid 110 } 111 112 func (e *CommProcEvent) Tgid() uint32 { 113 return e.ProcessTgid 114 } 115 116 func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error { 117 h, err := NewHandle() 118 if err != nil { 119 return err 120 } 121 defer h.Delete() 122 123 s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC) 124 if err != nil { 125 return err 126 } 127 128 var nlmsg nl.NetlinkRequest 129 130 nlmsg.Pid = uint32(os.Getpid()) 131 nlmsg.Type = unix.NLMSG_DONE 132 nlmsg.Len = uint32(unix.SizeofNlMsghdr) 133 134 cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN) 135 nlmsg.AddData(cm) 136 137 s.Send(&nlmsg) 138 139 if done != nil { 140 go func() { 141 <-done 142 s.Close() 143 }() 144 } 145 146 go func() { 147 defer close(ch) 148 for { 149 msgs, from, err := s.Receive() 150 if err != nil { 151 errorChan <- err 152 return 153 } 154 if from.Pid != nl.PidKernel { 155 errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel) 156 return 157 } 158 159 for _, m := range msgs { 160 e := parseNetlinkMessage(m) 161 if e != nil { 162 ch <- *e 163 } 164 } 165 166 } 167 }() 168 169 return nil 170 } 171 172 func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent { 173 if m.Header.Type == unix.NLMSG_DONE { 174 buf := bytes.NewBuffer(m.Data) 175 msg := &nl.CnMsg{} 176 hdr := &ProcEventHeader{} 177 binary.Read(buf, nl.NativeEndian(), msg) 178 binary.Read(buf, nl.NativeEndian(), hdr) 179 180 pe := &ProcEvent{} 181 pe.setHeader(*hdr) 182 switch hdr.What { 183 case PROC_EVENT_EXIT: 184 event := &ExitProcEvent{} 185 binary.Read(buf, nl.NativeEndian(), event) 186 pe.Msg = event 187 return pe 188 case PROC_EVENT_FORK: 189 event := &ForkProcEvent{} 190 binary.Read(buf, nl.NativeEndian(), event) 191 pe.Msg = event 192 return pe 193 case PROC_EVENT_EXEC: 194 event := &ExecProcEvent{} 195 binary.Read(buf, nl.NativeEndian(), event) 196 pe.Msg = event 197 return pe 198 case PROC_EVENT_COMM: 199 event := &CommProcEvent{} 200 binary.Read(buf, nl.NativeEndian(), event) 201 pe.Msg = event 202 return pe 203 } 204 return nil 205 } 206 207 return nil 208 }