aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/jit.c27
-rw-r--r--kernel/bpf/verifier.c25
-rw-r--r--tools/testing/selftests/bpf/.gitignore1
-rw-r--r--tools/testing/selftests/bpf/test_verifier.c305
4 files changed, 308 insertions, 50 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/jit.c b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
index 662cbc21d909..e23ca90289f7 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/jit.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/jit.c
@@ -3052,26 +3052,19 @@ static int jset_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
3052{ 3052{
3053 const struct bpf_insn *insn = &meta->insn; 3053 const struct bpf_insn *insn = &meta->insn;
3054 u64 imm = insn->imm; /* sign extend */ 3054 u64 imm = insn->imm; /* sign extend */
3055 u8 dst_gpr = insn->dst_reg * 2;
3055 swreg tmp_reg; 3056 swreg tmp_reg;
3056 3057
3057 if (!imm) { 3058 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog));
3058 meta->skip = true; 3059 emit_alu(nfp_prog, imm_b(nfp_prog),
3059 return 0; 3060 reg_a(dst_gpr), ALU_OP_AND, tmp_reg);
3060 } 3061 /* Upper word of the mask can only be 0 or ~0 from sign extension,
3061 3062 * so either ignore it or OR the whole thing in.
3062 if (imm & ~0U) { 3063 */
3063 tmp_reg = ur_load_imm_any(nfp_prog, imm & ~0U, imm_b(nfp_prog)); 3064 if (imm >> 32)
3064 emit_alu(nfp_prog, reg_none(),
3065 reg_a(insn->dst_reg * 2), ALU_OP_AND, tmp_reg);
3066 emit_br(nfp_prog, BR_BNE, insn->off, 0);
3067 }
3068
3069 if (imm >> 32) {
3070 tmp_reg = ur_load_imm_any(nfp_prog, imm >> 32, imm_b(nfp_prog));
3071 emit_alu(nfp_prog, reg_none(), 3065 emit_alu(nfp_prog, reg_none(),
3072 reg_a(insn->dst_reg * 2 + 1), ALU_OP_AND, tmp_reg); 3066 reg_a(dst_gpr + 1), ALU_OP_OR, imm_b(nfp_prog));
3073 emit_br(nfp_prog, BR_BNE, insn->off, 0); 3067 emit_br(nfp_prog, BR_BNE, insn->off, 0);
3074 }
3075 3068
3076 return 0; 3069 return 0;
3077} 3070}
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 5c64281d566e..d27d5a880015 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3859,6 +3859,12 @@ static int is_branch_taken(struct bpf_reg_state *reg, u64 val, u8 opcode)
3859 if (tnum_is_const(reg->var_off)) 3859 if (tnum_is_const(reg->var_off))
3860 return !tnum_equals_const(reg->var_off, val); 3860 return !tnum_equals_const(reg->var_off, val);
3861 break; 3861 break;
3862 case BPF_JSET:
3863 if ((~reg->var_off.mask & reg->var_off.value) & val)
3864 return 1;
3865 if (!((reg->var_off.mask | reg->var_off.value) & val))
3866 return 0;
3867 break;
3862 case BPF_JGT: 3868 case BPF_JGT:
3863 if (reg->umin_value > val) 3869 if (reg->umin_value > val)
3864 return 1; 3870 return 1;
@@ -3943,6 +3949,13 @@ static void reg_set_min_max(struct bpf_reg_state *true_reg,
3943 */ 3949 */
3944 __mark_reg_known(false_reg, val); 3950 __mark_reg_known(false_reg, val);
3945 break; 3951 break;
3952 case BPF_JSET:
3953 false_reg->var_off = tnum_and(false_reg->var_off,
3954 tnum_const(~val));
3955 if (is_power_of_2(val))
3956 true_reg->var_off = tnum_or(true_reg->var_off,
3957 tnum_const(val));
3958 break;
3946 case BPF_JGT: 3959 case BPF_JGT:
3947 false_reg->umax_value = min(false_reg->umax_value, val); 3960 false_reg->umax_value = min(false_reg->umax_value, val);
3948 true_reg->umin_value = max(true_reg->umin_value, val + 1); 3961 true_reg->umin_value = max(true_reg->umin_value, val + 1);
@@ -4015,6 +4028,13 @@ static void reg_set_min_max_inv(struct bpf_reg_state *true_reg,
4015 */ 4028 */
4016 __mark_reg_known(false_reg, val); 4029 __mark_reg_known(false_reg, val);
4017 break; 4030 break;
4031 case BPF_JSET:
4032 false_reg->var_off = tnum_and(false_reg->var_off,
4033 tnum_const(~val));
4034 if (is_power_of_2(val))
4035 true_reg->var_off = tnum_or(true_reg->var_off,
4036 tnum_const(val));
4037 break;
4018 case BPF_JGT: 4038 case BPF_JGT:
4019 true_reg->umax_value = min(true_reg->umax_value, val - 1); 4039 true_reg->umax_value = min(true_reg->umax_value, val - 1);
4020 false_reg->umin_value = max(false_reg->umin_value, val); 4040 false_reg->umin_value = max(false_reg->umin_value, val);
@@ -6963,10 +6983,11 @@ skip_full_check:
6963 free_states(env); 6983 free_states(env);
6964 6984
6965 if (ret == 0) 6985 if (ret == 0)
6966 sanitize_dead_code(env); 6986 ret = check_max_stack_depth(env);
6967 6987
6988 /* instruction rewrites happen after this point */
6968 if (ret == 0) 6989 if (ret == 0)
6969 ret = check_max_stack_depth(env); 6990 sanitize_dead_code(env);
6970 6991
6971 if (ret == 0) 6992 if (ret == 0)
6972 /* program is valid, convert *(u32*)(ctx + off) accesses */ 6993 /* program is valid, convert *(u32*)(ctx + off) accesses */
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
index 1b799e30c06d..4a9785043a39 100644
--- a/tools/testing/selftests/bpf/.gitignore
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -27,3 +27,4 @@ test_flow_dissector
27flow_dissector_load 27flow_dissector_load
28test_netcnt 28test_netcnt
29test_section_names 29test_section_names
30test_tcpnotify_user
diff --git a/tools/testing/selftests/bpf/test_verifier.c b/tools/testing/selftests/bpf/test_verifier.c
index 7865b94c02c4..b246931c46ef 100644
--- a/tools/testing/selftests/bpf/test_verifier.c
+++ b/tools/testing/selftests/bpf/test_verifier.c
@@ -49,6 +49,7 @@
49#define MAX_INSNS BPF_MAXINSNS 49#define MAX_INSNS BPF_MAXINSNS
50#define MAX_FIXUPS 8 50#define MAX_FIXUPS 8
51#define MAX_NR_MAPS 13 51#define MAX_NR_MAPS 13
52#define MAX_TEST_RUNS 8
52#define POINTER_VALUE 0xcafe4all 53#define POINTER_VALUE 0xcafe4all
53#define TEST_DATA_LEN 64 54#define TEST_DATA_LEN 64
54 55
@@ -86,6 +87,14 @@ struct bpf_test {
86 uint8_t flags; 87 uint8_t flags;
87 __u8 data[TEST_DATA_LEN]; 88 __u8 data[TEST_DATA_LEN];
88 void (*fill_helper)(struct bpf_test *self); 89 void (*fill_helper)(struct bpf_test *self);
90 uint8_t runs;
91 struct {
92 uint32_t retval, retval_unpriv;
93 union {
94 __u8 data[TEST_DATA_LEN];
95 __u64 data64[TEST_DATA_LEN / 8];
96 };
97 } retvals[MAX_TEST_RUNS];
89}; 98};
90 99
91/* Note we want this to be 64 bit aligned so that the end of our array is 100/* Note we want this to be 64 bit aligned so that the end of our array is
@@ -14161,6 +14170,197 @@ static struct bpf_test tests[] = {
14161 .errstr_unpriv = "R1 leaks addr", 14170 .errstr_unpriv = "R1 leaks addr",
14162 .result = REJECT, 14171 .result = REJECT,
14163 }, 14172 },
14173 {
14174 "jset: functional",
14175 .insns = {
14176 /* r0 = 0 */
14177 BPF_MOV64_IMM(BPF_REG_0, 0),
14178 /* prep for direct packet access via r2 */
14179 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
14180 offsetof(struct __sk_buff, data)),
14181 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
14182 offsetof(struct __sk_buff, data_end)),
14183 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
14184 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8),
14185 BPF_JMP_REG(BPF_JLE, BPF_REG_4, BPF_REG_3, 1),
14186 BPF_EXIT_INSN(),
14187
14188 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_2, 0),
14189
14190 /* reg, bit 63 or bit 0 set, taken */
14191 BPF_LD_IMM64(BPF_REG_8, 0x8000000000000001),
14192 BPF_JMP_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1),
14193 BPF_EXIT_INSN(),
14194
14195 /* reg, bit 62, not taken */
14196 BPF_LD_IMM64(BPF_REG_8, 0x4000000000000000),
14197 BPF_JMP_REG(BPF_JSET, BPF_REG_7, BPF_REG_8, 1),
14198 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
14199 BPF_EXIT_INSN(),
14200
14201 /* imm, any bit set, taken */
14202 BPF_JMP_IMM(BPF_JSET, BPF_REG_7, -1, 1),
14203 BPF_EXIT_INSN(),
14204
14205 /* imm, bit 31 set, taken */
14206 BPF_JMP_IMM(BPF_JSET, BPF_REG_7, 0x80000000, 1),
14207 BPF_EXIT_INSN(),
14208
14209 /* all good - return r0 == 2 */
14210 BPF_MOV64_IMM(BPF_REG_0, 2),
14211 BPF_EXIT_INSN(),
14212 },
14213 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
14214 .result = ACCEPT,
14215 .runs = 7,
14216 .retvals = {
14217 { .retval = 2,
14218 .data64 = { (1ULL << 63) | (1U << 31) | (1U << 0), }
14219 },
14220 { .retval = 2,
14221 .data64 = { (1ULL << 63) | (1U << 31), }
14222 },
14223 { .retval = 2,
14224 .data64 = { (1ULL << 31) | (1U << 0), }
14225 },
14226 { .retval = 2,
14227 .data64 = { (__u32)-1, }
14228 },
14229 { .retval = 2,
14230 .data64 = { ~0x4000000000000000ULL, }
14231 },
14232 { .retval = 0,
14233 .data64 = { 0, }
14234 },
14235 { .retval = 0,
14236 .data64 = { ~0ULL, }
14237 },
14238 },
14239 },
14240 {
14241 "jset: sign-extend",
14242 .insns = {
14243 /* r0 = 0 */
14244 BPF_MOV64_IMM(BPF_REG_0, 0),
14245 /* prep for direct packet access via r2 */
14246 BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1,
14247 offsetof(struct __sk_buff, data)),
14248 BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1,
14249 offsetof(struct __sk_buff, data_end)),
14250 BPF_MOV64_REG(BPF_REG_4, BPF_REG_2),
14251 BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 8),
14252 BPF_JMP_REG(BPF_JLE, BPF_REG_4, BPF_REG_3, 1),
14253 BPF_EXIT_INSN(),
14254
14255 BPF_LDX_MEM(BPF_DW, BPF_REG_7, BPF_REG_2, 0),
14256
14257 BPF_JMP_IMM(BPF_JSET, BPF_REG_7, 0x80000000, 1),
14258 BPF_EXIT_INSN(),
14259
14260 BPF_MOV64_IMM(BPF_REG_0, 2),
14261 BPF_EXIT_INSN(),
14262 },
14263 .prog_type = BPF_PROG_TYPE_SCHED_CLS,
14264 .result = ACCEPT,
14265 .retval = 2,
14266 .data = { 1, 0, 0, 0, 0, 0, 0, 1, },
14267 },
14268 {
14269 "jset: known const compare",
14270 .insns = {
14271 BPF_MOV64_IMM(BPF_REG_0, 1),
14272 BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
14273 BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
14274 BPF_EXIT_INSN(),
14275 },
14276 .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
14277 .retval_unpriv = 1,
14278 .result_unpriv = ACCEPT,
14279 .retval = 1,
14280 .result = ACCEPT,
14281 },
14282 {
14283 "jset: known const compare bad",
14284 .insns = {
14285 BPF_MOV64_IMM(BPF_REG_0, 0),
14286 BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
14287 BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
14288 BPF_EXIT_INSN(),
14289 },
14290 .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
14291 .errstr_unpriv = "!read_ok",
14292 .result_unpriv = REJECT,
14293 .errstr = "!read_ok",
14294 .result = REJECT,
14295 },
14296 {
14297 "jset: unknown const compare taken",
14298 .insns = {
14299 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
14300 BPF_FUNC_get_prandom_u32),
14301 BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
14302 BPF_JMP_IMM(BPF_JA, 0, 0, 1),
14303 BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
14304 BPF_EXIT_INSN(),
14305 },
14306 .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
14307 .errstr_unpriv = "!read_ok",
14308 .result_unpriv = REJECT,
14309 .errstr = "!read_ok",
14310 .result = REJECT,
14311 },
14312 {
14313 "jset: unknown const compare not taken",
14314 .insns = {
14315 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
14316 BPF_FUNC_get_prandom_u32),
14317 BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 1, 1),
14318 BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
14319 BPF_EXIT_INSN(),
14320 },
14321 .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
14322 .errstr_unpriv = "!read_ok",
14323 .result_unpriv = REJECT,
14324 .errstr = "!read_ok",
14325 .result = REJECT,
14326 },
14327 {
14328 "jset: half-known const compare",
14329 .insns = {
14330 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
14331 BPF_FUNC_get_prandom_u32),
14332 BPF_ALU64_IMM(BPF_OR, BPF_REG_0, 2),
14333 BPF_JMP_IMM(BPF_JSET, BPF_REG_0, 3, 1),
14334 BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
14335 BPF_MOV64_IMM(BPF_REG_0, 0),
14336 BPF_EXIT_INSN(),
14337 },
14338 .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
14339 .result_unpriv = ACCEPT,
14340 .result = ACCEPT,
14341 },
14342 {
14343 "jset: range",
14344 .insns = {
14345 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
14346 BPF_FUNC_get_prandom_u32),
14347 BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
14348 BPF_MOV64_IMM(BPF_REG_0, 0),
14349 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xff),
14350 BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0xf0, 3),
14351 BPF_JMP_IMM(BPF_JLT, BPF_REG_1, 0x10, 1),
14352 BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
14353 BPF_EXIT_INSN(),
14354 BPF_JMP_IMM(BPF_JSET, BPF_REG_1, 0x10, 1),
14355 BPF_EXIT_INSN(),
14356 BPF_JMP_IMM(BPF_JGE, BPF_REG_1, 0x10, 1),
14357 BPF_LDX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, 0),
14358 BPF_EXIT_INSN(),
14359 },
14360 .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
14361 .result_unpriv = ACCEPT,
14362 .result = ACCEPT,
14363 },
14164}; 14364};
14165 14365
14166static int probe_filter_length(const struct bpf_insn *fp) 14366static int probe_filter_length(const struct bpf_insn *fp)
@@ -14443,16 +14643,42 @@ out:
14443 return ret; 14643 return ret;
14444} 14644}
14445 14645
14646static int do_prog_test_run(int fd_prog, bool unpriv, uint32_t expected_val,
14647 void *data, size_t size_data)
14648{
14649 __u8 tmp[TEST_DATA_LEN << 2];
14650 __u32 size_tmp = sizeof(tmp);
14651 uint32_t retval;
14652 int err;
14653
14654 if (unpriv)
14655 set_admin(true);
14656 err = bpf_prog_test_run(fd_prog, 1, data, size_data,
14657 tmp, &size_tmp, &retval, NULL);
14658 if (unpriv)
14659 set_admin(false);
14660 if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) {
14661 printf("Unexpected bpf_prog_test_run error ");
14662 return err;
14663 }
14664 if (!err && retval != expected_val &&
14665 expected_val != POINTER_VALUE) {
14666 printf("FAIL retval %d != %d ", retval, expected_val);
14667 return 1;
14668 }
14669
14670 return 0;
14671}
14672
14446static void do_test_single(struct bpf_test *test, bool unpriv, 14673static void do_test_single(struct bpf_test *test, bool unpriv,
14447 int *passes, int *errors) 14674 int *passes, int *errors)
14448{ 14675{
14449 int fd_prog, expected_ret, alignment_prevented_execution; 14676 int fd_prog, expected_ret, alignment_prevented_execution;
14450 int prog_len, prog_type = test->prog_type; 14677 int prog_len, prog_type = test->prog_type;
14451 struct bpf_insn *prog = test->insns; 14678 struct bpf_insn *prog = test->insns;
14679 int run_errs, run_successes;
14452 int map_fds[MAX_NR_MAPS]; 14680 int map_fds[MAX_NR_MAPS];
14453 const char *expected_err; 14681 const char *expected_err;
14454 uint32_t expected_val;
14455 uint32_t retval;
14456 __u32 pflags; 14682 __u32 pflags;
14457 int i, err; 14683 int i, err;
14458 14684
@@ -14476,8 +14702,6 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
14476 test->result_unpriv : test->result; 14702 test->result_unpriv : test->result;
14477 expected_err = unpriv && test->errstr_unpriv ? 14703 expected_err = unpriv && test->errstr_unpriv ?
14478 test->errstr_unpriv : test->errstr; 14704 test->errstr_unpriv : test->errstr;
14479 expected_val = unpriv && test->retval_unpriv ?
14480 test->retval_unpriv : test->retval;
14481 14705
14482 alignment_prevented_execution = 0; 14706 alignment_prevented_execution = 0;
14483 14707
@@ -14489,10 +14713,8 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
14489 } 14713 }
14490#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 14714#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
14491 if (fd_prog >= 0 && 14715 if (fd_prog >= 0 &&
14492 (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS)) { 14716 (test->flags & F_NEEDS_EFFICIENT_UNALIGNED_ACCESS))
14493 alignment_prevented_execution = 1; 14717 alignment_prevented_execution = 1;
14494 goto test_ok;
14495 }
14496#endif 14718#endif
14497 } else { 14719 } else {
14498 if (fd_prog >= 0) { 14720 if (fd_prog >= 0) {
@@ -14519,33 +14741,54 @@ static void do_test_single(struct bpf_test *test, bool unpriv,
14519 } 14741 }
14520 } 14742 }
14521 14743
14522 if (fd_prog >= 0) { 14744 run_errs = 0;
14523 __u8 tmp[TEST_DATA_LEN << 2]; 14745 run_successes = 0;
14524 __u32 size_tmp = sizeof(tmp); 14746 if (!alignment_prevented_execution && fd_prog >= 0) {
14525 14747 uint32_t expected_val;
14526 if (unpriv) 14748 int i;
14527 set_admin(true); 14749
14528 err = bpf_prog_test_run(fd_prog, 1, test->data, 14750 if (!test->runs) {
14529 sizeof(test->data), tmp, &size_tmp, 14751 expected_val = unpriv && test->retval_unpriv ?
14530 &retval, NULL); 14752 test->retval_unpriv : test->retval;
14531 if (unpriv) 14753
14532 set_admin(false); 14754 err = do_prog_test_run(fd_prog, unpriv, expected_val,
14533 if (err && errno != 524/*ENOTSUPP*/ && errno != EPERM) { 14755 test->data, sizeof(test->data));
14534 printf("Unexpected bpf_prog_test_run error\n"); 14756 if (err)
14535 goto fail_log; 14757 run_errs++;
14758 else
14759 run_successes++;
14536 } 14760 }
14537 if (!err && retval != expected_val && 14761
14538 expected_val != POINTER_VALUE) { 14762 for (i = 0; i < test->runs; i++) {
14539 printf("FAIL retval %d != %d\n", retval, expected_val); 14763 if (unpriv && test->retvals[i].retval_unpriv)
14540 goto fail_log; 14764 expected_val = test->retvals[i].retval_unpriv;
14765 else
14766 expected_val = test->retvals[i].retval;
14767
14768 err = do_prog_test_run(fd_prog, unpriv, expected_val,
14769 test->retvals[i].data,
14770 sizeof(test->retvals[i].data));
14771 if (err) {
14772 printf("(run %d/%d) ", i + 1, test->runs);
14773 run_errs++;
14774 } else {
14775 run_successes++;
14776 }
14541 } 14777 }
14542 } 14778 }
14543#ifndef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS 14779
14544test_ok: 14780 if (!run_errs) {
14545#endif 14781 (*passes)++;
14546 (*passes)++; 14782 if (run_successes > 1)
14547 printf("OK%s\n", alignment_prevented_execution ? 14783 printf("%d cases ", run_successes);
14548 " (NOTE: not executed due to unknown alignment)" : ""); 14784 printf("OK");
14785 if (alignment_prevented_execution)
14786 printf(" (NOTE: not executed due to unknown alignment)");
14787 printf("\n");
14788 } else {
14789 printf("\n");
14790 goto fail_log;
14791 }
14549close_fds: 14792close_fds:
14550 close(fd_prog); 14793 close(fd_prog);
14551 for (i = 0; i < MAX_NR_MAPS; i++) 14794 for (i = 0; i < MAX_NR_MAPS; i++)