Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
3 : : * All rights reserved.
4 : : *
5 : : * Redistribution and use in source and binary forms, with or without
6 : : * modification, are permitted provided that the following conditions
7 : : * are met:
8 : : * 1. Redistributions of source code must retain the above copyright
9 : : * notice, this list of conditions and the following disclaimer.
10 : : * 2. Redistributions in binary form must reproduce the above copyright
11 : : * notice, this list of conditions and the following disclaimer in the
12 : : * documentation and/or other materials provided with the distribution.
13 : : * 3. The name of the author may not be used to endorse or promote products
14 : : * derived from this software without specific prior written permission.
15 : : *
16 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : : */
27 : :
28 : : #include "defs.h"
29 : :
30 : : #ifdef HAVE_LINUX_SECCOMP_H
31 : : # include <linux/seccomp.h>
32 : : #endif
33 : : #include "xlat/seccomp_ops.h"
34 : : #include "xlat/seccomp_filter_flags.h"
35 : :
36 : : #ifdef HAVE_LINUX_FILTER_H
37 : : # include <linux/filter.h>
38 : : # include "xlat/bpf_class.h"
39 : : # include "xlat/bpf_miscop.h"
40 : : # include "xlat/bpf_mode.h"
41 : : # include "xlat/bpf_op_alu.h"
42 : : # include "xlat/bpf_op_jmp.h"
43 : : # include "xlat/bpf_rval.h"
44 : : # include "xlat/bpf_size.h"
45 : : # include "xlat/bpf_src.h"
46 : :
47 : : # ifndef SECCOMP_RET_ACTION
48 : : # define SECCOMP_RET_ACTION 0x7fff0000U
49 : : # endif
50 : : # include "xlat/seccomp_ret_action.h"
51 : : #endif
52 : :
53 : : struct bpf_filter {
54 : : uint16_t code;
55 : : uint8_t jt;
56 : : uint8_t jf;
57 : : uint32_t k;
58 : : };
59 : :
60 : : #ifdef HAVE_LINUX_FILTER_H
61 : :
62 : : static void
63 : 20605 : decode_bpf_code(uint16_t code)
64 : : {
65 : 20605 : uint16_t i = code & ~BPF_CLASS(code);
66 : :
67 : 20605 : printxval(bpf_class, BPF_CLASS(code), "BPF_???");
68 [ + + + + : 20605 : switch (BPF_CLASS(code)) {
+ + - ]
69 : : case BPF_LD:
70 : : case BPF_LDX:
71 : 5130 : tprints("|");
72 : 5130 : printxval(bpf_size, BPF_SIZE(code), "BPF_???");
73 : 5130 : tprints("|");
74 : 5130 : printxval(bpf_mode, BPF_MODE(code), "BPF_???");
75 : 5130 : break;
76 : : case BPF_ST:
77 : : case BPF_STX:
78 [ - + ]: 5120 : if (i)
79 : 0 : tprintf("|%#x /* %s */", i, "BPF_???");
80 : 5120 : break;
81 : : case BPF_ALU:
82 : 2560 : tprints("|");
83 : 2560 : printxval(bpf_src, BPF_SRC(code), "BPF_???");
84 : 2560 : tprints("|");
85 : 2560 : printxval(bpf_op_alu, BPF_OP(code), "BPF_???");
86 : 2560 : break;
87 : : case BPF_JMP:
88 : 2610 : tprints("|");
89 : 2610 : printxval(bpf_src, BPF_SRC(code), "BPF_???");
90 : 2610 : tprints("|");
91 : 2610 : printxval(bpf_op_jmp, BPF_OP(code), "BPF_???");
92 : 2610 : break;
93 : : case BPF_RET:
94 : 2625 : tprints("|");
95 : 2625 : printxval(bpf_rval, BPF_RVAL(code), "BPF_???");
96 : 2625 : i &= ~BPF_RVAL(code);
97 [ - + ]: 2625 : if (i)
98 : 0 : tprintf("|%#x /* %s */", i, "BPF_???");
99 : 2625 : break;
100 : : case BPF_MISC:
101 : 2560 : tprints("|");
102 : 2560 : printxval(bpf_miscop, BPF_MISCOP(code), "BPF_???");
103 : 2560 : i &= ~BPF_MISCOP(code);
104 [ - + ]: 2560 : if (i)
105 : 0 : tprintf("|%#x /* %s */", i, "BPF_???");
106 : 2560 : break;
107 : : }
108 : :
109 : 20605 : }
110 : :
111 : : #endif /* HAVE_LINUX_FILTER_H */
112 : :
113 : : static void
114 : 20555 : decode_bpf_stmt(const struct bpf_filter *filter)
115 : : {
116 : : #ifdef HAVE_LINUX_FILTER_H
117 : 20555 : tprints("BPF_STMT(");
118 : 20555 : decode_bpf_code(filter->code);
119 : 20555 : tprints(", ");
120 [ + + ]: 20555 : if (BPF_CLASS(filter->code) == BPF_RET) {
121 : 2625 : unsigned int action = SECCOMP_RET_ACTION & filter->k;
122 : 2625 : unsigned int data = filter->k & ~action;
123 : :
124 : 2625 : printxval(seccomp_ret_action, action, "SECCOMP_RET_???");
125 [ + + ]: 2625 : if (data)
126 : 20 : tprintf("|%#x)", data);
127 : : else
128 : 2625 : tprints(")");
129 : : } else {
130 : 17930 : tprintf("%#x)", filter->k);
131 : : }
132 : : #else
133 : : tprintf("BPF_STMT(%#x, %#x)", filter->code, filter->k);
134 : : #endif /* HAVE_LINUX_FILTER_H */
135 : 20555 : }
136 : :
137 : : static void
138 : 50 : decode_bpf_jump(const struct bpf_filter *filter)
139 : : {
140 : : #ifdef HAVE_LINUX_FILTER_H
141 : 50 : tprints("BPF_JUMP(");
142 : 50 : decode_bpf_code(filter->code);
143 : 50 : tprintf(", %#x, %#x, %#x)",
144 : 100 : filter->k, filter->jt, filter->jf);
145 : : #else
146 : : tprintf("BPF_JUMP(%#x, %#x, %#x, %#x)",
147 : : filter->code, filter->k, filter->jt, filter->jf);
148 : : #endif /* HAVE_LINUX_FILTER_H */
149 : 50 : }
150 : :
151 : : #ifndef BPF_MAXINSNS
152 : : # define BPF_MAXINSNS 4096
153 : : #endif
154 : :
155 : : static bool
156 : 20610 : print_bpf_filter(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
157 : : {
158 : 20610 : const struct bpf_filter *filter = elem_buf;
159 : 20610 : unsigned int *pn = data;
160 : :
161 [ + + ]: 20610 : if ((*pn)++ >= BPF_MAXINSNS) {
162 : 5 : tprints("...");
163 : 5 : return false;
164 : : }
165 : :
166 [ + - ][ + + ]: 20605 : if (filter->jt || filter->jf)
167 : 50 : decode_bpf_jump(filter);
168 : : else
169 : 20555 : decode_bpf_stmt(filter);
170 : :
171 : 20605 : return true;
172 : : }
173 : :
174 : : void
175 : 40 : print_seccomp_fprog(struct tcb *const tcp, const kernel_ulong_t addr,
176 : : const unsigned short len)
177 : : {
178 [ + + ]: 40 : if (abbrev(tcp)) {
179 : 10 : printaddr(addr);
180 : : } else {
181 : 30 : unsigned int insns = 0;
182 : : struct bpf_filter filter;
183 : :
184 : 30 : print_array(tcp, addr, len, &filter, sizeof(filter),
185 : : umoven_or_printaddr, print_bpf_filter, &insns);
186 : : }
187 : 40 : }
188 : :
189 : : #include "seccomp_fprog.h"
190 : :
191 : : void
192 : 40 : print_seccomp_filter(struct tcb *const tcp, const kernel_ulong_t addr)
193 : : {
194 : : struct seccomp_fprog fprog;
195 : :
196 [ + + ]: 40 : if (fetch_seccomp_fprog(tcp, addr, &fprog)) {
197 : 35 : tprintf("{len=%hu, filter=", fprog.len);
198 : 35 : print_seccomp_fprog(tcp, fprog.filter, fprog.len);
199 : 35 : tprints("}");
200 : : }
201 : 40 : }
202 : :
203 : : static void
204 : 10 : decode_seccomp_set_mode_strict(const unsigned int flags,
205 : : const kernel_ulong_t addr)
206 : : {
207 : 10 : tprintf("%u, ", flags);
208 : 10 : printaddr(addr);
209 : 10 : }
210 : :
211 : 45 : SYS_FUNC(seccomp)
212 : : {
213 : 45 : unsigned int op = tcp->u_arg[0];
214 : :
215 : 45 : printxval(seccomp_ops, op, "SECCOMP_SET_MODE_???");
216 : 45 : tprints(", ");
217 : :
218 [ + + ]: 45 : if (op == SECCOMP_SET_MODE_FILTER) {
219 : 35 : printflags(seccomp_filter_flags, tcp->u_arg[1],
220 : : "SECCOMP_FILTER_FLAG_???");
221 : 35 : tprints(", ");
222 : 35 : print_seccomp_filter(tcp, tcp->u_arg[2]);
223 : : } else {
224 : 10 : decode_seccomp_set_mode_strict(tcp->u_arg[1],
225 : : tcp->u_arg[2]);
226 : : }
227 : :
228 : 45 : return RVAL_DECODED;
229 : : }
|