proc_event_linux.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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. func (e *ExitProcEvent) Pid() uint32 {
  56. return e.ProcessPid
  57. }
  58. func (e *ExitProcEvent) Tgid() uint32 {
  59. return e.ProcessTgid
  60. }
  61. type ExecProcEvent struct {
  62. ProcessPid uint32
  63. ProcessTgid uint32
  64. }
  65. func (e *ExecProcEvent) Pid() uint32 {
  66. return e.ProcessPid
  67. }
  68. func (e *ExecProcEvent) Tgid() uint32 {
  69. return e.ProcessTgid
  70. }
  71. type ForkProcEvent struct {
  72. ParentPid uint32
  73. ParentTgid uint32
  74. ChildPid uint32
  75. ChildTgid uint32
  76. }
  77. func (e *ForkProcEvent) Pid() uint32 {
  78. return e.ParentPid
  79. }
  80. func (e *ForkProcEvent) Tgid() uint32 {
  81. return e.ParentTgid
  82. }
  83. type CommProcEvent struct {
  84. ProcessPid uint32
  85. ProcessTgid uint32
  86. Comm [16]byte
  87. }
  88. func (e *CommProcEvent) Pid() uint32 {
  89. return e.ProcessPid
  90. }
  91. func (e *CommProcEvent) Tgid() uint32 {
  92. return e.ProcessTgid
  93. }
  94. func ProcEventMonitor(ch chan<- ProcEvent, done <-chan struct{}, errorChan chan<- error) error {
  95. h, err := NewHandle()
  96. if err != nil {
  97. return err
  98. }
  99. defer h.Delete()
  100. s, err := nl.SubscribeAt(netns.None(), netns.None(), unix.NETLINK_CONNECTOR, CN_IDX_PROC)
  101. if err != nil {
  102. return err
  103. }
  104. var nlmsg nl.NetlinkRequest
  105. nlmsg.Pid = uint32(os.Getpid())
  106. nlmsg.Type = unix.NLMSG_DONE
  107. nlmsg.Len = uint32(unix.SizeofNlMsghdr)
  108. cm := nl.NewCnMsg(CN_IDX_PROC, CN_VAL_PROC, PROC_CN_MCAST_LISTEN)
  109. nlmsg.AddData(cm)
  110. s.Send(&nlmsg)
  111. if done != nil {
  112. go func() {
  113. <-done
  114. s.Close()
  115. }()
  116. }
  117. go func() {
  118. defer close(ch)
  119. for {
  120. msgs, from, err := s.Receive()
  121. if err != nil {
  122. errorChan <- err
  123. return
  124. }
  125. if from.Pid != nl.PidKernel {
  126. errorChan <- fmt.Errorf("Wrong sender portid %d, expected %d", from.Pid, nl.PidKernel)
  127. return
  128. }
  129. for _, m := range msgs {
  130. e := parseNetlinkMessage(m)
  131. if e != nil {
  132. ch <- *e
  133. }
  134. }
  135. }
  136. }()
  137. return nil
  138. }
  139. func parseNetlinkMessage(m syscall.NetlinkMessage) *ProcEvent {
  140. if m.Header.Type == unix.NLMSG_DONE {
  141. buf := bytes.NewBuffer(m.Data)
  142. msg := &nl.CnMsg{}
  143. hdr := &ProcEventHeader{}
  144. binary.Read(buf, nl.NativeEndian(), msg)
  145. binary.Read(buf, nl.NativeEndian(), hdr)
  146. pe := &ProcEvent{}
  147. pe.setHeader(*hdr)
  148. switch hdr.What {
  149. case PROC_EVENT_EXIT:
  150. event := &ExitProcEvent{}
  151. binary.Read(buf, nl.NativeEndian(), event)
  152. pe.Msg = event
  153. return pe
  154. case PROC_EVENT_FORK:
  155. event := &ForkProcEvent{}
  156. binary.Read(buf, nl.NativeEndian(), event)
  157. pe.Msg = event
  158. return pe
  159. case PROC_EVENT_EXEC:
  160. event := &ExecProcEvent{}
  161. binary.Read(buf, nl.NativeEndian(), event)
  162. pe.Msg = event
  163. return pe
  164. case PROC_EVENT_COMM:
  165. event := &CommProcEvent{}
  166. binary.Read(buf, nl.NativeEndian(), event)
  167. pe.Msg = event
  168. return pe
  169. }
  170. return nil
  171. }
  172. return nil
  173. }