History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Alexei Starovoitov says: ==================== pull-request: bpf 2019-01-02 The following pull-request contains BPF updates for your *net* tree. The main changes are: 1) prevent out of bounds speculation on pointer arithmetic, from Daniel. 2) typo fix, from Xiaozhou. ====================

David S. Miller committed 7 years ago

Commit be630042 parents d63967e a67825f6 files · +1452 −108Browse files

Unified · Split

6 files
  1. include/linux/bpf_verifier.h +12 −0
  2. include/linux/filter.h +3 −7
  3. kernel/bpf/core.c +37 −17
  4. kernel/bpf/verifier.c +275 −61
  5. tools/testing/selftests/bpf/test_maps.c +1 −1
  6. tools/testing/selftests/bpf/test_verifier.c +1124 −22
include/linux/bpf_verifier.h+12−0
@@ -148,6 +148,7 @@ struct bpf_verifier_state { · 147 unmodified lines
148 /* call stack tracking */148 /* call stack tracking */
149 struct bpf_func_state *frame[MAX_CALL_FRAMES];149 struct bpf_func_state *frame[MAX_CALL_FRAMES];
150 u32 curframe;150 u32 curframe;
151 bool speculative;
151};152};
152 153
153#define bpf_get_spilled_reg(slot, frame) \154#define bpf_get_spilled_reg(slot, frame) \
@@ -167,15 +168,24 @@ struct bpf_verifier_state_list { · 13 unmodified lines
167 struct bpf_verifier_state_list *next;168 struct bpf_verifier_state_list *next;
168};169};
169 170
171/* Possible states for alu_state member. */
172#define BPF_ALU_SANITIZE_SRC 1U
173#define BPF_ALU_SANITIZE_DST 2U
174#define BPF_ALU_NEG_VALUE (1U << 2)
175#define BPF_ALU_SANITIZE (BPF_ALU_SANITIZE_SRC | \
176 BPF_ALU_SANITIZE_DST)
177
170struct bpf_insn_aux_data {178struct bpf_insn_aux_data {
171 union {179 union {
172 enum bpf_reg_type ptr_type; /* pointer type for load/store insns */180 enum bpf_reg_type ptr_type; /* pointer type for load/store insns */
173 unsigned long map_state; /* pointer/poison value for maps */181 unsigned long map_state; /* pointer/poison value for maps */
174 s32 call_imm; /* saved imm field of call insn */182 s32 call_imm; /* saved imm field of call insn */
183 u32 alu_limit; /* limit for add/sub register with pointer */
175 };184 };
176 int ctx_field_size; /* the ctx field size for load insn, maybe 0 */185 int ctx_field_size; /* the ctx field size for load insn, maybe 0 */
177 int sanitize_stack_off; /* stack slot to be cleared */186 int sanitize_stack_off; /* stack slot to be cleared */
178 bool seen; /* this insn was processed by the verifier */187 bool seen; /* this insn was processed by the verifier */
188 u8 alu_state; /* used in combination with alu_limit */
179};189};
180 190
181#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */191#define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF program */
@@ -212,6 +222,8 @@ struct bpf_subprog_info { · 30 unmodified lines
212 * one verifier_env per bpf_check() call222 * one verifier_env per bpf_check() call
213 */223 */
214struct bpf_verifier_env {224struct bpf_verifier_env {
225 u32 insn_idx;
226 u32 prev_insn_idx;
215 struct bpf_prog *prog; /* eBPF program being verified */227 struct bpf_prog *prog; /* eBPF program being verified */
216 const struct bpf_verifier_ops *ops;228 const struct bpf_verifier_ops *ops;
217 struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */229 struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
include/linux/filter.h+3−7
@@ -53,14 +53,10 @@ struct sock_reuseport; · 52 unmodified lines
53#define BPF_REG_D BPF_REG_8 /* data, callee-saved */53#define BPF_REG_D BPF_REG_8 /* data, callee-saved */
54#define BPF_REG_H BPF_REG_9 /* hlen, callee-saved */54#define BPF_REG_H BPF_REG_9 /* hlen, callee-saved */
55 55
56/* Kernel hidden auxiliary/helper register for hardening step.56/* Kernel hidden auxiliary/helper register. */
57 * Only used by eBPF JITs. It's nothing more than a temporary
58 * register that JITs use internally, only that here it's part
59 * of eBPF instructions that have been rewritten for blinding
60 * constants. See JIT pre-step in bpf_jit_blind_constants().
61 */
62#define BPF_REG_AX MAX_BPF_REG57#define BPF_REG_AX MAX_BPF_REG
63#define MAX_BPF_JIT_REG (MAX_BPF_REG + 1)58#define MAX_BPF_EXT_REG (MAX_BPF_REG + 1)
59#define MAX_BPF_JIT_REG MAX_BPF_EXT_REG
64 60
65/* unused opcode to mark special call to bpf_tail_call() helper */61/* unused opcode to mark special call to bpf_tail_call() helper */
66#define BPF_TAIL_CALL 0xf062#define BPF_TAIL_CALL 0xf0
kernel/bpf/core.c+37−17
@@ -54,6 +54,7 @@ · 53 unmodified lines
54#define DST regs[insn->dst_reg]54#define DST regs[insn->dst_reg]
55#define SRC regs[insn->src_reg]55#define SRC regs[insn->src_reg]
56#define FP regs[BPF_REG_FP]56#define FP regs[BPF_REG_FP]
57#define AX regs[BPF_REG_AX]
57#define ARG1 regs[BPF_REG_ARG1]58#define ARG1 regs[BPF_REG_ARG1]
58#define CTX regs[BPF_REG_CTX]59#define CTX regs[BPF_REG_CTX]
59#define IMM insn->imm60#define IMM insn->imm
@@ -857,6 +858,26 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from, · 797 unmodified lines
857 BUILD_BUG_ON(BPF_REG_AX + 1 != MAX_BPF_JIT_REG);858 BUILD_BUG_ON(BPF_REG_AX + 1 != MAX_BPF_JIT_REG);
858 BUILD_BUG_ON(MAX_BPF_REG + 1 != MAX_BPF_JIT_REG);859 BUILD_BUG_ON(MAX_BPF_REG + 1 != MAX_BPF_JIT_REG);
859 860
861 /* Constraints on AX register:
862 *
863 * AX register is inaccessible from user space. It is mapped in
864 * all JITs, and used here for constant blinding rewrites. It is
865 * typically "stateless" meaning its contents are only valid within
866 * the executed instruction, but not across several instructions.
867 * There are a few exceptions however which are further detailed
868 * below.
869 *
870 * Constant blinding is only used by JITs, not in the interpreter.
871 * The interpreter uses AX in some occasions as a local temporary
872 * register e.g. in DIV or MOD instructions.
873 *
874 * In restricted circumstances, the verifier can also use the AX
875 * register for rewrites as long as they do not interfere with
876 * the above cases!
877 */
878 if (from->dst_reg == BPF_REG_AX || from->src_reg == BPF_REG_AX)
879 goto out;
880
860 if (from->imm == 0 &&881 if (from->imm == 0 &&
861 (from->code == (BPF_ALU | BPF_MOV | BPF_K) ||882 (from->code == (BPF_ALU | BPF_MOV | BPF_K) ||
862 from->code == (BPF_ALU64 | BPF_MOV | BPF_K))) {883 from->code == (BPF_ALU64 | BPF_MOV | BPF_K))) {
@@ -1188,7 +1209,6 @@ bool bpf_opcode_in_insntable(u8 code) · 325 unmodified lines
1188 */1209 */
1189static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)1210static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack)
1190{1211{
1191 u64 tmp;
1192#define BPF_INSN_2_LBL(x, y) [BPF_##x | BPF_##y] = &&x##_##y1212#define BPF_INSN_2_LBL(x, y) [BPF_##x | BPF_##y] = &&x##_##y
1193#define BPF_INSN_3_LBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = &&x##_##y##_##z1213#define BPF_INSN_3_LBL(x, y, z) [BPF_##x | BPF_##y | BPF_##z] = &&x##_##y##_##z
1194 static const void *jumptable[256] = {1214 static const void *jumptable[256] = {
@@ -1268,36 +1288,36 @@ select_insn: · 73 unmodified lines
1268 (*(s64 *) &DST) >>= IMM;1288 (*(s64 *) &DST) >>= IMM;
1269 CONT;1289 CONT;
1270 ALU64_MOD_X:1290 ALU64_MOD_X:
1271 div64_u64_rem(DST, SRC, &tmp);1291 div64_u64_rem(DST, SRC, &AX);
1272 DST = tmp;1292 DST = AX;
1273 CONT;1293 CONT;
1274 ALU_MOD_X:1294 ALU_MOD_X:
1275 tmp = (u32) DST;1295 AX = (u32) DST;
1276 DST = do_div(tmp, (u32) SRC);1296 DST = do_div(AX, (u32) SRC);
1277 CONT;1297 CONT;
1278 ALU64_MOD_K:1298 ALU64_MOD_K:
1279 div64_u64_rem(DST, IMM, &tmp);1299 div64_u64_rem(DST, IMM, &AX);
1280 DST = tmp;1300 DST = AX;
1281 CONT;1301 CONT;
1282 ALU_MOD_K:1302 ALU_MOD_K:
1283 tmp = (u32) DST;1303 AX = (u32) DST;
1284 DST = do_div(tmp, (u32) IMM);1304 DST = do_div(AX, (u32) IMM);
1285 CONT;1305 CONT;
1286 ALU64_DIV_X:1306 ALU64_DIV_X:
1287 DST = div64_u64(DST, SRC);1307 DST = div64_u64(DST, SRC);
1288 CONT;1308 CONT;
1289 ALU_DIV_X:1309 ALU_DIV_X:
1290 tmp = (u32) DST;1310 AX = (u32) DST;
1291 do_div(tmp, (u32) SRC);1311 do_div(AX, (u32) SRC);
1292 DST = (u32) tmp;1312 DST = (u32) AX;
1293 CONT;1313 CONT;
1294 ALU64_DIV_K:1314 ALU64_DIV_K:
1295 DST = div64_u64(DST, IMM);1315 DST = div64_u64(DST, IMM);
1296 CONT;1316 CONT;
1297 ALU_DIV_K:1317 ALU_DIV_K:
1298 tmp = (u32) DST;1318 AX = (u32) DST;
1299 do_div(tmp, (u32) IMM);1319 do_div(AX, (u32) IMM);
1300 DST = (u32) tmp;1320 DST = (u32) AX;
1301 CONT;1321 CONT;
1302 ALU_END_TO_BE:1322 ALU_END_TO_BE:
1303 switch (IMM) {1323 switch (IMM) {
@@ -1553,7 +1573,7 @@ STACK_FRAME_NON_STANDARD(___bpf_prog_run); /* jump table */ · 249 unmodified lines
1553static unsigned int PROG_NAME(stack_size)(const void *ctx, const struct bpf_insn *insn) \1573static unsigned int PROG_NAME(stack_size)(const void *ctx, const struct bpf_insn *insn) \
1554{ \1574{ \
1555 u64 stack[stack_size / sizeof(u64)]; \1575 u64 stack[stack_size / sizeof(u64)]; \
1556 u64 regs[MAX_BPF_REG]; \1576 u64 regs[MAX_BPF_EXT_REG]; \
1557\1577\
1558 FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \1578 FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \
1559 ARG1 = (u64) (unsigned long) ctx; \1579 ARG1 = (u64) (unsigned long) ctx; \
@@ -1566,7 +1586,7 @@ static u64 PROG_NAME_ARGS(stack_size)(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5, \ · 6 unmodified lines
1566 const struct bpf_insn *insn) \1586 const struct bpf_insn *insn) \
1567{ \1587{ \
1568 u64 stack[stack_size / sizeof(u64)]; \1588 u64 stack[stack_size / sizeof(u64)]; \
1569 u64 regs[MAX_BPF_REG]; \1589 u64 regs[MAX_BPF_EXT_REG]; \
1570\1590\
1571 FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \1591 FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; \
1572 BPF_R1 = r1; \1592 BPF_R1 = r1; \
kernel/bpf/verifier.c+275−61
@@ -710,6 +710,7 @@ static int copy_verifier_state(struct bpf_verifier_state *dst_state, · 709 unmodified lines
710 free_func_state(dst_state->frame[i]);710 free_func_state(dst_state->frame[i]);
711 dst_state->frame[i] = NULL;711 dst_state->frame[i] = NULL;
712 }712 }
713 dst_state->speculative = src->speculative;
713 dst_state->curframe = src->curframe;714 dst_state->curframe = src->curframe;
714 for (i = 0; i <= src->curframe; i++) {715 for (i = 0; i <= src->curframe; i++) {
715 dst = dst_state->frame[i];716 dst = dst_state->frame[i];
@@ -754,7 +755,8 @@ static int pop_stack(struct bpf_verifier_env *env, int *prev_insn_idx, · 38 unmodified lines
754}755}
755 756
756static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,757static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env,
757 int insn_idx, int prev_insn_idx)758 int insn_idx, int prev_insn_idx,
759 bool speculative)
758{760{
759 struct bpf_verifier_state *cur = env->cur_state;761 struct bpf_verifier_state *cur = env->cur_state;
760 struct bpf_verifier_stack_elem *elem;762 struct bpf_verifier_stack_elem *elem;
@@ -772,6 +774,7 @@ static struct bpf_verifier_state *push_stack(struct bpf_verifier_env *env, · 11 unmodified lines
772 err = copy_verifier_state(&elem->st, cur);774 err = copy_verifier_state(&elem->st, cur);
773 if (err)775 if (err)
774 goto err;776 goto err;
777 elem->st.speculative |= speculative;
775 if (env->stack_size > BPF_COMPLEXITY_LIMIT_STACK) {778 if (env->stack_size > BPF_COMPLEXITY_LIMIT_STACK) {
776 verbose(env, "BPF program is too complex\n");779 verbose(env, "BPF program is too complex\n");
777 goto err;780 goto err;
@@ -1387,6 +1390,31 @@ static int check_stack_read(struct bpf_verifier_env *env, · 609 unmodified lines
1387 }1390 }
1388}1391}
1389 1392
1393static int check_stack_access(struct bpf_verifier_env *env,
1394 const struct bpf_reg_state *reg,
1395 int off, int size)
1396{
1397 /* Stack accesses must be at a fixed offset, so that we
1398 * can determine what type of data were returned. See
1399 * check_stack_read().
1400 */
1401 if (!tnum_is_const(reg->var_off)) {
1402 char tn_buf[48];
1403
1404 tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
1405 verbose(env, "variable stack access var_off=%s off=%d size=%d",
1406 tn_buf, off, size);
1407 return -EACCES;
1408 }
1409
1410 if (off >= 0 || off < -MAX_BPF_STACK) {
1411 verbose(env, "invalid stack off=%d size=%d\n", off, size);
1412 return -EACCES;
1413 }
1414
1415 return 0;
1416}
1417
1390/* check read/write into map element returned by bpf_map_lookup_elem() */1418/* check read/write into map element returned by bpf_map_lookup_elem() */
1391static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off,1419static int __check_map_access(struct bpf_verifier_env *env, u32 regno, int off,
1392 int size, bool zero_size_allowed)1420 int size, bool zero_size_allowed)
@@ -1418,13 +1446,17 @@ static int check_map_access(struct bpf_verifier_env *env, u32 regno, · 25 unmodified lines
1418 */1446 */
1419 if (env->log.level)1447 if (env->log.level)
1420 print_verifier_state(env, state);1448 print_verifier_state(env, state);
1449
1421 /* The minimum value is only important with signed1450 /* The minimum value is only important with signed
1422 * comparisons where we can't assume the floor of a1451 * comparisons where we can't assume the floor of a
1423 * value is 0. If we are using signed variables for our1452 * value is 0. If we are using signed variables for our
1424 * index'es we need to make sure that whatever we use1453 * index'es we need to make sure that whatever we use
1425 * will have a set floor within our range.1454 * will have a set floor within our range.
1426 */1455 */
1427 if (reg->smin_value < 0) {1456 if (reg->smin_value < 0 &&
1457 (reg->smin_value == S64_MIN ||
1458 (off + reg->smin_value != (s64)(s32)(off + reg->smin_value)) ||
1459 reg->smin_value + off < 0)) {
1428 verbose(env, "R%d min value is negative, either use unsigned index or do a if (index >=0) check.\n",1460 verbose(env, "R%d min value is negative, either use unsigned index or do a if (index >=0) check.\n",
1429 regno);1461 regno);
1430 return -EACCES;1462 return -EACCES;
@@ -1954,24 +1986,10 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn · 523 unmodified lines
1954 }1986 }
1955 1987
1956 } else if (reg->type == PTR_TO_STACK) {1988 } else if (reg->type == PTR_TO_STACK) {
1957 /* stack accesses must be at a fixed offset, so that we can
1958 * determine what type of data were returned.
1959 * See check_stack_read().
1960 */
1961 if (!tnum_is_const(reg->var_off)) {
1962 char tn_buf[48];
1963
1964 tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
1965 verbose(env, "variable stack access var_off=%s off=%d size=%d",
1966 tn_buf, off, size);
1967 return -EACCES;
1968 }
1969 off += reg->var_off.value;1989 off += reg->var_off.value;
1970 if (off >= 0 || off < -MAX_BPF_STACK) {1990 err = check_stack_access(env, reg, off, size);
1971 verbose(env, "invalid stack off=%d size=%d\n", off,1991 if (err)
1972 size);1992 return err;
1973 return -EACCES;
1974 }
1975 1993
1976 state = func(env, reg);1994 state = func(env, reg);
1977 err = update_stack_depth(env, state, off);1995 err = update_stack_depth(env, state, off);
@@ -3052,6 +3070,102 @@ static bool check_reg_sane_offset(struct bpf_verifier_env *env, · 1074 unmodified lines
3052 return true;3070 return true;
3053}3071}
3054 3072
3073static struct bpf_insn_aux_data *cur_aux(struct bpf_verifier_env *env)
3074{
3075 return &env->insn_aux_data[env->insn_idx];
3076}
3077
3078static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
3079 u32 *ptr_limit, u8 opcode, bool off_is_neg)
3080{
3081 bool mask_to_left = (opcode == BPF_ADD && off_is_neg) ||
3082 (opcode == BPF_SUB && !off_is_neg);
3083 u32 off;
3084
3085 switch (ptr_reg->type) {
3086 case PTR_TO_STACK:
3087 off = ptr_reg->off + ptr_reg->var_off.value;
3088 if (mask_to_left)
3089 *ptr_limit = MAX_BPF_STACK + off;
3090 else
3091 *ptr_limit = -off;
3092 return 0;
3093 case PTR_TO_MAP_VALUE:
3094 if (mask_to_left) {
3095 *ptr_limit = ptr_reg->umax_value + ptr_reg->off;
3096 } else {
3097 off = ptr_reg->smin_value + ptr_reg->off;
3098 *ptr_limit = ptr_reg->map_ptr->value_size - off;
3099 }
3100 return 0;
3101 default:
3102 return -EINVAL;
3103 }
3104}
3105
3106static int sanitize_ptr_alu(struct bpf_verifier_env *env,
3107 struct bpf_insn *insn,
3108 const struct bpf_reg_state *ptr_reg,
3109 struct bpf_reg_state *dst_reg,
3110 bool off_is_neg)
3111{
3112 struct bpf_verifier_state *vstate = env->cur_state;
3113 struct bpf_insn_aux_data *aux = cur_aux(env);
3114 bool ptr_is_dst_reg = ptr_reg == dst_reg;
3115 u8 opcode = BPF_OP(insn->code);
3116 u32 alu_state, alu_limit;
3117 struct bpf_reg_state tmp;
3118 bool ret;
3119
3120 if (env->allow_ptr_leaks || BPF_SRC(insn->code) == BPF_K)
3121 return 0;
3122
3123 /* We already marked aux for masking from non-speculative
3124 * paths, thus we got here in the first place. We only care
3125 * to explore bad access from here.
3126 */
3127 if (vstate->speculative)
3128 goto do_sim;
3129
3130 alu_state = off_is_neg ? BPF_ALU_NEG_VALUE : 0;
3131 alu_state |= ptr_is_dst_reg ?
3132 BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST;
3133
3134 if (retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg))
3135 return 0;
3136
3137 /* If we arrived here from different branches with different
3138 * limits to sanitize, then this won't work.
3139 */
3140 if (aux->alu_state &&
3141 (aux->alu_state != alu_state ||
3142 aux->alu_limit != alu_limit))
3143 return -EACCES;
3144
3145 /* Corresponding fixup done in fixup_bpf_calls(). */
3146 aux->alu_state = alu_state;
3147 aux->alu_limit = alu_limit;
3148
3149do_sim:
3150 /* Simulate and find potential out-of-bounds access under
3151 * speculative execution from truncation as a result of
3152 * masking when off was not within expected range. If off
3153 * sits in dst, then we temporarily need to move ptr there
3154 * to simulate dst (== 0) +/-= ptr. Needed, for example,
3155 * for cases where we use K-based arithmetic in one direction
3156 * and truncated reg-based in the other in order to explore
3157 * bad access.
3158 */
3159 if (!ptr_is_dst_reg) {
3160 tmp = *dst_reg;
3161 *dst_reg = *ptr_reg;
3162 }
3163 ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true);
3164 if (!ptr_is_dst_reg)
3165 *dst_reg = tmp;
3166 return !ret ? -EFAULT : 0;
3167}
3168
3055/* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.3169/* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.
3056 * Caller should also handle BPF_MOV case separately.3170 * Caller should also handle BPF_MOV case separately.
3057 * If we return -EACCES, caller may want to try again treating pointer as a3171 * If we return -EACCES, caller may want to try again treating pointer as a
@@ -3070,8 +3184,9 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 12 unmodified lines
3070 smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value;3184 smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value;
3071 u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value,3185 u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value,
3072 umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value;3186 umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value;
3187 u32 dst = insn->dst_reg, src = insn->src_reg;
3073 u8 opcode = BPF_OP(insn->code);3188 u8 opcode = BPF_OP(insn->code);
3074 u32 dst = insn->dst_reg;3189 int ret;
3075 3190
3076 dst_reg = &regs[dst];3191 dst_reg = &regs[dst];
3077 3192
@@ -3104,6 +3219,13 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 26 unmodified lines
3104 verbose(env, "R%d pointer arithmetic on %s prohibited\n",3219 verbose(env, "R%d pointer arithmetic on %s prohibited\n",
3105 dst, reg_type_str[ptr_reg->type]);3220 dst, reg_type_str[ptr_reg->type]);
3106 return -EACCES;3221 return -EACCES;
3222 case PTR_TO_MAP_VALUE:
3223 if (!env->allow_ptr_leaks && !known && (smin_val < 0) != (smax_val < 0)) {
3224 verbose(env, "R%d has unknown scalar with mixed signed bounds, pointer arithmetic with it prohibited for !root\n",
3225 off_reg == dst_reg ? dst : src);
3226 return -EACCES;
3227 }
3228 /* fall-through */
3107 default:3229 default:
3108 break;3230 break;
3109 }3231 }
@@ -3120,6 +3242,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 10 unmodified lines
3120 3242
3121 switch (opcode) {3243 switch (opcode) {
3122 case BPF_ADD:3244 case BPF_ADD:
3245 ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0);
3246 if (ret < 0) {
3247 verbose(env, "R%d tried to add from different maps or paths\n", dst);
3248 return ret;
3249 }
3123 /* We can take a fixed offset as long as it doesn't overflow3250 /* We can take a fixed offset as long as it doesn't overflow
3124 * the s32 'off' field3251 * the s32 'off' field
3125 */3252 */
@@ -3170,6 +3297,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 44 unmodified lines
3170 }3297 }
3171 break;3298 break;
3172 case BPF_SUB:3299 case BPF_SUB:
3300 ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0);
3301 if (ret < 0) {
3302 verbose(env, "R%d tried to sub from different maps or paths\n", dst);
3303 return ret;
3304 }
3173 if (dst_reg == off_reg) {3305 if (dst_reg == off_reg) {
3174 /* scalar -= pointer. Creates an unknown scalar */3306 /* scalar -= pointer. Creates an unknown scalar */
3175 verbose(env, "R%d tried to subtract pointer from scalar\n",3307 verbose(env, "R%d tried to subtract pointer from scalar\n",
@@ -3249,6 +3381,25 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · 73 unmodified lines
3249 __update_reg_bounds(dst_reg);3381 __update_reg_bounds(dst_reg);
3250 __reg_deduce_bounds(dst_reg);3382 __reg_deduce_bounds(dst_reg);
3251 __reg_bound_offset(dst_reg);3383 __reg_bound_offset(dst_reg);
3384
3385 /* For unprivileged we require that resulting offset must be in bounds
3386 * in order to be able to sanitize access later on.
3387 */
3388 if (!env->allow_ptr_leaks) {
3389 if (dst_reg->type == PTR_TO_MAP_VALUE &&
3390 check_map_access(env, dst, dst_reg->off, 1, false)) {
3391 verbose(env, "R%d pointer arithmetic of map value goes out of range, "
3392 "prohibited for !root\n", dst);
3393 return -EACCES;
3394 } else if (dst_reg->type == PTR_TO_STACK &&
3395 check_stack_access(env, dst_reg, dst_reg->off +
3396 dst_reg->var_off.value, 1)) {
3397 verbose(env, "R%d stack pointer arithmetic goes out of range, "
3398 "prohibited for !root\n", dst);
3399 return -EACCES;
3400 }
3401 }
3402
3252 return 0;3403 return 0;
3253}3404}
3254 3405
@@ -4348,7 +4499,8 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env, · 1093 unmodified lines
4348 }4499 }
4349 }4500 }
4350 4501
4351 other_branch = push_stack(env, *insn_idx + insn->off + 1, *insn_idx);4502 other_branch = push_stack(env, *insn_idx + insn->off + 1, *insn_idx,
4503 false);
4352 if (!other_branch)4504 if (!other_branch)
4353 return -EFAULT;4505 return -EFAULT;
4354 other_branch_regs = other_branch->frame[other_branch->curframe]->regs;4506 other_branch_regs = other_branch->frame[other_branch->curframe]->regs;
@@ -5458,6 +5610,12 @@ static bool states_equal(struct bpf_verifier_env *env, · 1103 unmodified lines
5458 if (old->curframe != cur->curframe)5610 if (old->curframe != cur->curframe)
5459 return false;5611 return false;
5460 5612
5613 /* Verification state from speculative execution simulation
5614 * must never prune a non-speculative execution one.
5615 */
5616 if (old->speculative && !cur->speculative)
5617 return false;
5618
5461 /* for states to be equal callsites have to be the same5619 /* for states to be equal callsites have to be the same
5462 * and all frame states need to be equivalent5620 * and all frame states need to be equivalent
5463 */5621 */
@@ -5650,7 +5808,6 @@ static int do_check(struct bpf_verifier_env *env) · 186 unmodified lines
5650 struct bpf_insn *insns = env->prog->insnsi;5808 struct bpf_insn *insns = env->prog->insnsi;
5651 struct bpf_reg_state *regs;5809 struct bpf_reg_state *regs;
5652 int insn_cnt = env->prog->len, i;5810 int insn_cnt = env->prog->len, i;
5653 int insn_idx, prev_insn_idx = 0;
5654 int insn_processed = 0;5811 int insn_processed = 0;
5655 bool do_print_state = false;5812 bool do_print_state = false;
5656 5813
@@ -5660,6 +5817,7 @@ static int do_check(struct bpf_verifier_env *env) · 3 unmodified lines
5660 if (!state)5817 if (!state)
5661 return -ENOMEM;5818 return -ENOMEM;
5662 state->curframe = 0;5819 state->curframe = 0;
5820 state->speculative = false;
5663 state->frame[0] = kzalloc(sizeof(struct bpf_func_state), GFP_KERNEL);5821 state->frame[0] = kzalloc(sizeof(struct bpf_func_state), GFP_KERNEL);
5664 if (!state->frame[0]) {5822 if (!state->frame[0]) {
5665 kfree(state);5823 kfree(state);
@@ -5670,19 +5828,19 @@ static int do_check(struct bpf_verifier_env *env) · 4 unmodified lines
5670 BPF_MAIN_FUNC /* callsite */,5828 BPF_MAIN_FUNC /* callsite */,
5671 0 /* frameno */,5829 0 /* frameno */,
5672 0 /* subprogno, zero == main subprog */);5830 0 /* subprogno, zero == main subprog */);
5673 insn_idx = 0;5831
5674 for (;;) {5832 for (;;) {
5675 struct bpf_insn *insn;5833 struct bpf_insn *insn;
5676 u8 class;5834 u8 class;
5677 int err;5835 int err;
5678 5836
5679 if (insn_idx >= insn_cnt) {5837 if (env->insn_idx >= insn_cnt) {
5680 verbose(env, "invalid insn idx %d insn_cnt %d\n",5838 verbose(env, "invalid insn idx %d insn_cnt %d\n",
5681 insn_idx, insn_cnt);5839 env->insn_idx, insn_cnt);
5682 return -EFAULT;5840 return -EFAULT;
5683 }5841 }
5684 5842
5685 insn = &insns[insn_idx];5843 insn = &insns[env->insn_idx];
5686 class = BPF_CLASS(insn->code);5844 class = BPF_CLASS(insn->code);
5687 5845
5688 if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) {5846 if (++insn_processed > BPF_COMPLEXITY_LIMIT_INSNS) {
@@ -5692,17 +5850,19 @@ static int do_check(struct bpf_verifier_env *env) · 3 unmodified lines
5692 return -E2BIG;5850 return -E2BIG;
5693 }5851 }
5694 5852
5695 err = is_state_visited(env, insn_idx);5853 err = is_state_visited(env, env->insn_idx);
5696 if (err < 0)5854 if (err < 0)
5697 return err;5855 return err;
5698 if (err == 1) {5856 if (err == 1) {
5699 /* found equivalent state, can prune the search */5857 /* found equivalent state, can prune the search */
5700 if (env->log.level) {5858 if (env->log.level) {
5701 if (do_print_state)5859 if (do_print_state)
5702 verbose(env, "\nfrom %d to %d: safe\n",5860 verbose(env, "\nfrom %d to %d%s: safe\n",
5703 prev_insn_idx, insn_idx);5861 env->prev_insn_idx, env->insn_idx,
5862 env->cur_state->speculative ?
5863 " (speculative execution)" : "");
5704 else5864 else
5705 verbose(env, "%d: safe\n", insn_idx);5865 verbose(env, "%d: safe\n", env->insn_idx);
5706 }5866 }
5707 goto process_bpf_exit;5867 goto process_bpf_exit;
5708 }5868 }
@@ -5715,10 +5875,12 @@ static int do_check(struct bpf_verifier_env *env) · 6 unmodified lines
5715 5875
5716 if (env->log.level > 1 || (env->log.level && do_print_state)) {5876 if (env->log.level > 1 || (env->log.level && do_print_state)) {
5717 if (env->log.level > 1)5877 if (env->log.level > 1)
5718 verbose(env, "%d:", insn_idx);5878 verbose(env, "%d:", env->insn_idx);
5719 else5879 else
5720 verbose(env, "\nfrom %d to %d:",5880 verbose(env, "\nfrom %d to %d%s:",
5721 prev_insn_idx, insn_idx);5881 env->prev_insn_idx, env->insn_idx,
5882 env->cur_state->speculative ?
5883 " (speculative execution)" : "");
5722 print_verifier_state(env, state->frame[state->curframe]);5884 print_verifier_state(env, state->frame[state->curframe]);
5723 do_print_state = false;5885 do_print_state = false;
5724 }5886 }
@@ -5729,20 +5891,20 @@ static int do_check(struct bpf_verifier_env *env) · 4 unmodified lines
5729 .private_data = env,5891 .private_data = env,
5730 };5892 };
5731 5893
5732 verbose_linfo(env, insn_idx, "; ");5894 verbose_linfo(env, env->insn_idx, "; ");
5733 verbose(env, "%d: ", insn_idx);5895 verbose(env, "%d: ", env->insn_idx);
5734 print_bpf_insn(&cbs, insn, env->allow_ptr_leaks);5896 print_bpf_insn(&cbs, insn, env->allow_ptr_leaks);
5735 }5897 }
5736 5898
5737 if (bpf_prog_is_dev_bound(env->prog->aux)) {5899 if (bpf_prog_is_dev_bound(env->prog->aux)) {
5738 err = bpf_prog_offload_verify_insn(env, insn_idx,5900 err = bpf_prog_offload_verify_insn(env, env->insn_idx,
5739 prev_insn_idx);5901 env->prev_insn_idx);
5740 if (err)5902 if (err)
5741 return err;5903 return err;
5742 }5904 }
5743 5905
5744 regs = cur_regs(env);5906 regs = cur_regs(env);
5745 env->insn_aux_data[insn_idx].seen = true;5907 env->insn_aux_data[env->insn_idx].seen = true;
5746 5908
5747 if (class == BPF_ALU || class == BPF_ALU64) {5909 if (class == BPF_ALU || class == BPF_ALU64) {
5748 err = check_alu_op(env, insn);5910 err = check_alu_op(env, insn);
@@ -5768,13 +5930,13 @@ static int do_check(struct bpf_verifier_env *env) · 19 unmodified lines
5768 /* check that memory (src_reg + off) is readable,5930 /* check that memory (src_reg + off) is readable,
5769 * the state of dst_reg will be updated by this func5931 * the state of dst_reg will be updated by this func
5770 */5932 */
5771 err = check_mem_access(env, insn_idx, insn->src_reg, insn->off,5933 err = check_mem_access(env, env->insn_idx, insn->src_reg,
5772 BPF_SIZE(insn->code), BPF_READ,5934 insn->off, BPF_SIZE(insn->code),
5773 insn->dst_reg, false);5935 BPF_READ, insn->dst_reg, false);
5774 if (err)5936 if (err)
5775 return err;5937 return err;
5776 5938
5777 prev_src_type = &env->insn_aux_data[insn_idx].ptr_type;5939 prev_src_type = &env->insn_aux_data[env->insn_idx].ptr_type;
5778 5940
5779 if (*prev_src_type == NOT_INIT) {5941 if (*prev_src_type == NOT_INIT) {
5780 /* saw a valid insn5942 /* saw a valid insn
@@ -5799,10 +5961,10 @@ static int do_check(struct bpf_verifier_env *env) · 18 unmodified lines
5799 enum bpf_reg_type *prev_dst_type, dst_reg_type;5961 enum bpf_reg_type *prev_dst_type, dst_reg_type;
5800 5962
5801 if (BPF_MODE(insn->code) == BPF_XADD) {5963 if (BPF_MODE(insn->code) == BPF_XADD) {
5802 err = check_xadd(env, insn_idx, insn);5964 err = check_xadd(env, env->insn_idx, insn);
5803 if (err)5965 if (err)
5804 return err;5966 return err;
5805 insn_idx++;5967 env->insn_idx++;
5806 continue;5968 continue;
5807 }5969 }
5808 5970
@@ -5818,13 +5980,13 @@ static int do_check(struct bpf_verifier_env *env) · 9 unmodified lines
5818 dst_reg_type = regs[insn->dst_reg].type;5980 dst_reg_type = regs[insn->dst_reg].type;
5819 5981
5820 /* check that memory (dst_reg + off) is writeable */5982 /* check that memory (dst_reg + off) is writeable */
5821 err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,5983 err = check_mem_access(env, env->insn_idx, insn->dst_reg,
5822 BPF_SIZE(insn->code), BPF_WRITE,5984 insn->off, BPF_SIZE(insn->code),
5823 insn->src_reg, false);5985 BPF_WRITE, insn->src_reg, false);
5824 if (err)5986 if (err)
5825 return err;5987 return err;
5826 5988
5827 prev_dst_type = &env->insn_aux_data[insn_idx].ptr_type;5989 prev_dst_type = &env->insn_aux_data[env->insn_idx].ptr_type;
5828 5990
5829 if (*prev_dst_type == NOT_INIT) {5991 if (*prev_dst_type == NOT_INIT) {
5830 *prev_dst_type = dst_reg_type;5992 *prev_dst_type = dst_reg_type;
@@ -5852,9 +6014,9 @@ static int do_check(struct bpf_verifier_env *env) · 21 unmodified lines
5852 }6014 }
5853 6015
5854 /* check that memory (dst_reg + off) is writeable */6016 /* check that memory (dst_reg + off) is writeable */
5855 err = check_mem_access(env, insn_idx, insn->dst_reg, insn->off,6017 err = check_mem_access(env, env->insn_idx, insn->dst_reg,
5856 BPF_SIZE(insn->code), BPF_WRITE,6018 insn->off, BPF_SIZE(insn->code),
5857 -1, false);6019 BPF_WRITE, -1, false);
5858 if (err)6020 if (err)
5859 return err;6021 return err;
5860 6022
@@ -5872,9 +6034,9 @@ static int do_check(struct bpf_verifier_env *env) · 11 unmodified lines
5872 }6034 }
5873 6035
5874 if (insn->src_reg == BPF_PSEUDO_CALL)6036 if (insn->src_reg == BPF_PSEUDO_CALL)
5875 err = check_func_call(env, insn, &insn_idx);6037 err = check_func_call(env, insn, &env->insn_idx);
5876 else6038 else
5877 err = check_helper_call(env, insn->imm, insn_idx);6039 err = check_helper_call(env, insn->imm, env->insn_idx);
5878 if (err)6040 if (err)
5879 return err;6041 return err;
5880 6042
@@ -5887,7 +6049,7 @@ static int do_check(struct bpf_verifier_env *env) · 6 unmodified lines
5887 return -EINVAL;6049 return -EINVAL;
5888 }6050 }
5889 6051
5890 insn_idx += insn->off + 1;6052 env->insn_idx += insn->off + 1;
5891 continue;6053 continue;
5892 6054
5893 } else if (opcode == BPF_EXIT) {6055 } else if (opcode == BPF_EXIT) {
@@ -5901,8 +6063,8 @@ static int do_check(struct bpf_verifier_env *env) · 7 unmodified lines
5901 6063
5902 if (state->curframe) {6064 if (state->curframe) {
5903 /* exit from nested function */6065 /* exit from nested function */
5904 prev_insn_idx = insn_idx;6066 env->prev_insn_idx = env->insn_idx;
5905 err = prepare_func_exit(env, &insn_idx);6067 err = prepare_func_exit(env, &env->insn_idx);
5906 if (err)6068 if (err)
5907 return err;6069 return err;
5908 do_print_state = true;6070 do_print_state = true;
@@ -5932,7 +6094,8 @@ static int do_check(struct bpf_verifier_env *env) · 23 unmodified lines
5932 if (err)6094 if (err)
5933 return err;6095 return err;
5934process_bpf_exit:6096process_bpf_exit:
5935 err = pop_stack(env, &prev_insn_idx, &insn_idx);6097 err = pop_stack(env, &env->prev_insn_idx,
6098 &env->insn_idx);
5936 if (err < 0) {6099 if (err < 0) {
5937 if (err != -ENOENT)6100 if (err != -ENOENT)
5938 return err;6101 return err;
@@ -5942,7 +6105,7 @@ process_bpf_exit: · 3 unmodified lines
5942 continue;6105 continue;
5943 }6106 }
5944 } else {6107 } else {
5945 err = check_cond_jmp_op(env, insn, &insn_idx);6108 err = check_cond_jmp_op(env, insn, &env->insn_idx);
5946 if (err)6109 if (err)
5947 return err;6110 return err;
5948 }6111 }
@@ -5959,8 +6122,8 @@ process_bpf_exit: · 10 unmodified lines
5959 if (err)6122 if (err)
5960 return err;6123 return err;
5961 6124
5962 insn_idx++;6125 env->insn_idx++;
5963 env->insn_aux_data[insn_idx].seen = true;6126 env->insn_aux_data[env->insn_idx].seen = true;
5964 } else {6127 } else {
5965 verbose(env, "invalid BPF_LD mode\n");6128 verbose(env, "invalid BPF_LD mode\n");
5966 return -EINVAL;6129 return -EINVAL;
@@ -5970,7 +6133,7 @@ process_bpf_exit: · 3 unmodified lines
5970 return -EINVAL;6133 return -EINVAL;
5971 }6134 }
5972 6135
5973 insn_idx++;6136 env->insn_idx++;
5974 }6137 }
5975 6138
5976 verbose(env, "processed %d insns (limit %d), stack depth ",6139 verbose(env, "processed %d insns (limit %d), stack depth ",
@@ -6709,6 +6872,57 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env) · 732 unmodified lines
6709 continue;6872 continue;
6710 }6873 }
6711 6874
6875 if (insn->code == (BPF_ALU64 | BPF_ADD | BPF_X) ||
6876 insn->code == (BPF_ALU64 | BPF_SUB | BPF_X)) {
6877 const u8 code_add = BPF_ALU64 | BPF_ADD | BPF_X;
6878 const u8 code_sub = BPF_ALU64 | BPF_SUB | BPF_X;
6879 struct bpf_insn insn_buf[16];
6880 struct bpf_insn *patch = &insn_buf[0];
6881 bool issrc, isneg;
6882 u32 off_reg;
6883
6884 aux = &env->insn_aux_data[i + delta];
6885 if (!aux->alu_state)
6886 continue;
6887
6888 isneg = aux->alu_state & BPF_ALU_NEG_VALUE;
6889 issrc = (aux->alu_state & BPF_ALU_SANITIZE) ==
6890 BPF_ALU_SANITIZE_SRC;
6891
6892 off_reg = issrc ? insn->src_reg : insn->dst_reg;
6893 if (isneg)
6894 *patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
6895 *patch++ = BPF_MOV32_IMM(BPF_REG_AX, aux->alu_limit - 1);
6896 *patch++ = BPF_ALU64_REG(BPF_SUB, BPF_REG_AX, off_reg);
6897 *patch++ = BPF_ALU64_REG(BPF_OR, BPF_REG_AX, off_reg);
6898 *patch++ = BPF_ALU64_IMM(BPF_NEG, BPF_REG_AX, 0);
6899 *patch++ = BPF_ALU64_IMM(BPF_ARSH, BPF_REG_AX, 63);
6900 if (issrc) {
6901 *patch++ = BPF_ALU64_REG(BPF_AND, BPF_REG_AX,
6902 off_reg);
6903 insn->src_reg = BPF_REG_AX;
6904 } else {
6905 *patch++ = BPF_ALU64_REG(BPF_AND, off_reg,
6906 BPF_REG_AX);
6907 }
6908 if (isneg)
6909 insn->code = insn->code == code_add ?
6910 code_sub : code_add;
6911 *patch++ = *insn;
6912 if (issrc && isneg)
6913 *patch++ = BPF_ALU64_IMM(BPF_MUL, off_reg, -1);
6914 cnt = patch - insn_buf;
6915
6916 new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
6917 if (!new_prog)
6918 return -ENOMEM;
6919
6920 delta += cnt - 1;
6921 env->prog = prog = new_prog;
6922 insn = new_prog->insnsi + i + delta;
6923 continue;
6924 }
6925
6712 if (insn->code != (BPF_JMP | BPF_CALL))6926 if (insn->code != (BPF_JMP | BPF_CALL))
6713 continue;6927 continue;
6714 if (insn->src_reg == BPF_PSEUDO_CALL)6928 if (insn->src_reg == BPF_PSEUDO_CALL)
tools/testing/selftests/bpf/test_maps.c+1−1
@@ -510,7 +510,7 @@ static void test_devmap(int task, void *data) · 509 unmodified lines
510 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),510 fd = bpf_create_map(BPF_MAP_TYPE_DEVMAP, sizeof(key), sizeof(value),
511 2, 0);511 2, 0);
512 if (fd < 0) {512 if (fd < 0) {
513 printf("Failed to create arraymap '%s'!\n", strerror(errno));513 printf("Failed to create devmap '%s'!\n", strerror(errno));
514 exit(1);514 exit(1);
515 }515 }
516 516
tools/testing/selftests/bpf/test_verifier.c+1124−22
@@ -23,6 +23,7 @@ · 22 unmodified lines
23#include <stdbool.h>23#include <stdbool.h>
24#include <sched.h>24#include <sched.h>
25#include <limits.h>25#include <limits.h>
26#include <assert.h>
26 27
27#include <sys/capability.h>28#include <sys/capability.h>
28 29
@@ -2577,6 +2578,7 @@ static struct bpf_test tests[] = { · 2548 unmodified lines
2577 },2578 },
2578 .result = REJECT,2579 .result = REJECT,
2579 .errstr = "invalid stack off=-79992 size=8",2580 .errstr = "invalid stack off=-79992 size=8",
2581 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
2580 },2582 },
2581 {2583 {
2582 "PTR_TO_STACK store/load - out of bounds high",2584 "PTR_TO_STACK store/load - out of bounds high",
@@ -3104,6 +3106,8 @@ static struct bpf_test tests[] = { · 521 unmodified lines
3104 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),3106 BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
3105 BPF_EXIT_INSN(),3107 BPF_EXIT_INSN(),
3106 },3108 },
3109 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
3110 .result_unpriv = REJECT,
3107 .result = ACCEPT,3111 .result = ACCEPT,
3108 },3112 },
3109 {3113 {
@@ -3205,6 +3209,243 @@ static struct bpf_test tests[] = { · 95 unmodified lines
3205 /* Verifier rewrite for unpriv skips tail call here. */3209 /* Verifier rewrite for unpriv skips tail call here. */
3206 .retval_unpriv = 2,3210 .retval_unpriv = 2,
3207 },3211 },
3212 {
3213 "PTR_TO_STACK check high 1",
3214 .insns = {
3215 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3216 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -1),
3217 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3218 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3219 BPF_EXIT_INSN(),
3220 },
3221 .result = ACCEPT,
3222 .retval = 42,
3223 },
3224 {
3225 "PTR_TO_STACK check high 2",
3226 .insns = {
3227 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3228 BPF_ST_MEM(BPF_B, BPF_REG_1, -1, 42),
3229 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, -1),
3230 BPF_EXIT_INSN(),
3231 },
3232 .result = ACCEPT,
3233 .retval = 42,
3234 },
3235 {
3236 "PTR_TO_STACK check high 3",
3237 .insns = {
3238 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3239 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0),
3240 BPF_ST_MEM(BPF_B, BPF_REG_1, -1, 42),
3241 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, -1),
3242 BPF_EXIT_INSN(),
3243 },
3244 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
3245 .result_unpriv = REJECT,
3246 .result = ACCEPT,
3247 .retval = 42,
3248 },
3249 {
3250 "PTR_TO_STACK check high 4",
3251 .insns = {
3252 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3253 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, 0),
3254 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3255 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3256 BPF_EXIT_INSN(),
3257 },
3258 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
3259 .errstr = "invalid stack off=0 size=1",
3260 .result = REJECT,
3261 },
3262 {
3263 "PTR_TO_STACK check high 5",
3264 .insns = {
3265 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3266 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, (1 << 29) - 1),
3267 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3268 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3269 BPF_EXIT_INSN(),
3270 },
3271 .result = REJECT,
3272 .errstr = "invalid stack off",
3273 },
3274 {
3275 "PTR_TO_STACK check high 6",
3276 .insns = {
3277 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3278 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, (1 << 29) - 1),
3279 BPF_ST_MEM(BPF_B, BPF_REG_1, SHRT_MAX, 42),
3280 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, SHRT_MAX),
3281 BPF_EXIT_INSN(),
3282 },
3283 .result = REJECT,
3284 .errstr = "invalid stack off",
3285 },
3286 {
3287 "PTR_TO_STACK check high 7",
3288 .insns = {
3289 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3290 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, (1 << 29) - 1),
3291 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, (1 << 29) - 1),
3292 BPF_ST_MEM(BPF_B, BPF_REG_1, SHRT_MAX, 42),
3293 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, SHRT_MAX),
3294 BPF_EXIT_INSN(),
3295 },
3296 .result = REJECT,
3297 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
3298 .errstr = "fp pointer offset",
3299 },
3300 {
3301 "PTR_TO_STACK check low 1",
3302 .insns = {
3303 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3304 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -512),
3305 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3306 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3307 BPF_EXIT_INSN(),
3308 },
3309 .result = ACCEPT,
3310 .retval = 42,
3311 },
3312 {
3313 "PTR_TO_STACK check low 2",
3314 .insns = {
3315 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3316 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -513),
3317 BPF_ST_MEM(BPF_B, BPF_REG_1, 1, 42),
3318 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 1),
3319 BPF_EXIT_INSN(),
3320 },
3321 .result_unpriv = REJECT,
3322 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
3323 .result = ACCEPT,
3324 .retval = 42,
3325 },
3326 {
3327 "PTR_TO_STACK check low 3",
3328 .insns = {
3329 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3330 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -513),
3331 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3332 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3333 BPF_EXIT_INSN(),
3334 },
3335 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
3336 .errstr = "invalid stack off=-513 size=1",
3337 .result = REJECT,
3338 },
3339 {
3340 "PTR_TO_STACK check low 4",
3341 .insns = {
3342 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3343 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, INT_MIN),
3344 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3345 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3346 BPF_EXIT_INSN(),
3347 },
3348 .result = REJECT,
3349 .errstr = "math between fp pointer",
3350 },
3351 {
3352 "PTR_TO_STACK check low 5",
3353 .insns = {
3354 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3355 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -((1 << 29) - 1)),
3356 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3357 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3358 BPF_EXIT_INSN(),
3359 },
3360 .result = REJECT,
3361 .errstr = "invalid stack off",
3362 },
3363 {
3364 "PTR_TO_STACK check low 6",
3365 .insns = {
3366 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3367 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -((1 << 29) - 1)),
3368 BPF_ST_MEM(BPF_B, BPF_REG_1, SHRT_MIN, 42),
3369 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, SHRT_MIN),
3370 BPF_EXIT_INSN(),
3371 },
3372 .result = REJECT,
3373 .errstr = "invalid stack off",
3374 },
3375 {
3376 "PTR_TO_STACK check low 7",
3377 .insns = {
3378 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3379 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -((1 << 29) - 1)),
3380 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -((1 << 29) - 1)),
3381 BPF_ST_MEM(BPF_B, BPF_REG_1, SHRT_MIN, 42),
3382 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, SHRT_MIN),
3383 BPF_EXIT_INSN(),
3384 },
3385 .result = REJECT,
3386 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
3387 .errstr = "fp pointer offset",
3388 },
3389 {
3390 "PTR_TO_STACK mixed reg/k, 1",
3391 .insns = {
3392 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3393 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -3),
3394 BPF_MOV64_IMM(BPF_REG_2, -3),
3395 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
3396 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3397 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3398 BPF_EXIT_INSN(),
3399 },
3400 .result = ACCEPT,
3401 .retval = 42,
3402 },
3403 {
3404 "PTR_TO_STACK mixed reg/k, 2",
3405 .insns = {
3406 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
3407 BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
3408 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3409 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -3),
3410 BPF_MOV64_IMM(BPF_REG_2, -3),
3411 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
3412 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3413 BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
3414 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_5, -6),
3415 BPF_EXIT_INSN(),
3416 },
3417 .result = ACCEPT,
3418 .retval = 42,
3419 },
3420 {
3421 "PTR_TO_STACK mixed reg/k, 3",
3422 .insns = {
3423 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3424 BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -3),
3425 BPF_MOV64_IMM(BPF_REG_2, -3),
3426 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
3427 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3428 BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
3429 BPF_EXIT_INSN(),
3430 },
3431 .result = ACCEPT,
3432 .retval = -3,
3433 },
3434 {
3435 "PTR_TO_STACK reg",
3436 .insns = {
3437 BPF_MOV64_REG(BPF_REG_1, BPF_REG_10),
3438 BPF_MOV64_IMM(BPF_REG_2, -3),
3439 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
3440 BPF_ST_MEM(BPF_B, BPF_REG_1, 0, 42),
3441 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
3442 BPF_EXIT_INSN(),
3443 },
3444 .result_unpriv = REJECT,
3445 .errstr_unpriv = "invalid stack off=0 size=1",
3446 .result = ACCEPT,
3447 .retval = 42,
3448 },
3208 {3449 {
3209 "stack pointer arithmetic",3450 "stack pointer arithmetic",
3210 .insns = {3451 .insns = {
@@ -6610,7 +6851,446 @@ static struct bpf_test tests[] = { · 3399 unmodified lines
6610 .prog_type = BPF_PROG_TYPE_TRACEPOINT,6851 .prog_type = BPF_PROG_TYPE_TRACEPOINT,
6611 },6852 },
6612 {6853 {
6613 "map access: known scalar += value_ptr",6854 "map access: known scalar += value_ptr from different maps",
6855 .insns = {
6856 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
6857 offsetof(struct __sk_buff, len)),
6858 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6859 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6860 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6861 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 1, 3),
6862 BPF_LD_MAP_FD(BPF_REG_1, 0),
6863 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 1, 2),
6864 BPF_LD_MAP_FD(BPF_REG_1, 0),
6865 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6866 BPF_FUNC_map_lookup_elem),
6867 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
6868 BPF_MOV64_IMM(BPF_REG_1, 4),
6869 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
6870 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
6871 BPF_MOV64_IMM(BPF_REG_0, 1),
6872 BPF_EXIT_INSN(),
6873 },
6874 .fixup_map_hash_16b = { 5 },
6875 .fixup_map_array_48b = { 8 },
6876 .result = ACCEPT,
6877 .result_unpriv = REJECT,
6878 .errstr_unpriv = "R1 tried to add from different maps",
6879 .retval = 1,
6880 },
6881 {
6882 "map access: value_ptr -= known scalar from different maps",
6883 .insns = {
6884 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
6885 offsetof(struct __sk_buff, len)),
6886 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6887 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6888 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6889 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 1, 3),
6890 BPF_LD_MAP_FD(BPF_REG_1, 0),
6891 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 1, 2),
6892 BPF_LD_MAP_FD(BPF_REG_1, 0),
6893 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6894 BPF_FUNC_map_lookup_elem),
6895 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6896 BPF_MOV64_IMM(BPF_REG_1, 4),
6897 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6898 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6899 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6900 BPF_MOV64_IMM(BPF_REG_0, 1),
6901 BPF_EXIT_INSN(),
6902 },
6903 .fixup_map_hash_16b = { 5 },
6904 .fixup_map_array_48b = { 8 },
6905 .result = ACCEPT,
6906 .result_unpriv = REJECT,
6907 .errstr_unpriv = "R0 min value is outside of the array range",
6908 .retval = 1,
6909 },
6910 {
6911 "map access: known scalar += value_ptr from different maps, but same value properties",
6912 .insns = {
6913 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1,
6914 offsetof(struct __sk_buff, len)),
6915 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6916 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6917 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6918 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 1, 3),
6919 BPF_LD_MAP_FD(BPF_REG_1, 0),
6920 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 1, 2),
6921 BPF_LD_MAP_FD(BPF_REG_1, 0),
6922 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6923 BPF_FUNC_map_lookup_elem),
6924 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
6925 BPF_MOV64_IMM(BPF_REG_1, 4),
6926 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
6927 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
6928 BPF_MOV64_IMM(BPF_REG_0, 1),
6929 BPF_EXIT_INSN(),
6930 },
6931 .fixup_map_hash_48b = { 5 },
6932 .fixup_map_array_48b = { 8 },
6933 .result = ACCEPT,
6934 .retval = 1,
6935 },
6936 {
6937 "map access: value_ptr += known scalar, upper oob arith, test 1",
6938 .insns = {
6939 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6940 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6941 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6942 BPF_LD_MAP_FD(BPF_REG_1, 0),
6943 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6944 BPF_FUNC_map_lookup_elem),
6945 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6946 BPF_MOV64_IMM(BPF_REG_1, 48),
6947 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6948 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6949 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6950 BPF_MOV64_IMM(BPF_REG_0, 1),
6951 BPF_EXIT_INSN(),
6952 },
6953 .fixup_map_array_48b = { 3 },
6954 .result = ACCEPT,
6955 .result_unpriv = REJECT,
6956 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
6957 .retval = 1,
6958 },
6959 {
6960 "map access: value_ptr += known scalar, upper oob arith, test 2",
6961 .insns = {
6962 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6963 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6964 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6965 BPF_LD_MAP_FD(BPF_REG_1, 0),
6966 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6967 BPF_FUNC_map_lookup_elem),
6968 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6969 BPF_MOV64_IMM(BPF_REG_1, 49),
6970 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6971 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6972 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6973 BPF_MOV64_IMM(BPF_REG_0, 1),
6974 BPF_EXIT_INSN(),
6975 },
6976 .fixup_map_array_48b = { 3 },
6977 .result = ACCEPT,
6978 .result_unpriv = REJECT,
6979 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
6980 .retval = 1,
6981 },
6982 {
6983 "map access: value_ptr += known scalar, upper oob arith, test 3",
6984 .insns = {
6985 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6986 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
6987 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
6988 BPF_LD_MAP_FD(BPF_REG_1, 0),
6989 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6990 BPF_FUNC_map_lookup_elem),
6991 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6992 BPF_MOV64_IMM(BPF_REG_1, 47),
6993 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6994 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
6995 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6996 BPF_MOV64_IMM(BPF_REG_0, 1),
6997 BPF_EXIT_INSN(),
6998 },
6999 .fixup_map_array_48b = { 3 },
7000 .result = ACCEPT,
7001 .result_unpriv = REJECT,
7002 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
7003 .retval = 1,
7004 },
7005 {
7006 "map access: value_ptr -= known scalar, lower oob arith, test 1",
7007 .insns = {
7008 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7009 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7010 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7011 BPF_LD_MAP_FD(BPF_REG_1, 0),
7012 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7013 BPF_FUNC_map_lookup_elem),
7014 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
7015 BPF_MOV64_IMM(BPF_REG_1, 47),
7016 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7017 BPF_MOV64_IMM(BPF_REG_1, 48),
7018 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
7019 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
7020 BPF_MOV64_IMM(BPF_REG_0, 1),
7021 BPF_EXIT_INSN(),
7022 },
7023 .fixup_map_array_48b = { 3 },
7024 .result = REJECT,
7025 .errstr = "R0 min value is outside of the array range",
7026 .result_unpriv = REJECT,
7027 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
7028 },
7029 {
7030 "map access: value_ptr -= known scalar, lower oob arith, test 2",
7031 .insns = {
7032 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7033 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7034 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7035 BPF_LD_MAP_FD(BPF_REG_1, 0),
7036 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7037 BPF_FUNC_map_lookup_elem),
7038 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
7039 BPF_MOV64_IMM(BPF_REG_1, 47),
7040 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7041 BPF_MOV64_IMM(BPF_REG_1, 48),
7042 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
7043 BPF_MOV64_IMM(BPF_REG_1, 1),
7044 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7045 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
7046 BPF_MOV64_IMM(BPF_REG_0, 1),
7047 BPF_EXIT_INSN(),
7048 },
7049 .fixup_map_array_48b = { 3 },
7050 .result = ACCEPT,
7051 .result_unpriv = REJECT,
7052 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
7053 .retval = 1,
7054 },
7055 {
7056 "map access: value_ptr -= known scalar, lower oob arith, test 3",
7057 .insns = {
7058 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7059 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7060 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7061 BPF_LD_MAP_FD(BPF_REG_1, 0),
7062 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7063 BPF_FUNC_map_lookup_elem),
7064 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
7065 BPF_MOV64_IMM(BPF_REG_1, 47),
7066 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7067 BPF_MOV64_IMM(BPF_REG_1, 47),
7068 BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1),
7069 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
7070 BPF_MOV64_IMM(BPF_REG_0, 1),
7071 BPF_EXIT_INSN(),
7072 },
7073 .fixup_map_array_48b = { 3 },
7074 .result = ACCEPT,
7075 .result_unpriv = REJECT,
7076 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
7077 .retval = 1,
7078 },
7079 {
7080 "map access: known scalar += value_ptr",
7081 .insns = {
7082 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7083 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7084 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7085 BPF_LD_MAP_FD(BPF_REG_1, 0),
7086 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7087 BPF_FUNC_map_lookup_elem),
7088 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
7089 BPF_MOV64_IMM(BPF_REG_1, 4),
7090 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
7091 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
7092 BPF_MOV64_IMM(BPF_REG_0, 1),
7093 BPF_EXIT_INSN(),
7094 },
7095 .fixup_map_array_48b = { 3 },
7096 .result = ACCEPT,
7097 .retval = 1,
7098 },
7099 {
7100 "map access: value_ptr += known scalar, 1",
7101 .insns = {
7102 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7103 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7104 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7105 BPF_LD_MAP_FD(BPF_REG_1, 0),
7106 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7107 BPF_FUNC_map_lookup_elem),
7108 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
7109 BPF_MOV64_IMM(BPF_REG_1, 4),
7110 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7111 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
7112 BPF_MOV64_IMM(BPF_REG_0, 1),
7113 BPF_EXIT_INSN(),
7114 },
7115 .fixup_map_array_48b = { 3 },
7116 .result = ACCEPT,
7117 .retval = 1,
7118 },
7119 {
7120 "map access: value_ptr += known scalar, 2",
7121 .insns = {
7122 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7123 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7124 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7125 BPF_LD_MAP_FD(BPF_REG_1, 0),
7126 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7127 BPF_FUNC_map_lookup_elem),
7128 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
7129 BPF_MOV64_IMM(BPF_REG_1, 49),
7130 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7131 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
7132 BPF_MOV64_IMM(BPF_REG_0, 1),
7133 BPF_EXIT_INSN(),
7134 },
7135 .fixup_map_array_48b = { 3 },
7136 .result = REJECT,
7137 .errstr = "invalid access to map value",
7138 },
7139 {
7140 "map access: value_ptr += known scalar, 3",
7141 .insns = {
7142 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7143 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7144 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7145 BPF_LD_MAP_FD(BPF_REG_1, 0),
7146 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7147 BPF_FUNC_map_lookup_elem),
7148 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
7149 BPF_MOV64_IMM(BPF_REG_1, -1),
7150 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7151 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
7152 BPF_MOV64_IMM(BPF_REG_0, 1),
7153 BPF_EXIT_INSN(),
7154 },
7155 .fixup_map_array_48b = { 3 },
7156 .result = REJECT,
7157 .errstr = "invalid access to map value",
7158 },
7159 {
7160 "map access: value_ptr += known scalar, 4",
7161 .insns = {
7162 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7163 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7164 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7165 BPF_LD_MAP_FD(BPF_REG_1, 0),
7166 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7167 BPF_FUNC_map_lookup_elem),
7168 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 7),
7169 BPF_MOV64_IMM(BPF_REG_1, 5),
7170 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7171 BPF_MOV64_IMM(BPF_REG_1, -2),
7172 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7173 BPF_MOV64_IMM(BPF_REG_1, -1),
7174 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7175 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
7176 BPF_MOV64_IMM(BPF_REG_0, 1),
7177 BPF_EXIT_INSN(),
7178 },
7179 .fixup_map_array_48b = { 3 },
7180 .result = ACCEPT,
7181 .result_unpriv = REJECT,
7182 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
7183 .retval = 1,
7184 },
7185 {
7186 "map access: value_ptr += known scalar, 5",
7187 .insns = {
7188 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7189 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7190 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7191 BPF_LD_MAP_FD(BPF_REG_1, 0),
7192 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7193 BPF_FUNC_map_lookup_elem),
7194 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),
7195 BPF_MOV64_IMM(BPF_REG_1, (6 + 1) * sizeof(int)),
7196 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
7197 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
7198 BPF_EXIT_INSN(),
7199 },
7200 .fixup_map_array_48b = { 3 },
7201 .result = ACCEPT,
7202 .retval = 0xabcdef12,
7203 },
7204 {
7205 "map access: value_ptr += known scalar, 6",
7206 .insns = {
7207 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7208 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7209 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7210 BPF_LD_MAP_FD(BPF_REG_1, 0),
7211 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7212 BPF_FUNC_map_lookup_elem),
7213 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 5),
7214 BPF_MOV64_IMM(BPF_REG_1, (3 + 1) * sizeof(int)),
7215 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7216 BPF_MOV64_IMM(BPF_REG_1, 3 * sizeof(int)),
7217 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7218 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 0),
7219 BPF_EXIT_INSN(),
7220 },
7221 .fixup_map_array_48b = { 3 },
7222 .result = ACCEPT,
7223 .retval = 0xabcdef12,
7224 },
7225 {
7226 "map access: unknown scalar += value_ptr, 1",
7227 .insns = {
7228 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7229 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7230 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7231 BPF_LD_MAP_FD(BPF_REG_1, 0),
7232 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7233 BPF_FUNC_map_lookup_elem),
7234 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
7235 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
7236 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
7237 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
7238 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
7239 BPF_MOV64_IMM(BPF_REG_0, 1),
7240 BPF_EXIT_INSN(),
7241 },
7242 .fixup_map_array_48b = { 3 },
7243 .result = ACCEPT,
7244 .retval = 1,
7245 },
7246 {
7247 "map access: unknown scalar += value_ptr, 2",
7248 .insns = {
7249 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7250 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7251 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7252 BPF_LD_MAP_FD(BPF_REG_1, 0),
7253 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7254 BPF_FUNC_map_lookup_elem),
7255 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
7256 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
7257 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 31),
7258 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
7259 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
7260 BPF_EXIT_INSN(),
7261 },
7262 .fixup_map_array_48b = { 3 },
7263 .result = ACCEPT,
7264 .retval = 0xabcdef12,
7265 },
7266 {
7267 "map access: unknown scalar += value_ptr, 3",
7268 .insns = {
7269 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
7270 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
7271 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
7272 BPF_LD_MAP_FD(BPF_REG_1, 0),
7273 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
7274 BPF_FUNC_map_lookup_elem),
7275 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 8),
7276 BPF_MOV64_IMM(BPF_REG_1, -1),
7277 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7278 BPF_MOV64_IMM(BPF_REG_1, 1),
7279 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7280 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
7281 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 31),
7282 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
7283 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
7284 BPF_EXIT_INSN(),
7285 },
7286 .fixup_map_array_48b = { 3 },
7287 .result = ACCEPT,
7288 .result_unpriv = REJECT,
7289 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
7290 .retval = 0xabcdef12,
7291 },
7292 {
7293 "map access: unknown scalar += value_ptr, 4",
6614 .insns = {7294 .insns = {
6615 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),7295 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6616 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),7296 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -6618,19 +7298,22 @@ static struct bpf_test tests[] = { · 1 unmodified line
6618 BPF_LD_MAP_FD(BPF_REG_1, 0),7298 BPF_LD_MAP_FD(BPF_REG_1, 0),
6619 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,7299 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6620 BPF_FUNC_map_lookup_elem),7300 BPF_FUNC_map_lookup_elem),
6621 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),7301 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
6622 BPF_MOV64_IMM(BPF_REG_1, 4),7302 BPF_MOV64_IMM(BPF_REG_1, 19),
7303 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
7304 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
7305 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 31),
6623 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),7306 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),
6624 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),7307 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
6625 BPF_MOV64_IMM(BPF_REG_0, 1),
6626 BPF_EXIT_INSN(),7308 BPF_EXIT_INSN(),
6627 },7309 },
6628 .fixup_map_array_48b = { 3 },7310 .fixup_map_array_48b = { 3 },
6629 .result = ACCEPT,7311 .result = REJECT,
6630 .retval = 1,7312 .errstr = "R1 max value is outside of the array range",
7313 .errstr_unpriv = "R1 pointer arithmetic of map value goes out of range",
6631 },7314 },
6632 {7315 {
6633 "map access: value_ptr += known scalar",7316 "map access: value_ptr += unknown scalar, 1",
6634 .insns = {7317 .insns = {
6635 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),7318 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6636 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),7319 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -6638,8 +7321,9 @@ static struct bpf_test tests[] = { · 1 unmodified line
6638 BPF_LD_MAP_FD(BPF_REG_1, 0),7321 BPF_LD_MAP_FD(BPF_REG_1, 0),
6639 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,7322 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6640 BPF_FUNC_map_lookup_elem),7323 BPF_FUNC_map_lookup_elem),
6641 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3),7324 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6642 BPF_MOV64_IMM(BPF_REG_1, 4),7325 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
7326 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
6643 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),7327 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6644 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),7328 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
6645 BPF_MOV64_IMM(BPF_REG_0, 1),7329 BPF_MOV64_IMM(BPF_REG_0, 1),
@@ -6650,7 +7334,7 @@ static struct bpf_test tests[] = { · 4 unmodified lines
6650 .retval = 1,7334 .retval = 1,
6651 },7335 },
6652 {7336 {
6653 "map access: unknown scalar += value_ptr",7337 "map access: value_ptr += unknown scalar, 2",
6654 .insns = {7338 .insns = {
6655 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),7339 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6656 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),7340 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -6659,19 +7343,18 @@ static struct bpf_test tests[] = { · 2 unmodified lines
6659 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,7343 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6660 BPF_FUNC_map_lookup_elem),7344 BPF_FUNC_map_lookup_elem),
6661 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),7345 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),
6662 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),7346 BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0),
6663 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),7347 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 31),
6664 BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_0),7348 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
6665 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),7349 BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 0),
6666 BPF_MOV64_IMM(BPF_REG_0, 1),
6667 BPF_EXIT_INSN(),7350 BPF_EXIT_INSN(),
6668 },7351 },
6669 .fixup_map_array_48b = { 3 },7352 .fixup_map_array_48b = { 3 },
6670 .result = ACCEPT,7353 .result = ACCEPT,
6671 .retval = 1,7354 .retval = 0xabcdef12,
6672 },7355 },
6673 {7356 {
6674 "map access: value_ptr += unknown scalar",7357 "map access: value_ptr += unknown scalar, 3",
6675 .insns = {7358 .insns = {
6676 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),7359 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
6677 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),7360 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
@@ -6679,13 +7362,20 @@ static struct bpf_test tests[] = { · 1 unmodified line
6679 BPF_LD_MAP_FD(BPF_REG_1, 0),7362 BPF_LD_MAP_FD(BPF_REG_1, 0),
6680 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,7363 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
6681 BPF_FUNC_map_lookup_elem),7364 BPF_FUNC_map_lookup_elem),
6682 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 4),7365 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 11),
6683 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),7366 BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0),
7367 BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 8),
7368 BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 16),
6684 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),7369 BPF_ALU64_IMM(BPF_AND, BPF_REG_1, 0xf),
6685 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),7370 BPF_ALU64_IMM(BPF_AND, BPF_REG_3, 1),
6686 BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),7371 BPF_ALU64_IMM(BPF_OR, BPF_REG_3, 1),
7372 BPF_JMP_REG(BPF_JGT, BPF_REG_2, BPF_REG_3, 4),
7373 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_3),
7374 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
6687 BPF_MOV64_IMM(BPF_REG_0, 1),7375 BPF_MOV64_IMM(BPF_REG_0, 1),
6688 BPF_EXIT_INSN(),7376 BPF_EXIT_INSN(),
7377 BPF_MOV64_IMM(BPF_REG_0, 2),
7378 BPF_JMP_IMM(BPF_JA, 0, 0, -3),
6689 },7379 },
6690 .fixup_map_array_48b = { 3 },7380 .fixup_map_array_48b = { 3 },
6691 .result = ACCEPT,7381 .result = ACCEPT,
@@ -6770,6 +7460,8 @@ static struct bpf_test tests[] = { · 78 unmodified lines
6770 },7460 },
6771 .fixup_map_array_48b = { 3 },7461 .fixup_map_array_48b = { 3 },
6772 .result = ACCEPT,7462 .result = ACCEPT,
7463 .result_unpriv = REJECT,
7464 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
6773 .retval = 1,7465 .retval = 1,
6774 },7466 },
6775 {7467 {
@@ -6837,6 +7529,8 @@ static struct bpf_test tests[] = { · 61 unmodified lines
6837 },7529 },
6838 .fixup_map_array_48b = { 3 },7530 .fixup_map_array_48b = { 3 },
6839 .result = ACCEPT,7531 .result = ACCEPT,
7532 .result_unpriv = REJECT,
7533 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
6840 .retval = 1,7534 .retval = 1,
6841 },7535 },
6842 {7536 {
@@ -8376,6 +9070,7 @@ static struct bpf_test tests[] = { · 1533 unmodified lines
8376 },9070 },
8377 .fixup_map_hash_8b = { 3 },9071 .fixup_map_hash_8b = { 3 },
8378 .errstr = "unbounded min value",9072 .errstr = "unbounded min value",
9073 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8379 .result = REJECT,9074 .result = REJECT,
8380 },9075 },
8381 {9076 {
@@ -8400,6 +9095,7 @@ static struct bpf_test tests[] = { · 18 unmodified lines
8400 },9095 },
8401 .fixup_map_hash_8b = { 3 },9096 .fixup_map_hash_8b = { 3 },
8402 .errstr = "unbounded min value",9097 .errstr = "unbounded min value",
9098 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8403 .result = REJECT,9099 .result = REJECT,
8404 },9100 },
8405 {9101 {
@@ -8426,6 +9122,7 @@ static struct bpf_test tests[] = { · 20 unmodified lines
8426 },9122 },
8427 .fixup_map_hash_8b = { 3 },9123 .fixup_map_hash_8b = { 3 },
8428 .errstr = "unbounded min value",9124 .errstr = "unbounded min value",
9125 .errstr_unpriv = "R8 has unknown scalar with mixed signed bounds",
8429 .result = REJECT,9126 .result = REJECT,
8430 },9127 },
8431 {9128 {
@@ -8451,6 +9148,7 @@ static struct bpf_test tests[] = { · 19 unmodified lines
8451 },9148 },
8452 .fixup_map_hash_8b = { 3 },9149 .fixup_map_hash_8b = { 3 },
8453 .errstr = "unbounded min value",9150 .errstr = "unbounded min value",
9151 .errstr_unpriv = "R8 has unknown scalar with mixed signed bounds",
8454 .result = REJECT,9152 .result = REJECT,
8455 },9153 },
8456 {9154 {
@@ -8499,6 +9197,7 @@ static struct bpf_test tests[] = { · 42 unmodified lines
8499 },9197 },
8500 .fixup_map_hash_8b = { 3 },9198 .fixup_map_hash_8b = { 3 },
8501 .errstr = "unbounded min value",9199 .errstr = "unbounded min value",
9200 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8502 .result = REJECT,9201 .result = REJECT,
8503 },9202 },
8504 {9203 {
@@ -8570,6 +9269,7 @@ static struct bpf_test tests[] = { · 65 unmodified lines
8570 },9269 },
8571 .fixup_map_hash_8b = { 3 },9270 .fixup_map_hash_8b = { 3 },
8572 .errstr = "unbounded min value",9271 .errstr = "unbounded min value",
9272 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8573 .result = REJECT,9273 .result = REJECT,
8574 },9274 },
8575 {9275 {
@@ -8621,6 +9321,7 @@ static struct bpf_test tests[] = { · 45 unmodified lines
8621 },9321 },
8622 .fixup_map_hash_8b = { 3 },9322 .fixup_map_hash_8b = { 3 },
8623 .errstr = "unbounded min value",9323 .errstr = "unbounded min value",
9324 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8624 .result = REJECT,9325 .result = REJECT,
8625 },9326 },
8626 {9327 {
@@ -8648,6 +9349,7 @@ static struct bpf_test tests[] = { · 21 unmodified lines
8648 },9349 },
8649 .fixup_map_hash_8b = { 3 },9350 .fixup_map_hash_8b = { 3 },
8650 .errstr = "unbounded min value",9351 .errstr = "unbounded min value",
9352 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8651 .result = REJECT,9353 .result = REJECT,
8652 },9354 },
8653 {9355 {
@@ -8674,6 +9376,7 @@ static struct bpf_test tests[] = { · 20 unmodified lines
8674 },9376 },
8675 .fixup_map_hash_8b = { 3 },9377 .fixup_map_hash_8b = { 3 },
8676 .errstr = "unbounded min value",9378 .errstr = "unbounded min value",
9379 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8677 .result = REJECT,9380 .result = REJECT,
8678 },9381 },
8679 {9382 {
@@ -8703,6 +9406,7 @@ static struct bpf_test tests[] = { · 23 unmodified lines
8703 },9406 },
8704 .fixup_map_hash_8b = { 3 },9407 .fixup_map_hash_8b = { 3 },
8705 .errstr = "unbounded min value",9408 .errstr = "unbounded min value",
9409 .errstr_unpriv = "R7 has unknown scalar with mixed signed bounds",
8706 .result = REJECT,9410 .result = REJECT,
8707 },9411 },
8708 {9412 {
@@ -8733,6 +9437,7 @@ static struct bpf_test tests[] = { · 24 unmodified lines
8733 },9437 },
8734 .fixup_map_hash_8b = { 4 },9438 .fixup_map_hash_8b = { 4 },
8735 .errstr = "unbounded min value",9439 .errstr = "unbounded min value",
9440 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8736 .result = REJECT,9441 .result = REJECT,
8737 },9442 },
8738 {9443 {
@@ -8761,6 +9466,7 @@ static struct bpf_test tests[] = { · 22 unmodified lines
8761 },9466 },
8762 .fixup_map_hash_8b = { 3 },9467 .fixup_map_hash_8b = { 3 },
8763 .errstr = "unbounded min value",9468 .errstr = "unbounded min value",
9469 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8764 .result = REJECT,9470 .result = REJECT,
8765 .result_unpriv = REJECT,9471 .result_unpriv = REJECT,
8766 },9472 },
@@ -8813,8 +9519,38 @@ static struct bpf_test tests[] = { · 46 unmodified lines
8813 },9519 },
8814 .fixup_map_hash_8b = { 3 },9520 .fixup_map_hash_8b = { 3 },
8815 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",9521 .errstr = "R0 min value is negative, either use unsigned index or do a if (index >=0) check.",
9522 .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds",
8816 .result = REJECT,9523 .result = REJECT,
8817 },9524 },
9525 {
9526 "check subtraction on pointers for unpriv",
9527 .insns = {
9528 BPF_MOV64_IMM(BPF_REG_0, 0),
9529 BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
9530 BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
9531 BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
9532 BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 9),
9533 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
9534 BPF_FUNC_map_lookup_elem),
9535 BPF_MOV64_REG(BPF_REG_9, BPF_REG_FP),
9536 BPF_ALU64_REG(BPF_SUB, BPF_REG_9, BPF_REG_0),
9537 BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
9538 BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
9539 BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -8),
9540 BPF_ST_MEM(BPF_DW, BPF_REG_ARG2, 0, 0),
9541 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
9542 BPF_FUNC_map_lookup_elem),
9543 BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
9544 BPF_EXIT_INSN(),
9545 BPF_STX_MEM(BPF_DW, BPF_REG_0, BPF_REG_9, 0),
9546 BPF_MOV64_IMM(BPF_REG_0, 0),
9547 BPF_EXIT_INSN(),
9548 },
9549 .fixup_map_hash_8b = { 1, 9 },
9550 .result = ACCEPT,
9551 .result_unpriv = REJECT,
9552 .errstr_unpriv = "R9 pointer -= pointer prohibited",
9553 },
8818 {9554 {
8819 "bounds check based on zero-extended MOV",9555 "bounds check based on zero-extended MOV",
8820 .insns = {9556 .insns = {
@@ -9145,6 +9881,36 @@ static struct bpf_test tests[] = { · 324 unmodified lines
9145 .errstr = "R0 unbounded memory access",9881 .errstr = "R0 unbounded memory access",
9146 .result = REJECT9882 .result = REJECT
9147 },9883 },
9884 {
9885 "bounds check after 32-bit right shift with 64-bit input",
9886 .insns = {
9887 BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
9888 BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
9889 BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -8),
9890 BPF_LD_MAP_FD(BPF_REG_1, 0),
9891 BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
9892 BPF_FUNC_map_lookup_elem),
9893 BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 6),
9894 /* r1 = 2 */
9895 BPF_MOV64_IMM(BPF_REG_1, 2),
9896 /* r1 = 1<<32 */
9897 BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 31),
9898 /* r1 = 0 (NOT 2!) */
9899 BPF_ALU32_IMM(BPF_RSH, BPF_REG_1, 31),
9900 /* r1 = 0xffff'fffe (NOT 0!) */
9901 BPF_ALU32_IMM(BPF_SUB, BPF_REG_1, 2),
9902 /* computes OOB pointer */
9903 BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1),
9904 /* OOB access */
9905 BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
9906 /* exit */
9907 BPF_MOV64_IMM(BPF_REG_0, 0),
9908 BPF_EXIT_INSN(),
9909 },
9910 .fixup_map_hash_8b = { 3 },
9911 .errstr = "R0 invalid mem access",
9912 .result = REJECT,
9913 },
9148 {9914 {
9149 "bounds check map access with off+size signed 32bit overflow. test1",9915 "bounds check map access with off+size signed 32bit overflow. test1",
9150 .insns = {9916 .insns = {
@@ -9185,6 +9951,7 @@ static struct bpf_test tests[] = { · 34 unmodified lines
9185 },9951 },
9186 .fixup_map_hash_8b = { 3 },9952 .fixup_map_hash_8b = { 3 },
9187 .errstr = "pointer offset 1073741822",9953 .errstr = "pointer offset 1073741822",
9954 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
9188 .result = REJECT9955 .result = REJECT
9189 },9956 },
9190 {9957 {
@@ -9206,6 +9973,7 @@ static struct bpf_test tests[] = { · 15 unmodified lines
9206 },9973 },
9207 .fixup_map_hash_8b = { 3 },9974 .fixup_map_hash_8b = { 3 },
9208 .errstr = "pointer offset -1073741822",9975 .errstr = "pointer offset -1073741822",
9976 .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
9209 .result = REJECT9977 .result = REJECT
9210 },9978 },
9211 {9979 {
@@ -9377,6 +10145,7 @@ static struct bpf_test tests[] = { · 165 unmodified lines
9377 BPF_EXIT_INSN()10145 BPF_EXIT_INSN()
9378 },10146 },
9379 .errstr = "fp pointer offset 1073741822",10147 .errstr = "fp pointer offset 1073741822",
10148 .errstr_unpriv = "R1 stack pointer arithmetic goes out of range",
9380 .result = REJECT10149 .result = REJECT
9381 },10150 },
9382 {10151 {
@@ -13718,6 +14487,328 @@ static struct bpf_test tests[] = { · 4335 unmodified lines
13718 .result_unpriv = ACCEPT,14487 .result_unpriv = ACCEPT,
13719 .insn_processed = 15,14488 .insn_processed = 15,
13720 },14489 },
14490 {
14491 "masking, test out of bounds 1",
14492 .insns = {
14493 BPF_MOV32_IMM(BPF_REG_1, 5),
14494 BPF_MOV32_IMM(BPF_REG_2, 5 - 1),
14495 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14496 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14497 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14498 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14499 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14500 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14501 BPF_EXIT_INSN(),
14502 },
14503 .result = ACCEPT,
14504 .retval = 0,
14505 },
14506 {
14507 "masking, test out of bounds 2",
14508 .insns = {
14509 BPF_MOV32_IMM(BPF_REG_1, 1),
14510 BPF_MOV32_IMM(BPF_REG_2, 1 - 1),
14511 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14512 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14513 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14514 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14515 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14516 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14517 BPF_EXIT_INSN(),
14518 },
14519 .result = ACCEPT,
14520 .retval = 0,
14521 },
14522 {
14523 "masking, test out of bounds 3",
14524 .insns = {
14525 BPF_MOV32_IMM(BPF_REG_1, 0xffffffff),
14526 BPF_MOV32_IMM(BPF_REG_2, 0xffffffff - 1),
14527 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14528 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14529 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14530 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14531 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14532 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14533 BPF_EXIT_INSN(),
14534 },
14535 .result = ACCEPT,
14536 .retval = 0,
14537 },
14538 {
14539 "masking, test out of bounds 4",
14540 .insns = {
14541 BPF_MOV32_IMM(BPF_REG_1, 0xffffffff),
14542 BPF_MOV32_IMM(BPF_REG_2, 1 - 1),
14543 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14544 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14545 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14546 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14547 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14548 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14549 BPF_EXIT_INSN(),
14550 },
14551 .result = ACCEPT,
14552 .retval = 0,
14553 },
14554 {
14555 "masking, test out of bounds 5",
14556 .insns = {
14557 BPF_MOV32_IMM(BPF_REG_1, -1),
14558 BPF_MOV32_IMM(BPF_REG_2, 1 - 1),
14559 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14560 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14561 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14562 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14563 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14564 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14565 BPF_EXIT_INSN(),
14566 },
14567 .result = ACCEPT,
14568 .retval = 0,
14569 },
14570 {
14571 "masking, test out of bounds 6",
14572 .insns = {
14573 BPF_MOV32_IMM(BPF_REG_1, -1),
14574 BPF_MOV32_IMM(BPF_REG_2, 0xffffffff - 1),
14575 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14576 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14577 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14578 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14579 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14580 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14581 BPF_EXIT_INSN(),
14582 },
14583 .result = ACCEPT,
14584 .retval = 0,
14585 },
14586 {
14587 "masking, test out of bounds 7",
14588 .insns = {
14589 BPF_MOV64_IMM(BPF_REG_1, 5),
14590 BPF_MOV32_IMM(BPF_REG_2, 5 - 1),
14591 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14592 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14593 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14594 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14595 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14596 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14597 BPF_EXIT_INSN(),
14598 },
14599 .result = ACCEPT,
14600 .retval = 0,
14601 },
14602 {
14603 "masking, test out of bounds 8",
14604 .insns = {
14605 BPF_MOV64_IMM(BPF_REG_1, 1),
14606 BPF_MOV32_IMM(BPF_REG_2, 1 - 1),
14607 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14608 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14609 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14610 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14611 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14612 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14613 BPF_EXIT_INSN(),
14614 },
14615 .result = ACCEPT,
14616 .retval = 0,
14617 },
14618 {
14619 "masking, test out of bounds 9",
14620 .insns = {
14621 BPF_MOV64_IMM(BPF_REG_1, 0xffffffff),
14622 BPF_MOV32_IMM(BPF_REG_2, 0xffffffff - 1),
14623 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14624 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14625 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14626 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14627 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14628 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14629 BPF_EXIT_INSN(),
14630 },
14631 .result = ACCEPT,
14632 .retval = 0,
14633 },
14634 {
14635 "masking, test out of bounds 10",
14636 .insns = {
14637 BPF_MOV64_IMM(BPF_REG_1, 0xffffffff),
14638 BPF_MOV32_IMM(BPF_REG_2, 1 - 1),
14639 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14640 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14641 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14642 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14643 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14644 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14645 BPF_EXIT_INSN(),
14646 },
14647 .result = ACCEPT,
14648 .retval = 0,
14649 },
14650 {
14651 "masking, test out of bounds 11",
14652 .insns = {
14653 BPF_MOV64_IMM(BPF_REG_1, -1),
14654 BPF_MOV32_IMM(BPF_REG_2, 1 - 1),
14655 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14656 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14657 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14658 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14659 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14660 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14661 BPF_EXIT_INSN(),
14662 },
14663 .result = ACCEPT,
14664 .retval = 0,
14665 },
14666 {
14667 "masking, test out of bounds 12",
14668 .insns = {
14669 BPF_MOV64_IMM(BPF_REG_1, -1),
14670 BPF_MOV32_IMM(BPF_REG_2, 0xffffffff - 1),
14671 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14672 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14673 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14674 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14675 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14676 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14677 BPF_EXIT_INSN(),
14678 },
14679 .result = ACCEPT,
14680 .retval = 0,
14681 },
14682 {
14683 "masking, test in bounds 1",
14684 .insns = {
14685 BPF_MOV32_IMM(BPF_REG_1, 4),
14686 BPF_MOV32_IMM(BPF_REG_2, 5 - 1),
14687 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14688 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14689 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14690 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14691 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14692 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14693 BPF_EXIT_INSN(),
14694 },
14695 .result = ACCEPT,
14696 .retval = 4,
14697 },
14698 {
14699 "masking, test in bounds 2",
14700 .insns = {
14701 BPF_MOV32_IMM(BPF_REG_1, 0),
14702 BPF_MOV32_IMM(BPF_REG_2, 0xffffffff - 1),
14703 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14704 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14705 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14706 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14707 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14708 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14709 BPF_EXIT_INSN(),
14710 },
14711 .result = ACCEPT,
14712 .retval = 0,
14713 },
14714 {
14715 "masking, test in bounds 3",
14716 .insns = {
14717 BPF_MOV32_IMM(BPF_REG_1, 0xfffffffe),
14718 BPF_MOV32_IMM(BPF_REG_2, 0xffffffff - 1),
14719 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14720 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14721 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14722 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14723 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14724 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14725 BPF_EXIT_INSN(),
14726 },
14727 .result = ACCEPT,
14728 .retval = 0xfffffffe,
14729 },
14730 {
14731 "masking, test in bounds 4",
14732 .insns = {
14733 BPF_MOV32_IMM(BPF_REG_1, 0xabcde),
14734 BPF_MOV32_IMM(BPF_REG_2, 0xabcdef - 1),
14735 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14736 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14737 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14738 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14739 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14740 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14741 BPF_EXIT_INSN(),
14742 },
14743 .result = ACCEPT,
14744 .retval = 0xabcde,
14745 },
14746 {
14747 "masking, test in bounds 5",
14748 .insns = {
14749 BPF_MOV32_IMM(BPF_REG_1, 0),
14750 BPF_MOV32_IMM(BPF_REG_2, 1 - 1),
14751 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14752 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14753 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14754 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14755 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14756 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14757 BPF_EXIT_INSN(),
14758 },
14759 .result = ACCEPT,
14760 .retval = 0,
14761 },
14762 {
14763 "masking, test in bounds 6",
14764 .insns = {
14765 BPF_MOV32_IMM(BPF_REG_1, 46),
14766 BPF_MOV32_IMM(BPF_REG_2, 47 - 1),
14767 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_1),
14768 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_1),
14769 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14770 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14771 BPF_ALU64_REG(BPF_AND, BPF_REG_1, BPF_REG_2),
14772 BPF_MOV64_REG(BPF_REG_0, BPF_REG_1),
14773 BPF_EXIT_INSN(),
14774 },
14775 .result = ACCEPT,
14776 .retval = 46,
14777 },
14778 {
14779 "masking, test in bounds 7",
14780 .insns = {
14781 BPF_MOV64_IMM(BPF_REG_3, -46),
14782 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, -1),
14783 BPF_MOV32_IMM(BPF_REG_2, 47 - 1),
14784 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_3),
14785 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_3),
14786 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14787 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14788 BPF_ALU64_REG(BPF_AND, BPF_REG_3, BPF_REG_2),
14789 BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
14790 BPF_EXIT_INSN(),
14791 },
14792 .result = ACCEPT,
14793 .retval = 46,
14794 },
14795 {
14796 "masking, test in bounds 8",
14797 .insns = {
14798 BPF_MOV64_IMM(BPF_REG_3, -47),
14799 BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, -1),
14800 BPF_MOV32_IMM(BPF_REG_2, 47 - 1),
14801 BPF_ALU64_REG(BPF_SUB, BPF_REG_2, BPF_REG_3),
14802 BPF_ALU64_REG(BPF_OR, BPF_REG_2, BPF_REG_3),
14803 BPF_ALU64_IMM(BPF_NEG, BPF_REG_2, 0),
14804 BPF_ALU64_IMM(BPF_ARSH, BPF_REG_2, 63),
14805 BPF_ALU64_REG(BPF_AND, BPF_REG_3, BPF_REG_2),
14806 BPF_MOV64_REG(BPF_REG_0, BPF_REG_3),
14807 BPF_EXIT_INSN(),
14808 },
14809 .result = ACCEPT,
14810 .retval = 0,
14811 },
13721 {14812 {
13722 "reference tracking in call: free reference in subprog and outside",14813 "reference tracking in call: free reference in subprog and outside",
13723 .insns = {14814 .insns = {
@@ -14413,6 +15504,16 @@ static int create_map(uint32_t type, uint32_t size_key, · 689 unmodified lines
14413 return fd;15504 return fd;
14414}15505}
14415 15506
15507static void update_map(int fd, int index)
15508{
15509 struct test_val value = {
15510 .index = (6 + 1) * sizeof(int),
15511 .foo[6] = 0xabcdef12,
15512 };
15513
15514 assert(!bpf_map_update_elem(fd, &index, &value, 0));
15515}
15516
14416static int create_prog_dummy1(enum bpf_prog_type prog_type)15517static int create_prog_dummy1(enum bpf_prog_type prog_type)
14417{15518{
14418 struct bpf_insn prog[] = {15519 struct bpf_insn prog[] = {
@@ -14564,6 +15665,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type, · 145 unmodified lines
14564 if (*fixup_map_array_48b) {15665 if (*fixup_map_array_48b) {
14565 map_fds[3] = create_map(BPF_MAP_TYPE_ARRAY, sizeof(int),15666 map_fds[3] = create_map(BPF_MAP_TYPE_ARRAY, sizeof(int),
14566 sizeof(struct test_val), 1);15667 sizeof(struct test_val), 1);
15668 update_map(map_fds[3], 0);
14567 do {15669 do {
14568 prog[*fixup_map_array_48b].imm = map_fds[3];15670 prog[*fixup_map_array_48b].imm = map_fds[3];
14569 fixup_map_array_48b++;15671 fixup_map_array_48b++;