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/bpf | |
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/bpf')
-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 | } |