4 * Copyright (c) 2012 Red Hat <pmoore@redhat.com>
5 * Author: Paul Moore <paul@paul-moore.com>
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of version 2.1 of the GNU Lesser General Public License as
11 * published by the Free Software Foundation.
13 * This library is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, see <http://www.gnu.org/licenses>.
31 #include <linux/audit.h>
32 #include <sys/types.h>
38 #define _OP_FMT "%-3s"
41 * Print the usage information to stderr and exit
42 * @param program the name of the current program being invoked
44 * Print the usage information and exit with EINVAL.
47 static void exit_usage(const char *program
)
49 fprintf(stderr
, "usage: %s -a <arch> [-d] [-h]\n", program
);
54 * Decode the BPF operand
55 * @param bpf the BPF instruction
57 * Decode the BPF operand and print it to stdout.
60 static const char *bpf_decode_op(const bpf_instr_raw
*bpf
)
63 case BPF_LD
+BPF_W
+BPF_IMM
:
64 case BPF_LD
+BPF_W
+BPF_ABS
:
65 case BPF_LD
+BPF_W
+BPF_IND
:
66 case BPF_LD
+BPF_W
+BPF_MEM
:
67 case BPF_LD
+BPF_W
+BPF_LEN
:
68 case BPF_LD
+BPF_W
+BPF_MSH
:
70 case BPF_LD
+BPF_H
+BPF_IMM
:
71 case BPF_LD
+BPF_H
+BPF_ABS
:
72 case BPF_LD
+BPF_H
+BPF_IND
:
73 case BPF_LD
+BPF_H
+BPF_MEM
:
74 case BPF_LD
+BPF_H
+BPF_LEN
:
75 case BPF_LD
+BPF_H
+BPF_MSH
:
77 case BPF_LD
+BPF_B
+BPF_IMM
:
78 case BPF_LD
+BPF_B
+BPF_ABS
:
79 case BPF_LD
+BPF_B
+BPF_IND
:
80 case BPF_LD
+BPF_B
+BPF_MEM
:
81 case BPF_LD
+BPF_B
+BPF_LEN
:
82 case BPF_LD
+BPF_B
+BPF_MSH
:
84 case BPF_LDX
+BPF_W
+BPF_IMM
:
85 case BPF_LDX
+BPF_W
+BPF_ABS
:
86 case BPF_LDX
+BPF_W
+BPF_IND
:
87 case BPF_LDX
+BPF_W
+BPF_MEM
:
88 case BPF_LDX
+BPF_W
+BPF_LEN
:
89 case BPF_LDX
+BPF_W
+BPF_MSH
:
90 case BPF_LDX
+BPF_H
+BPF_IMM
:
91 case BPF_LDX
+BPF_H
+BPF_ABS
:
92 case BPF_LDX
+BPF_H
+BPF_IND
:
93 case BPF_LDX
+BPF_H
+BPF_MEM
:
94 case BPF_LDX
+BPF_H
+BPF_LEN
:
95 case BPF_LDX
+BPF_H
+BPF_MSH
:
96 case BPF_LDX
+BPF_B
+BPF_IMM
:
97 case BPF_LDX
+BPF_B
+BPF_ABS
:
98 case BPF_LDX
+BPF_B
+BPF_IND
:
99 case BPF_LDX
+BPF_B
+BPF_MEM
:
100 case BPF_LDX
+BPF_B
+BPF_LEN
:
101 case BPF_LDX
+BPF_B
+BPF_MSH
:
107 case BPF_ALU
+BPF_ADD
+BPF_K
:
108 case BPF_ALU
+BPF_ADD
+BPF_X
:
110 case BPF_ALU
+BPF_SUB
+BPF_K
:
111 case BPF_ALU
+BPF_SUB
+BPF_X
:
113 case BPF_ALU
+BPF_MUL
+BPF_K
:
114 case BPF_ALU
+BPF_MUL
+BPF_X
:
116 case BPF_ALU
+BPF_DIV
+BPF_K
:
117 case BPF_ALU
+BPF_DIV
+BPF_X
:
119 case BPF_ALU
+BPF_OR
+BPF_K
:
120 case BPF_ALU
+BPF_OR
+BPF_X
:
122 case BPF_ALU
+BPF_AND
+BPF_K
:
123 case BPF_ALU
+BPF_AND
+BPF_X
:
125 case BPF_ALU
+BPF_LSH
+BPF_K
:
126 case BPF_ALU
+BPF_LSH
+BPF_X
:
128 case BPF_ALU
+BPF_RSH
+BPF_K
:
129 case BPF_ALU
+BPF_RSH
+BPF_X
:
131 case BPF_ALU
+BPF_NEG
+BPF_K
:
132 case BPF_ALU
+BPF_NEG
+BPF_X
:
134 case BPF_JMP
+BPF_JA
+BPF_K
:
135 case BPF_JMP
+BPF_JA
+BPF_X
:
137 case BPF_JMP
+BPF_JEQ
+BPF_K
:
138 case BPF_JMP
+BPF_JEQ
+BPF_X
:
140 case BPF_JMP
+BPF_JGT
+BPF_K
:
141 case BPF_JMP
+BPF_JGT
+BPF_X
:
143 case BPF_JMP
+BPF_JGE
+BPF_K
:
144 case BPF_JMP
+BPF_JGE
+BPF_X
:
146 case BPF_JMP
+BPF_JSET
+BPF_K
:
147 case BPF_JMP
+BPF_JSET
+BPF_X
:
153 case BPF_MISC
+BPF_TAX
:
155 case BPF_MISC
+BPF_TXA
:
162 * Decode a RET action
163 * @param k the return action
165 * Decode the action and print it to stdout.
168 static void bpf_decode_action(uint32_t k
)
170 uint32_t act
= k
& SECCOMP_RET_ACTION
;
171 uint32_t data
= k
& SECCOMP_RET_DATA
;
174 case SECCOMP_RET_KILL
:
177 case SECCOMP_RET_TRAP
:
180 case SECCOMP_RET_ERRNO
:
181 printf("ERRNO(%u)", data
);
183 case SECCOMP_RET_TRACE
:
184 printf("TRACE(%u)", data
);
186 case SECCOMP_RET_ALLOW
:
195 * Decode the BPF arguments (JT, JF, and K)
196 * @param bpf the BPF instruction
197 * @param line the current line number
199 * Decode the BPF arguments (JT, JF, and K) and print the relevant information
200 * to stdout based on the operand.
203 static void bpf_decode_args(const bpf_instr_raw
*bpf
, unsigned int line
)
205 switch (BPF_CLASS(bpf
->code
)) {
208 switch (BPF_MODE(bpf
->code
)) {
210 printf("$data[%u]", bpf
->k
);
213 printf("$temp[%u]", bpf
->k
);
216 printf("%u", bpf
->k
);
219 printf("$data[X + %u]", bpf
->k
);
222 printf("len($data)");
225 printf("4 * $data[%u] & 0x0f", bpf
->k
);
231 printf("$temp[%u]", bpf
->k
);
234 if (BPF_SRC(bpf
->code
) == BPF_K
) {
235 switch (BPF_OP(bpf
->code
)) {
238 printf("0x%.8x", bpf
->k
);
241 printf("%u", bpf
->k
);
244 printf("%u", bpf
->k
);
247 if (BPF_OP(bpf
->code
) == BPF_JA
) {
248 printf("%.4u", (line
+ 1) + bpf
->k
);
250 printf("%-4u true:%.4u false:%.4u",
252 (line
+ 1) + bpf
->jt
,
253 (line
+ 1) + bpf
->jf
);
257 if (BPF_RVAL(bpf
->code
) == BPF_A
) {
258 /* XXX - accumulator? */
260 } else if (BPF_SRC(bpf
->code
) == BPF_K
) {
261 bpf_decode_action(bpf
->k
);
262 } else if (BPF_SRC(bpf
->code
) == BPF_X
) {
263 /* XXX - any idea? */
275 * Perform a simple decoding of the BPF program
276 * @param file the BPF program
278 * Read the BPF program and display the instructions. Returns zero on success,
279 * negative values on failure.
282 static int bpf_decode(FILE *file
)
284 unsigned int line
= 0;
289 printf(" line OP JT JF K\n");
290 printf("=================================\n");
292 while ((len
= fread(&bpf
, sizeof(bpf
), 1, file
))) {
293 /* convert the bpf statement */
294 bpf
.code
= ttoh16(arch
, bpf
.code
);
295 bpf
.k
= ttoh32(arch
, bpf
.k
);
297 /* display a hex dump */
298 printf(" %.4u: 0x%.2x 0x%.2x 0x%.2x 0x%.8x",
299 line
, bpf
.code
, bpf
.jt
, bpf
.jf
, bpf
.k
);
301 /* display the assembler statements */
303 printf(_OP_FMT
, bpf_decode_op(&bpf
));
305 bpf_decode_args(&bpf
, line
);
317 * Decode the BPF arguments (JT, JF, and K)
318 * @param bpf the BPF instruction
319 * @param line the current line number
321 * Decode the BPF arguments (JT, JF, and K) and print the relevant information
322 * to stdout based on the operand.
325 static void bpf_dot_decode_args(const bpf_instr_raw
*bpf
, unsigned int line
)
327 const char *op
= bpf_decode_op(bpf
);
329 printf("\tline%d[label=\"%s", line
, op
);
330 switch (BPF_CLASS(bpf
->code
)) {
333 switch (BPF_MODE(bpf
->code
)) {
335 printf(" $data[%u]\",shape=parallelogram]\n", bpf
->k
);
338 printf(" $temp[%u]\",shape=parallelogram]\n", bpf
->k
);
341 printf(" %u\",shape=parallelogram]\n", bpf
->k
);
344 printf(" $data[X + %u]\",shape=parallelogram]\n", bpf
->k
);
347 printf(" len($data)\",shape=parallelogram]\n");
350 printf(" 4 * $data[%u] & 0x0f\",shape=parallelogram]\n", bpf
->k
);
356 printf(" $temp[%u]\",shape=parallelogram]\n",
360 if (BPF_SRC(bpf
->code
) == BPF_K
) {
361 switch (BPF_OP(bpf
->code
)) {
364 printf(" 0x%.8x\",shape=rectangle]\n", bpf
->k
);
367 printf(" %u\",shape=rectangle]\n", bpf
->k
);
370 printf(" %u\",shape=rectangle]\n", bpf
->k
);
373 if (BPF_OP(bpf
->code
) == BPF_JA
) {
374 printf("\",shape=hexagon]\n");
375 printf("\tline%d -> line%d\n",
376 line
, (line
+ 1) + bpf
->k
);
378 printf(" %-4u", bpf
->k
);
379 /* Heuristic: if k > 256, also emit hex version */
381 printf("\\n(0x%.8x)", bpf
->k
);
382 printf("\",shape=diamond]\n");
383 printf("\tline%d -> line%d [label=\"true\"]\n",
384 line
, (line
+ 1) + bpf
->jt
);
385 printf("\tline%d -> line%d [label=\"false\"]\n",
386 line
, (line
+ 1) + bpf
->jf
);
390 if (BPF_RVAL(bpf
->code
) == BPF_A
) {
391 /* XXX - accumulator? */
392 printf(" $acc\", shape=\"box\", style=rounded]\n");
393 } else if (BPF_SRC(bpf
->code
) == BPF_K
) {
395 bpf_decode_action(bpf
->k
);
396 printf("\", shape=\"box\", style=rounded]\n");
397 } else if (BPF_SRC(bpf
->code
) == BPF_X
) {
398 /* XXX - any idea? */
399 printf(" ???\", shape=\"box\", style=rounded]\n");
411 * Perform a simple decoding of the BPF program to a dot graph
412 * @param file the BPF program
414 * Read the BPF program and display the instructions. Returns zero on success,
415 * negative values on failure.
418 static int bpf_dot_decode(FILE *file
)
420 unsigned int line
= 0;
426 printf("digraph {\n");
427 printf("\tstart[shape=\"box\", style=rounded];\n");
429 while ((len
= fread(&bpf
, sizeof(bpf
), 1, file
))) {
430 /* convert the bpf statement */
431 bpf
.code
= ttoh16(arch
, bpf
.code
);
432 bpf
.k
= ttoh32(arch
, bpf
.k
);
434 /* display the statement */
435 bpf_dot_decode_args(&bpf
, line
);
437 /* if previous line wasn't RET/JMP, link it to this line */
439 printf("\tstart -> line%d\n", line
);
440 else if ((prev_class
!= BPF_JMP
) && (prev_class
!= BPF_RET
))
441 printf("\tline%d -> line%d\n", line
- 1, line
);
442 prev_class
= BPF_CLASS(bpf
.code
);
456 int main(int argc
, char *argv
[])
460 bool dot_out
= false;
463 /* parse the command line */
464 while ((opt
= getopt(argc
, argv
, "a:dh")) > 0) {
467 if (strcmp(optarg
, "x86") == 0)
468 arch
= AUDIT_ARCH_I386
;
469 else if (strcmp(optarg
, "x86_64") == 0)
470 arch
= AUDIT_ARCH_X86_64
;
471 else if (strcmp(optarg
, "x32") == 0)
472 arch
= AUDIT_ARCH_X86_64
;
473 else if (strcmp(optarg
, "arm") == 0)
474 arch
= AUDIT_ARCH_ARM
;
475 else if (strcmp(optarg
, "aarch64") == 0)
476 arch
= AUDIT_ARCH_AARCH64
;
477 else if (strcmp(optarg
, "mips") == 0)
478 arch
= AUDIT_ARCH_MIPS
;
479 else if (strcmp(optarg
, "mipsel") == 0)
480 arch
= AUDIT_ARCH_MIPSEL
;
481 else if (strcmp(optarg
, "mips64") == 0)
482 arch
= AUDIT_ARCH_MIPS64
;
483 else if (strcmp(optarg
, "mipsel64") == 0)
484 arch
= AUDIT_ARCH_MIPSEL64
;
485 else if (strcmp(optarg
, "mips64n32") == 0)
486 arch
= AUDIT_ARCH_MIPS64N32
;
487 else if (strcmp(optarg
, "mipsel64n32") == 0)
488 arch
= AUDIT_ARCH_MIPSEL64N32
;
489 else if (strcmp(optarg
, "ppc64") == 0)
490 arch
= AUDIT_ARCH_PPC64
;
491 else if (strcmp(optarg
, "ppc64le") == 0)
492 arch
= AUDIT_ARCH_PPC64LE
;
493 else if (strcmp(optarg
, "ppc") == 0)
494 arch
= AUDIT_ARCH_PPC
;
495 else if (strcmp(optarg
, "s390") == 0)
496 arch
= AUDIT_ARCH_S390
;
497 else if (strcmp(optarg
, "s390x") == 0)
498 arch
= AUDIT_ARCH_S390X
;
506 /* usage information */
511 if ((optind
> 1) && (optind
< argc
)) {
512 int opt_file
= optind
- 1 ;
513 file
= fopen(argv
[opt_file
], "r");
515 fprintf(stderr
, "error: unable to open \"%s\" (%s)\n",
516 argv
[opt_file
], strerror(errno
));
523 rc
= bpf_dot_decode(file
);
525 rc
= bpf_decode(file
);
This page took 0.037658 seconds and 4 git commands to generate.