7
7
package execsnoop
8
8
9
9
import (
10
+ "fmt"
10
11
"os"
11
12
"path/filepath"
13
+ "strings"
14
+ "sync"
12
15
13
16
"github.com/cilium/ebpf"
14
17
"github.com/cilium/ebpf/link"
15
18
"github.com/cilium/ebpf/ringbuf"
16
19
"github.com/cilium/ebpf/rlimit"
17
20
18
21
"github.com/linux-lock/bpflock/bpf/gobpf/bpfevents"
22
+ "github.com/linux-lock/bpflock/bpf/gobpf/bpfprogs"
19
23
20
24
"github.com/linux-lock/bpflock/pkg/components"
21
25
"github.com/linux-lock/bpflock/pkg/defaults"
@@ -66,29 +70,45 @@ type ExecSnoopBpf struct {
66
70
pinPath string
67
71
68
72
args []string
73
+
74
+ attachOnce sync.Once
75
+ destroyOnce sync.Once
76
+ attached bool
77
+ }
78
+
79
+ func init () {
80
+ bpfprogs .Register (bpfProgram , Init )
69
81
}
70
82
71
- func NewBpf () (* ExecSnoopBpf , error ) {
83
+ func Init () (bpfprogs. BpfProg , error ) {
72
84
return & ExecSnoopBpf {
73
85
name : components .ExecSnoop ,
74
- description : "trace process exec()" ,
86
+ description : components . BpfProgDescriptions [ components . ExecSnoop ] ,
75
87
args : make ([]string , 0 ),
76
88
}, nil
77
89
}
78
90
79
- func (e * ExecSnoopBpf ) GetName () string {
91
+ func (e * ExecSnoopBpf ) SetPinPath (pinPath string ) {
92
+ e .pinPath = pinPath
93
+ }
94
+
95
+ func (e * ExecSnoopBpf ) Name () string {
80
96
return e .name
81
97
}
82
98
83
- func (e * ExecSnoopBpf ) GetDescription () string {
99
+ func (e * ExecSnoopBpf ) Description () string {
84
100
return e .description
85
101
}
86
102
103
+ func (e * ExecSnoopBpf ) SetArgs (args []string ) {
104
+ e .args = args
105
+ }
106
+
87
107
func (e * ExecSnoopBpf ) GetArgs () []string {
88
108
return e .args
89
109
}
90
110
91
- func (e * ExecSnoopBpf ) Load (pinPath string ) error {
111
+ func (e * ExecSnoopBpf ) Load () error {
92
112
// Load pre-compiled programs and maps into the kernel.
93
113
objs := bpfObjects {}
94
114
@@ -99,20 +119,28 @@ func (e *ExecSnoopBpf) Load(pinPath string) error {
99
119
100
120
if err := loadBpfObjects (& objs , & ebpf.CollectionOptions {
101
121
Maps : ebpf.MapOptions {
102
- PinPath : pinPath ,
122
+ PinPath : e . pinPath ,
103
123
},
104
124
}); err != nil {
105
125
log .WithError (err ).Errorf ("loading '%s' objects failed" , e .name )
106
126
return err
107
127
}
108
128
109
129
e .objs = objs
110
- e .pinPath = pinPath
111
130
112
131
return nil
113
132
}
114
133
115
- func (e * ExecSnoopBpf ) SetArgs (traceTarget string ) error {
134
+ func (e * ExecSnoopBpf ) setupMaps () error {
135
+ target := ""
136
+
137
+ // We support only one argument for now
138
+ a := strings .Split (e .args [0 ], "=" )
139
+ if len (a ) != 2 {
140
+ return nil
141
+ }
142
+ target = a [1 ]
143
+
116
144
key := uint32 (ExecSnoopTraceTarget )
117
145
path := filepath .Join (e .pinPath , ExecSnoopArgsMap )
118
146
loadOpts := & ebpf.LoadPinOptions {}
@@ -123,7 +151,7 @@ func (e *ExecSnoopBpf) SetArgs(traceTarget string) error {
123
151
return nil
124
152
}
125
153
126
- switch traceTarget {
154
+ switch target {
127
155
case defaults .ExecSnoopByFilter :
128
156
value := uint32 (ExecSnoopTraceByFilter )
129
157
err = m .Put (key , value )
@@ -133,20 +161,38 @@ func (e *ExecSnoopBpf) SetArgs(traceTarget string) error {
133
161
}
134
162
135
163
if err != nil {
136
- log .Warnf ("Execsnoop ignored, updating map '%s' failed: %v" , path , err )
164
+ log .Warnf ("bpf program %s ignored, updating map '%s' failed: %v" , e . Name () , path , err )
137
165
return nil
138
166
}
139
167
140
- e .args = append (e .args , traceTarget )
168
+ return nil
169
+ }
170
+
171
+ func (e * ExecSnoopBpf ) Attach () error {
172
+ if e .attached {
173
+ return nil
174
+ }
175
+
176
+ e .attachOnce .Do (func () {
177
+ err := e .attach ()
178
+ if err != nil {
179
+ log .WithError (err ).Warnf ("attach bpf program '%s' failed" , e .Name ())
180
+ }
181
+ })
182
+
183
+ if e .attached == false {
184
+ return fmt .Errorf ("attach bpf program %s failed" , e .Name ())
185
+ }
141
186
142
187
return nil
143
188
}
144
189
145
- func (e * ExecSnoopBpf ) Attach (target string ) error {
190
+ func (e * ExecSnoopBpf ) attach () error {
191
+ e .attached = true
146
192
tp , err := link .Tracepoint ("syscalls" , "sys_enter_execve" ,
147
193
e .objs .TracepointSyscallsSysEnterExecve )
148
194
if err != nil {
149
- e .Detach ()
195
+ e .Destroy ()
150
196
log .WithError (err ).Errorf ("opening tracepoint 'sys_enter_execve' failed" )
151
197
return err
152
198
}
@@ -156,15 +202,16 @@ func (e *ExecSnoopBpf) Attach(target string) error {
156
202
tp , err = link .Tracepoint ("syscalls" , "sys_exit_execve" ,
157
203
e .objs .TracepointSyscallsSysExitExecve )
158
204
if err != nil {
159
- e .Detach ()
205
+ e .Destroy ()
160
206
log .WithError (err ).Errorf ("opening tracepoint 'sys_exit_execve' failed" )
207
+ return err
161
208
}
162
209
e .sysExitExecve = tp
163
210
164
211
tp , err = link .Tracepoint ("syscalls" , "sys_enter_execveat" ,
165
212
e .objs .TracepointSyscallsSysEnterExecveat )
166
213
if err != nil {
167
- e .Detach ()
214
+ e .Destroy ()
168
215
log .WithError (err ).Errorf ("opening tracepoint 'sys_enter_execveat' failed" )
169
216
return err
170
217
}
@@ -173,22 +220,22 @@ func (e *ExecSnoopBpf) Attach(target string) error {
173
220
tp , err = link .Tracepoint ("syscalls" , "sys_exit_execveat" ,
174
221
e .objs .TracepointSyscallsSysExitExecveat )
175
222
if err != nil {
176
- e .Detach ()
223
+ e .Destroy ()
177
224
log .WithError (err ).Errorf ("opening tracepoint 'sys_exit_execveat' failed" )
178
225
return err
179
226
}
180
227
e .sysExitExecveAt = tp
181
228
182
- err = e .SetArgs ( target )
229
+ err = e .setupMaps ( )
183
230
if err != nil {
184
- e .Detach ()
185
- log .WithError (err ).Errorf ("setArgs () failed" )
231
+ e .Destroy ()
232
+ log .WithError (err ).Errorf ("setupMaps () failed" )
186
233
return err
187
234
}
188
235
189
236
rd , err := ringbuf .NewReader (e .objs .BpflockEvents )
190
237
if err != nil {
191
- e .Detach ()
238
+ e .Destroy ()
192
239
log .WithError (err ).Errorf ("opening ringbuffer reader" )
193
240
return err
194
241
}
@@ -197,23 +244,23 @@ func (e *ExecSnoopBpf) Attach(target string) error {
197
244
return nil
198
245
}
199
246
200
- func (e * ExecSnoopBpf ) GetRingBufferPath () string {
247
+ func (e * ExecSnoopBpf ) GetOutputBufPath () string {
201
248
return filepath .Join (e .pinPath , bpfevents .SharedEvents )
202
249
}
203
250
204
- func (e * ExecSnoopBpf ) GetRingBuffer () * ringbuf.Reader {
251
+ func (e * ExecSnoopBpf ) GetOutputBuf () * ringbuf.Reader {
205
252
return e .ring
206
253
}
207
254
208
- func (e * ExecSnoopBpf ) CloseBuffer () {
255
+ func (e * ExecSnoopBpf ) closeBuffer () {
209
256
if e .ring != nil {
210
257
e .ring .Close ()
211
258
e .ring = nil
212
259
}
213
260
}
214
261
215
- // UnpinLocalMaps removes non shared maps only
216
- func (e * ExecSnoopBpf ) UnpinLocalMaps () {
262
+ // unpinLocalMaps removes non shared maps only
263
+ func (e * ExecSnoopBpf ) unpinLocalMaps () {
217
264
pinnedMap := filepath .Join (e .pinPath , "bpflock_execsnoop_storage" )
218
265
log .Infof ("Cleaning remove bpf-map=%s" , pinnedMap )
219
266
os .RemoveAll (pinnedMap )
@@ -223,7 +270,7 @@ func (e *ExecSnoopBpf) UnpinLocalMaps() {
223
270
os .RemoveAll (pinnedMap )
224
271
}
225
272
226
- func _ExecSnoopCloseLinks (links ... link.Link ) {
273
+ func _execSnoopCloseLinks (links ... link.Link ) {
227
274
for _ , l := range links {
228
275
if l != nil {
229
276
l .Close ()
@@ -233,24 +280,29 @@ func _ExecSnoopCloseLinks(links ...link.Link) {
233
280
}
234
281
235
282
func (e * ExecSnoopBpf ) closeLinks () {
236
- _ExecSnoopCloseLinks (
283
+ _execSnoopCloseLinks (
237
284
e .sysEnterExecve ,
238
285
e .sysEnterExecveAt ,
239
286
e .sysExitExecve ,
240
287
e .sysExitExecveAt ,
241
288
)
242
289
}
243
290
244
- // CloseExecSnoop remove and detach execsnoop resources
245
- func (e * ExecSnoopBpf ) Detach () {
246
- e .CloseBuffer ()
291
+ // Detach remove and detach execsnoop program
292
+ func (e * ExecSnoopBpf ) detach () {
293
+ e .closeBuffer ()
247
294
e .closeLinks ()
248
295
e .objs .Close ()
249
- log .Infof ("Cleaning remove bpf-program=%s" , e .GetName ())
296
+ log .Infof ("Cleaning remove bpf-program=%s" , e .Name ())
250
297
}
251
298
252
- // Clean cleans up everything related to execsnoop and closes ring buffer
299
+ // Destroy cleans up everything related to execsnoop and remove ring buffer
253
300
func (e * ExecSnoopBpf ) Destroy () {
254
- e .Detach ()
255
- e .UnpinLocalMaps ()
301
+ if e .attached {
302
+ e .destroyOnce .Do (func () {
303
+ e .detach ()
304
+ e .unpinLocalMaps ()
305
+ })
306
+ e .attached = false
307
+ }
256
308
}
0 commit comments