proc_event_linux.go 3.8 KB

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