diff options
| author | Josef Bacik <jbacik@fb.com> | 2016-09-28 10:54:32 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2016-09-29 01:35:35 -0400 |
| commit | 484611357c19f9e19ef742ebef4505a07d243cc9 (patch) | |
| tree | 34f14c2b2ac71d0bf0a53cab096960e7c91ae87f /samples | |
| parent | 7836667cec5e02ed2ae3eb09b88047b5b5f2343a (diff) | |
bpf: allow access into map value arrays
Suppose you have a map array value that is something like this
struct foo {
unsigned iter;
int array[SOME_CONSTANT];
};
You can easily insert this into an array, but you cannot modify the contents of
foo->array[] after the fact. This is because we have no way to verify we won't
go off the end of the array at verification time. This patch provides a start
for this work. We accomplish this by keeping track of a minimum and maximum
value a register could be while we're checking the code. Then at the time we
try to do an access into a MAP_VALUE we verify that the maximum offset into that
region is a valid access into that memory region. So in practice, code such as
this
unsigned index = 0;
if (foo->iter >= SOME_CONSTANT)
foo->iter = index;
else
index = foo->iter++;
foo->array[index] = bar;
would be allowed, as we can verify that index will always be between 0 and
SOME_CONSTANT-1. If you wish to use signed values you'll have to have an extra
check to make sure the index isn't less than 0, or do something like index %=
SOME_CONSTANT.
Signed-off-by: Josef Bacik <jbacik@fb.com>
Acked-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'samples')
| -rw-r--r-- | samples/bpf/libbpf.h | 8 | ||||
| -rw-r--r-- | samples/bpf/test_verifier.c | 243 |
2 files changed, 247 insertions, 4 deletions
diff --git a/samples/bpf/libbpf.h b/samples/bpf/libbpf.h index 364582b77888..ac6edb61b64a 100644 --- a/samples/bpf/libbpf.h +++ b/samples/bpf/libbpf.h | |||
| @@ -85,6 +85,14 @@ extern char bpf_log_buf[LOG_BUF_SIZE]; | |||
| 85 | .off = 0, \ | 85 | .off = 0, \ |
| 86 | .imm = IMM }) | 86 | .imm = IMM }) |
| 87 | 87 | ||
| 88 | #define BPF_MOV32_IMM(DST, IMM) \ | ||
| 89 | ((struct bpf_insn) { \ | ||
| 90 | .code = BPF_ALU | BPF_MOV | BPF_K, \ | ||
| 91 | .dst_reg = DST, \ | ||
| 92 | .src_reg = 0, \ | ||
| 93 | .off = 0, \ | ||
| 94 | .imm = IMM }) | ||
| 95 | |||
| 88 | /* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ | 96 | /* BPF_LD_IMM64 macro encodes single 'load 64-bit immediate' insn */ |
| 89 | #define BPF_LD_IMM64(DST, IMM) \ | 97 | #define BPF_LD_IMM64(DST, IMM) \ |
| 90 | BPF_LD_IMM64_RAW(DST, 0, IMM) | 98 | BPF_LD_IMM64_RAW(DST, 0, IMM) |
diff --git a/samples/bpf/test_verifier.c b/samples/bpf/test_verifier.c index ac590d4b7f02..369ffaad3799 100644 --- a/samples/bpf/test_verifier.c +++ b/samples/bpf/test_verifier.c | |||
| @@ -29,6 +29,7 @@ struct bpf_test { | |||
| 29 | struct bpf_insn insns[MAX_INSNS]; | 29 | struct bpf_insn insns[MAX_INSNS]; |
| 30 | int fixup[MAX_FIXUPS]; | 30 | int fixup[MAX_FIXUPS]; |
| 31 | int prog_array_fixup[MAX_FIXUPS]; | 31 | int prog_array_fixup[MAX_FIXUPS]; |
| 32 | int test_val_map_fixup[MAX_FIXUPS]; | ||
| 32 | const char *errstr; | 33 | const char *errstr; |
| 33 | const char *errstr_unpriv; | 34 | const char *errstr_unpriv; |
| 34 | enum { | 35 | enum { |
| @@ -39,6 +40,19 @@ struct bpf_test { | |||
| 39 | enum bpf_prog_type prog_type; | 40 | enum bpf_prog_type prog_type; |
| 40 | }; | 41 | }; |
| 41 | 42 | ||
| 43 | /* Note we want this to be 64 bit aligned so that the end of our array is | ||
| 44 | * actually the end of the structure. | ||
| 45 | */ | ||
| 46 | #define MAX_ENTRIES 11 | ||
| 47 | struct test_val { | ||
| 48 | unsigned index; | ||
| 49 | int foo[MAX_ENTRIES]; | ||
| 50 | }; | ||
| 51 | |||
| 52 | struct other_val { | ||
| 53 | unsigned int action[32]; | ||
| 54 | }; | ||
| 55 | |||
| 42 | static struct bpf_test tests[] = { | 56 | static struct bpf_test tests[] = { |
| 43 | { | 57 | { |
| 44 | "add+sub+mul", | 58 | "add+sub+mul", |
| @@ -2163,6 +2177,212 @@ static struct bpf_test tests[] = { | |||
| 2163 | .errstr = "invalid access to packet", | 2177 | .errstr = "invalid access to packet", |
| 2164 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, | 2178 | .prog_type = BPF_PROG_TYPE_SCHED_CLS, |
| 2165 | }, | 2179 | }, |
| 2180 | { | ||
| 2181 | "valid map access into an array with a constant", | ||
| 2182 | .insns = { | ||
| 2183 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2184 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2185 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2186 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2187 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2188 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), | ||
| 2189 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2190 | BPF_EXIT_INSN(), | ||
| 2191 | }, | ||
| 2192 | .test_val_map_fixup = {3}, | ||
| 2193 | .errstr_unpriv = "R0 leaks addr", | ||
| 2194 | .result_unpriv = REJECT, | ||
| 2195 | .result = ACCEPT, | ||
| 2196 | }, | ||
| 2197 | { | ||
| 2198 | "valid map access into an array with a register", | ||
| 2199 | .insns = { | ||
| 2200 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2201 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2202 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2203 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2204 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2205 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), | ||
| 2206 | BPF_MOV64_IMM(BPF_REG_1, 4), | ||
| 2207 | BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2), | ||
| 2208 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), | ||
| 2209 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2210 | BPF_EXIT_INSN(), | ||
| 2211 | }, | ||
| 2212 | .test_val_map_fixup = {3}, | ||
| 2213 | .errstr_unpriv = "R0 leaks addr", | ||
| 2214 | .result_unpriv = REJECT, | ||
| 2215 | .result = ACCEPT, | ||
| 2216 | }, | ||
| 2217 | { | ||
| 2218 | "valid map access into an array with a variable", | ||
| 2219 | .insns = { | ||
| 2220 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2221 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2222 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2223 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2224 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2225 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5), | ||
| 2226 | BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), | ||
| 2227 | BPF_JMP_IMM(BPF_JGE, BPF_REG_1, MAX_ENTRIES, 3), | ||
| 2228 | BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2), | ||
| 2229 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), | ||
| 2230 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2231 | BPF_EXIT_INSN(), | ||
| 2232 | }, | ||
| 2233 | .test_val_map_fixup = {3}, | ||
| 2234 | .errstr_unpriv = "R0 leaks addr", | ||
| 2235 | .result_unpriv = REJECT, | ||
| 2236 | .result = ACCEPT, | ||
| 2237 | }, | ||
| 2238 | { | ||
| 2239 | "valid map access into an array with a signed variable", | ||
| 2240 | .insns = { | ||
| 2241 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2242 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2243 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2244 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2245 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2246 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 9), | ||
| 2247 | BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), | ||
| 2248 | BPF_JMP_IMM(BPF_JSGT, BPF_REG_1, 0xffffffff, 1), | ||
| 2249 | BPF_MOV32_IMM(BPF_REG_1, 0), | ||
| 2250 | BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES), | ||
| 2251 | BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1), | ||
| 2252 | BPF_MOV32_IMM(BPF_REG_1, 0), | ||
| 2253 | BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2), | ||
| 2254 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), | ||
| 2255 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2256 | BPF_EXIT_INSN(), | ||
| 2257 | }, | ||
| 2258 | .test_val_map_fixup = {3}, | ||
| 2259 | .errstr_unpriv = "R0 leaks addr", | ||
| 2260 | .result_unpriv = REJECT, | ||
| 2261 | .result = ACCEPT, | ||
| 2262 | }, | ||
| 2263 | { | ||
| 2264 | "invalid map access into an array with a constant", | ||
| 2265 | .insns = { | ||
| 2266 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2267 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2268 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2269 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2270 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2271 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 1), | ||
| 2272 | BPF_ST_MEM(BPF_DW, BPF_REG_0, (MAX_ENTRIES + 1) << 2, | ||
| 2273 | offsetof(struct test_val, foo)), | ||
| 2274 | BPF_EXIT_INSN(), | ||
| 2275 | }, | ||
| 2276 | .test_val_map_fixup = {3}, | ||
| 2277 | .errstr = "invalid access to map value, value_size=48 off=48 size=8", | ||
| 2278 | .result = REJECT, | ||
| 2279 | }, | ||
| 2280 | { | ||
| 2281 | "invalid map access into an array with a register", | ||
| 2282 | .insns = { | ||
| 2283 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2284 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2285 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2286 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2287 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2288 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), | ||
| 2289 | BPF_MOV64_IMM(BPF_REG_1, MAX_ENTRIES + 1), | ||
| 2290 | BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2), | ||
| 2291 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), | ||
| 2292 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2293 | BPF_EXIT_INSN(), | ||
| 2294 | }, | ||
| 2295 | .test_val_map_fixup = {3}, | ||
| 2296 | .errstr = "R0 min value is outside of the array range", | ||
| 2297 | .result = REJECT, | ||
| 2298 | }, | ||
| 2299 | { | ||
| 2300 | "invalid map access into an array with a variable", | ||
| 2301 | .insns = { | ||
| 2302 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2303 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2304 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2305 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2306 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2307 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4), | ||
| 2308 | BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), | ||
| 2309 | BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 2), | ||
| 2310 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), | ||
| 2311 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2312 | BPF_EXIT_INSN(), | ||
| 2313 | }, | ||
| 2314 | .test_val_map_fixup = {3}, | ||
| 2315 | .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", | ||
| 2316 | .result = REJECT, | ||
| 2317 | }, | ||
| 2318 | { | ||
| 2319 | "invalid map access into an array with no floor check", | ||
| 2320 | .insns = { | ||
| 2321 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2322 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2323 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2324 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2325 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2326 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7), | ||
| 2327 | BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), | ||
| 2328 | BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES), | ||
| 2329 | BPF_JMP_REG(BPF_JSGT, BPF_REG_2, BPF_REG_1, 1), | ||
| 2330 | BPF_MOV32_IMM(BPF_REG_1, 0), | ||
| 2331 | BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2), | ||
| 2332 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), | ||
| 2333 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2334 | BPF_EXIT_INSN(), | ||
| 2335 | }, | ||
| 2336 | .test_val_map_fixup = {3}, | ||
| 2337 | .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", | ||
| 2338 | .result = REJECT, | ||
| 2339 | }, | ||
| 2340 | { | ||
| 2341 | "invalid map access into an array with a invalid max check", | ||
| 2342 | .insns = { | ||
| 2343 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2344 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2345 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2346 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2347 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2348 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7), | ||
| 2349 | BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0), | ||
| 2350 | BPF_MOV32_IMM(BPF_REG_2, MAX_ENTRIES + 1), | ||
| 2351 | BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_1, 1), | ||
| 2352 | BPF_MOV32_IMM(BPF_REG_1, 0), | ||
| 2353 | BPF_ALU32_IMM(BPF_LSH, BPF_REG_1, 2), | ||
| 2354 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1), | ||
| 2355 | BPF_ST_MEM(BPF_DW, BPF_REG_0, 0, offsetof(struct test_val, foo)), | ||
| 2356 | BPF_EXIT_INSN(), | ||
| 2357 | }, | ||
| 2358 | .test_val_map_fixup = {3}, | ||
| 2359 | .errstr = "invalid access to map value, value_size=48 off=44 size=8", | ||
| 2360 | .result = REJECT, | ||
| 2361 | }, | ||
| 2362 | { | ||
| 2363 | "invalid map access into an array with a invalid max check", | ||
| 2364 | .insns = { | ||
| 2365 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2366 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2367 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2368 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2369 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2370 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 10), | ||
| 2371 | BPF_MOV64_REG(BPF_REG_8, BPF_REG_0), | ||
| 2372 | BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0), | ||
| 2373 | BPF_MOV64_REG(BPF_REG_2, BPF_REG_10), | ||
| 2374 | BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8), | ||
| 2375 | BPF_LD_MAP_FD(BPF_REG_1, 0), | ||
| 2376 | BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem), | ||
| 2377 | BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2), | ||
| 2378 | BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_8), | ||
| 2379 | BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, offsetof(struct test_val, foo)), | ||
| 2380 | BPF_EXIT_INSN(), | ||
| 2381 | }, | ||
| 2382 | .test_val_map_fixup = {3, 11}, | ||
| 2383 | .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.", | ||
| 2384 | .result = REJECT, | ||
| 2385 | }, | ||
| 2166 | }; | 2386 | }; |
| 2167 | 2387 | ||
| 2168 | static int probe_filter_length(struct bpf_insn *fp) | 2388 | static int probe_filter_length(struct bpf_insn *fp) |
| @@ -2176,12 +2396,12 @@ static int probe_filter_length(struct bpf_insn *fp) | |||
| 2176 | return len + 1; | 2396 | return len + 1; |
| 2177 | } | 2397 | } |
| 2178 | 2398 | ||
| 2179 | static int create_map(void) | 2399 | static int create_map(size_t val_size, int num) |
| 2180 | { | 2400 | { |
| 2181 | int map_fd; | 2401 | int map_fd; |
| 2182 | 2402 | ||
| 2183 | map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, | 2403 | map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, |
| 2184 | sizeof(long long), sizeof(long long), 1024, 0); | 2404 | sizeof(long long), val_size, num, 0); |
| 2185 | if (map_fd < 0) | 2405 | if (map_fd < 0) |
| 2186 | printf("failed to create map '%s'\n", strerror(errno)); | 2406 | printf("failed to create map '%s'\n", strerror(errno)); |
| 2187 | 2407 | ||
| @@ -2211,12 +2431,13 @@ static int test(void) | |||
| 2211 | int prog_len = probe_filter_length(prog); | 2431 | int prog_len = probe_filter_length(prog); |
| 2212 | int *fixup = tests[i].fixup; | 2432 | int *fixup = tests[i].fixup; |
| 2213 | int *prog_array_fixup = tests[i].prog_array_fixup; | 2433 | int *prog_array_fixup = tests[i].prog_array_fixup; |
| 2434 | int *test_val_map_fixup = tests[i].test_val_map_fixup; | ||
| 2214 | int expected_result; | 2435 | int expected_result; |
| 2215 | const char *expected_errstr; | 2436 | const char *expected_errstr; |
| 2216 | int map_fd = -1, prog_array_fd = -1; | 2437 | int map_fd = -1, prog_array_fd = -1, test_val_map_fd = -1; |
| 2217 | 2438 | ||
| 2218 | if (*fixup) { | 2439 | if (*fixup) { |
| 2219 | map_fd = create_map(); | 2440 | map_fd = create_map(sizeof(long long), 1024); |
| 2220 | 2441 | ||
| 2221 | do { | 2442 | do { |
| 2222 | prog[*fixup].imm = map_fd; | 2443 | prog[*fixup].imm = map_fd; |
| @@ -2231,6 +2452,18 @@ static int test(void) | |||
| 2231 | prog_array_fixup++; | 2452 | prog_array_fixup++; |
| 2232 | } while (*prog_array_fixup); | 2453 | } while (*prog_array_fixup); |
| 2233 | } | 2454 | } |
| 2455 | if (*test_val_map_fixup) { | ||
| 2456 | /* Unprivileged can't create a hash map.*/ | ||
| 2457 | if (unpriv) | ||
| 2458 | continue; | ||
| 2459 | test_val_map_fd = create_map(sizeof(struct test_val), | ||
| 2460 | 256); | ||
| 2461 | do { | ||
| 2462 | prog[*test_val_map_fixup].imm = test_val_map_fd; | ||
| 2463 | test_val_map_fixup++; | ||
| 2464 | } while (*test_val_map_fixup); | ||
| 2465 | } | ||
| 2466 | |||
| 2234 | printf("#%d %s ", i, tests[i].descr); | 2467 | printf("#%d %s ", i, tests[i].descr); |
| 2235 | 2468 | ||
| 2236 | prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER, | 2469 | prog_fd = bpf_prog_load(prog_type ?: BPF_PROG_TYPE_SOCKET_FILTER, |
| @@ -2277,6 +2510,8 @@ fail: | |||
| 2277 | close(map_fd); | 2510 | close(map_fd); |
| 2278 | if (prog_array_fd >= 0) | 2511 | if (prog_array_fd >= 0) |
| 2279 | close(prog_array_fd); | 2512 | close(prog_array_fd); |
| 2513 | if (test_val_map_fd >= 0) | ||
| 2514 | close(test_val_map_fd); | ||
| 2280 | close(prog_fd); | 2515 | close(prog_fd); |
| 2281 | 2516 | ||
| 2282 | } | 2517 | } |
