Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bcc
Commits
5b47e0f8
Commit
5b47e0f8
authored
Jun 02, 2016
by
Mark Drayton
1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
execsnoop: use BPF_PERF_OUTPUT instead of trace pipe
parent
8084f8c1
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
112 additions
and
84 deletions
+112
-84
tools/execsnoop.py
tools/execsnoop.py
+112
-84
No files found.
tools/execsnoop.py
View file @
5b47e0f8
...
...
@@ -19,7 +19,10 @@
from
__future__
import
print_function
from
bcc
import
BPF
import
argparse
import
ctypes
as
ct
import
re
import
time
from
collections
import
defaultdict
# arguments
examples
=
"""examples:
...
...
@@ -47,65 +50,91 @@ bpf_text = """
#include <linux/fs.h>
#define MAXARG 20
#define ARGSIZE
64
#define ARGSIZE
128
static int print_arg(void *ptr) {
// Fetch an argument, and print using bpf_trace_printk(). This is a work
// around until we have a binary trace interface for passing event data to
// bcc. Since exec()s should be low frequency, the additional overhead in
// this case should not be a problem.
const char *argp = NULL;
char buf[ARGSIZE] = {};
enum event_type {
EVENT_ARG,
EVENT_RET,
};
bpf_probe_read(&argp, sizeof(argp), ptr);
if (argp == NULL) return 0;
struct data_t {
u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel)
char comm[TASK_COMM_LEN];
enum event_type type;
char argv[ARGSIZE];
int retval;
};
bpf_probe_read(&buf, sizeof(buf), (void *)(argp));
bpf_trace_printk("ARG %s
\
\
n", buf);
BPF_PERF_OUTPUT(events);
static int __submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data)
{
bpf_probe_read(data->argv, sizeof(data->argv), ptr);
events.perf_submit(ctx, data, sizeof(struct data_t));
return 1;
}
static int submit_arg(struct pt_regs *ctx, void *ptr, struct data_t *data)
{
const char *argp = NULL;
bpf_probe_read(&argp, sizeof(argp), ptr);
if (argp) {
return __submit_arg(ctx, (void *)(argp), data);
}
return 0;
}
int kprobe__sys_execve(struct pt_regs *ctx, struct filename *filename,
const char __user *const __user *__argv,
const char __user *const __user *__envp)
{
char fname[ARGSIZE] = {};
bpf_probe_read(&fname, sizeof(fname), (void *)(filename));
bpf_trace_printk("ARG %s
\
\
n", fname);
// create data here and pass to submit_arg to save space on the stack (#555)
struct data_t data = {};
data.pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&data.comm, sizeof(data.comm));
data.type = EVENT_ARG;
int i = 1; // skip first arg, as we printed fname
__submit_arg(ctx, (void *)filename, &data);
// unrolled loop to walk argv[] (MAXARG)
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++; // X
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++;
if (print_arg((void *)&__argv[i]) == 0) goto out; i++; // XX
bpf_trace_printk("ARG ...
\
\
n"); // truncated
int i = 1; // skip first arg, as we submitted filename
// unrolled loop to walk argv[] (MAXARG)
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++; // X
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++;
if (submit_arg(ctx, (void *)&__argv[i], &data) == 0) goto out; i++; // XX
// handle truncated argument list
char ellipsis[] = "...";
__submit_arg(ctx, (void *)ellipsis, &data);
out:
return 0;
}
int kretprobe__sys_execve(struct pt_regs *ctx)
{
bpf_trace_printk("RET %d
\
\
n", PT_REGS_RC(ctx));
struct data_t data = {};
data.pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&data.comm, sizeof(data.comm));
data.type = EVENT_RET;
data.retval = PT_REGS_RC(ctx);
events.perf_submit(ctx, &data, sizeof(data));
return 0;
}
"""
...
...
@@ -118,49 +147,48 @@ if args.timestamp:
print
(
"%-8s"
%
(
"TIME(s)"
),
end
=
""
)
print
(
"%-16s %-6s %3s %s"
%
(
"PCOMM"
,
"PID"
,
"RET"
,
"ARGS"
))
start_ts
=
0
cmd
=
{}
pcomm
=
{}
# format output
TASK_COMM_LEN
=
16
# linux/sched.h
ARGSIZE
=
128
# should match #define in C above
class
Data
(
ct
.
Structure
):
_fields_
=
[
(
"pid"
,
ct
.
c_uint
),
(
"comm"
,
ct
.
c_char
*
TASK_COMM_LEN
),
(
"type"
,
ct
.
c_int
),
(
"argv"
,
ct
.
c_char
*
ARGSIZE
),
(
"retval"
,
ct
.
c_int
),
]
class
EventType
(
object
):
EVENT_ARG
=
0
EVENT_RET
=
1
start_ts
=
time
.
time
()
argv
=
defaultdict
(
list
)
# process event
def
print_event
(
cpu
,
data
,
size
):
event
=
ct
.
cast
(
data
,
ct
.
POINTER
(
Data
)).
contents
skip
=
False
if
event
.
type
==
EventType
.
EVENT_ARG
:
argv
[
event
.
pid
].
append
(
event
.
argv
)
elif
event
.
type
==
EventType
.
EVENT_RET
:
if
args
.
fails
and
event
.
retval
==
0
:
skip
=
True
if
args
.
name
and
not
re
.
search
(
args
.
name
,
event
.
comm
):
skip
=
True
if
not
skip
:
if
args
.
timestamp
:
print
(
"%-8.3f"
%
(
time
.
time
()
-
start_ts
),
end
=
""
)
print
(
"%-16s %-6s %3s %s"
%
(
event
.
comm
,
event
.
pid
,
event
.
retval
,
' '
.
join
(
argv
[
event
.
pid
])))
del
(
argv
[
event
.
pid
])
# loop with callback to print_event
b
[
"events"
].
open_perf_buffer
(
print_event
)
while
1
:
(
task
,
pid
,
cpu
,
flags
,
ts
,
msg
)
=
b
.
trace_fields
()
try
:
(
type
,
arg
)
=
msg
.
split
(
" "
,
1
)
except
ValueError
:
continue
if
start_ts
==
0
:
start_ts
=
ts
if
type
==
"RET"
:
if
pid
not
in
cmd
:
# zero args
cmd
[
pid
]
=
""
pcomm
[
pid
]
=
""
skip
=
0
if
args
.
name
:
if
not
re
.
search
(
args
.
name
,
cmd
[
pid
]):
skip
=
1
if
not
args
.
fails
and
int
(
arg
)
<
0
:
skip
=
1
if
skip
:
del
cmd
[
pid
]
del
pcomm
[
pid
]
continue
# output
if
args
.
timestamp
:
print
(
"%-8.3f"
%
(
ts
-
start_ts
),
end
=
""
)
print
(
"%-16s %-6s %3s %s"
%
(
pcomm
[
pid
],
pid
,
arg
,
cmd
[
pid
]))
del
cmd
[
pid
]
del
pcomm
[
pid
]
else
:
# build command line string
if
pid
in
cmd
:
cmd
[
pid
]
=
cmd
[
pid
]
+
" "
+
arg
else
:
cmd
[
pid
]
=
arg
if
pid
not
in
pcomm
:
pcomm
[
pid
]
=
task
b
.
kprobe_poll
()
Kirill Smelkov
@kirr
mentioned in commit
3514bb12
·
Sep 26, 2017
mentioned in commit
3514bb12
mentioned in commit 3514bb125a41a4229258c8bb442ec3d96d759786
Toggle commit list
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment