root/tools/testing/selftests/bpf/verifier/var_off.c

/* [<][>][^][v][top][bottom][index][help] */
   1 {
   2         "variable-offset ctx access",
   3         .insns = {
   4         /* Get an unknown value */
   5         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
   6         /* Make it small and 4-byte aligned */
   7         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
   8         /* add it to skb.  We now have either &skb->len or
   9          * &skb->pkt_type, but we don't know which
  10          */
  11         BPF_ALU64_REG(BPF_ADD, BPF_REG_1, BPF_REG_2),
  12         /* dereference it */
  13         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_1, 0),
  14         BPF_EXIT_INSN(),
  15         },
  16         .errstr = "variable ctx access var_off=(0x0; 0x4)",
  17         .result = REJECT,
  18         .prog_type = BPF_PROG_TYPE_LWT_IN,
  19 },
  20 {
  21         "variable-offset stack access",
  22         .insns = {
  23         /* Fill the top 8 bytes of the stack */
  24         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  25         /* Get an unknown value */
  26         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
  27         /* Make it small and 4-byte aligned */
  28         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
  29         BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
  30         /* add it to fp.  We now have either fp-4 or fp-8, but
  31          * we don't know which
  32          */
  33         BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
  34         /* dereference it */
  35         BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_2, 0),
  36         BPF_EXIT_INSN(),
  37         },
  38         .errstr = "variable stack access var_off=(0xfffffffffffffff8; 0x4)",
  39         .result = REJECT,
  40         .prog_type = BPF_PROG_TYPE_LWT_IN,
  41 },
  42 {
  43         "indirect variable-offset stack access, unbounded",
  44         .insns = {
  45         BPF_MOV64_IMM(BPF_REG_2, 6),
  46         BPF_MOV64_IMM(BPF_REG_3, 28),
  47         /* Fill the top 16 bytes of the stack. */
  48         BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
  49         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  50         /* Get an unknown value. */
  51         BPF_LDX_MEM(BPF_DW, BPF_REG_4, BPF_REG_1, offsetof(struct bpf_sock_ops,
  52                                                            bytes_received)),
  53         /* Check the lower bound but don't check the upper one. */
  54         BPF_JMP_IMM(BPF_JSLT, BPF_REG_4, 0, 4),
  55         /* Point the lower bound to initialized stack. Offset is now in range
  56          * from fp-16 to fp+0x7fffffffffffffef, i.e. max value is unbounded.
  57          */
  58         BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
  59         BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
  60         BPF_MOV64_IMM(BPF_REG_5, 8),
  61         /* Dereference it indirectly. */
  62         BPF_EMIT_CALL(BPF_FUNC_getsockopt),
  63         BPF_MOV64_IMM(BPF_REG_0, 0),
  64         BPF_EXIT_INSN(),
  65         },
  66         .errstr = "R4 unbounded indirect variable offset stack access",
  67         .result = REJECT,
  68         .prog_type = BPF_PROG_TYPE_SOCK_OPS,
  69 },
  70 {
  71         "indirect variable-offset stack access, max out of bound",
  72         .insns = {
  73         /* Fill the top 8 bytes of the stack */
  74         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  75         /* Get an unknown value */
  76         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
  77         /* Make it small and 4-byte aligned */
  78         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
  79         BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 8),
  80         /* add it to fp.  We now have either fp-4 or fp-8, but
  81          * we don't know which
  82          */
  83         BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
  84         /* dereference it indirectly */
  85         BPF_LD_MAP_FD(BPF_REG_1, 0),
  86         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
  87         BPF_MOV64_IMM(BPF_REG_0, 0),
  88         BPF_EXIT_INSN(),
  89         },
  90         .fixup_map_hash_8b = { 5 },
  91         .errstr = "R2 max value is outside of stack bound",
  92         .result = REJECT,
  93         .prog_type = BPF_PROG_TYPE_LWT_IN,
  94 },
  95 {
  96         "indirect variable-offset stack access, min out of bound",
  97         .insns = {
  98         /* Fill the top 8 bytes of the stack */
  99         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
 100         /* Get an unknown value */
 101         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
 102         /* Make it small and 4-byte aligned */
 103         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
 104         BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 516),
 105         /* add it to fp.  We now have either fp-516 or fp-512, but
 106          * we don't know which
 107          */
 108         BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
 109         /* dereference it indirectly */
 110         BPF_LD_MAP_FD(BPF_REG_1, 0),
 111         BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_map_lookup_elem),
 112         BPF_MOV64_IMM(BPF_REG_0, 0),
 113         BPF_EXIT_INSN(),
 114         },
 115         .fixup_map_hash_8b = { 5 },
 116         .errstr = "R2 min value is outside of stack bound",
 117         .result = REJECT,
 118         .prog_type = BPF_PROG_TYPE_LWT_IN,
 119 },
 120 {
 121         "indirect variable-offset stack access, max_off+size > max_initialized",
 122         .insns = {
 123         /* Fill only the second from top 8 bytes of the stack. */
 124         BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
 125         /* Get an unknown value. */
 126         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
 127         /* Make it small and 4-byte aligned. */
 128         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
 129         BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
 130         /* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
 131          * which. fp-12 size 8 is partially uninitialized stack.
 132          */
 133         BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
 134         /* Dereference it indirectly. */
 135         BPF_LD_MAP_FD(BPF_REG_1, 0),
 136         BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
 137         BPF_MOV64_IMM(BPF_REG_0, 0),
 138         BPF_EXIT_INSN(),
 139         },
 140         .fixup_map_hash_8b = { 5 },
 141         .errstr = "invalid indirect read from stack var_off",
 142         .result = REJECT,
 143         .prog_type = BPF_PROG_TYPE_LWT_IN,
 144 },
 145 {
 146         "indirect variable-offset stack access, min_off < min_initialized",
 147         .insns = {
 148         /* Fill only the top 8 bytes of the stack. */
 149         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
 150         /* Get an unknown value */
 151         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
 152         /* Make it small and 4-byte aligned. */
 153         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
 154         BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
 155         /* Add it to fp.  We now have either fp-12 or fp-16, but we don't know
 156          * which. fp-16 size 8 is partially uninitialized stack.
 157          */
 158         BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
 159         /* Dereference it indirectly. */
 160         BPF_LD_MAP_FD(BPF_REG_1, 0),
 161         BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
 162         BPF_MOV64_IMM(BPF_REG_0, 0),
 163         BPF_EXIT_INSN(),
 164         },
 165         .fixup_map_hash_8b = { 5 },
 166         .errstr = "invalid indirect read from stack var_off",
 167         .result = REJECT,
 168         .prog_type = BPF_PROG_TYPE_LWT_IN,
 169 },
 170 {
 171         "indirect variable-offset stack access, priv vs unpriv",
 172         .insns = {
 173         /* Fill the top 16 bytes of the stack. */
 174         BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
 175         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
 176         /* Get an unknown value. */
 177         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
 178         /* Make it small and 4-byte aligned. */
 179         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
 180         BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
 181         /* Add it to fp.  We now have either fp-12 or fp-16, we don't know
 182          * which, but either way it points to initialized stack.
 183          */
 184         BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
 185         /* Dereference it indirectly. */
 186         BPF_LD_MAP_FD(BPF_REG_1, 0),
 187         BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
 188         BPF_MOV64_IMM(BPF_REG_0, 0),
 189         BPF_EXIT_INSN(),
 190         },
 191         .fixup_map_hash_8b = { 6 },
 192         .errstr_unpriv = "R2 stack pointer arithmetic goes out of range, prohibited for !root",
 193         .result_unpriv = REJECT,
 194         .result = ACCEPT,
 195         .prog_type = BPF_PROG_TYPE_CGROUP_SKB,
 196 },
 197 {
 198         "indirect variable-offset stack access, uninitialized",
 199         .insns = {
 200         BPF_MOV64_IMM(BPF_REG_2, 6),
 201         BPF_MOV64_IMM(BPF_REG_3, 28),
 202         /* Fill the top 16 bytes of the stack. */
 203         BPF_ST_MEM(BPF_W, BPF_REG_10, -16, 0),
 204         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
 205         /* Get an unknown value. */
 206         BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, 0),
 207         /* Make it small and 4-byte aligned. */
 208         BPF_ALU64_IMM(BPF_AND, BPF_REG_4, 4),
 209         BPF_ALU64_IMM(BPF_SUB, BPF_REG_4, 16),
 210         /* Add it to fp.  We now have either fp-12 or fp-16, we don't know
 211          * which, but either way it points to initialized stack.
 212          */
 213         BPF_ALU64_REG(BPF_ADD, BPF_REG_4, BPF_REG_10),
 214         BPF_MOV64_IMM(BPF_REG_5, 8),
 215         /* Dereference it indirectly. */
 216         BPF_EMIT_CALL(BPF_FUNC_getsockopt),
 217         BPF_MOV64_IMM(BPF_REG_0, 0),
 218         BPF_EXIT_INSN(),
 219         },
 220         .errstr = "invalid indirect read from stack var_off",
 221         .result = REJECT,
 222         .prog_type = BPF_PROG_TYPE_SOCK_OPS,
 223 },
 224 {
 225         "indirect variable-offset stack access, ok",
 226         .insns = {
 227         /* Fill the top 16 bytes of the stack. */
 228         BPF_ST_MEM(BPF_DW, BPF_REG_10, -16, 0),
 229         BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
 230         /* Get an unknown value. */
 231         BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, 0),
 232         /* Make it small and 4-byte aligned. */
 233         BPF_ALU64_IMM(BPF_AND, BPF_REG_2, 4),
 234         BPF_ALU64_IMM(BPF_SUB, BPF_REG_2, 16),
 235         /* Add it to fp.  We now have either fp-12 or fp-16, we don't know
 236          * which, but either way it points to initialized stack.
 237          */
 238         BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_10),
 239         /* Dereference it indirectly. */
 240         BPF_LD_MAP_FD(BPF_REG_1, 0),
 241         BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
 242         BPF_MOV64_IMM(BPF_REG_0, 0),
 243         BPF_EXIT_INSN(),
 244         },
 245         .fixup_map_hash_8b = { 6 },
 246         .result = ACCEPT,
 247         .prog_type = BPF_PROG_TYPE_LWT_IN,
 248 },

/* [<][>][^][v][top][bottom][index][help] */