1*98d666d0SBrendan Jackman { 2*98d666d0SBrendan Jackman "BPF_ATOMIC_FETCH_ADD smoketest - 64bit", 3*98d666d0SBrendan Jackman .insns = { 4*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 0), 5*98d666d0SBrendan Jackman /* Write 3 to stack */ 6*98d666d0SBrendan Jackman BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), 7*98d666d0SBrendan Jackman /* Put a 1 in R1, add it to the 3 on the stack, and load the value back into R1 */ 8*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_1, 1), 9*98d666d0SBrendan Jackman BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_1, -8), 10*98d666d0SBrendan Jackman /* Check the value we loaded back was 3 */ 11*98d666d0SBrendan Jackman BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2), 12*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 1), 13*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 14*98d666d0SBrendan Jackman /* Load value from stack */ 15*98d666d0SBrendan Jackman BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_10, -8), 16*98d666d0SBrendan Jackman /* Check value loaded from stack was 4 */ 17*98d666d0SBrendan Jackman BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1), 18*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 2), 19*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 20*98d666d0SBrendan Jackman }, 21*98d666d0SBrendan Jackman .result = ACCEPT, 22*98d666d0SBrendan Jackman }, 23*98d666d0SBrendan Jackman { 24*98d666d0SBrendan Jackman "BPF_ATOMIC_FETCH_ADD smoketest - 32bit", 25*98d666d0SBrendan Jackman .insns = { 26*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 0), 27*98d666d0SBrendan Jackman /* Write 3 to stack */ 28*98d666d0SBrendan Jackman BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 3), 29*98d666d0SBrendan Jackman /* Put a 1 in R1, add it to the 3 on the stack, and load the value back into R1 */ 30*98d666d0SBrendan Jackman BPF_MOV32_IMM(BPF_REG_1, 1), 31*98d666d0SBrendan Jackman BPF_ATOMIC_OP(BPF_W, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_1, -4), 32*98d666d0SBrendan Jackman /* Check the value we loaded back was 3 */ 33*98d666d0SBrendan Jackman BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 3, 2), 34*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 1), 35*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 36*98d666d0SBrendan Jackman /* Load value from stack */ 37*98d666d0SBrendan Jackman BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -4), 38*98d666d0SBrendan Jackman /* Check value loaded from stack was 4 */ 39*98d666d0SBrendan Jackman BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 4, 1), 40*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 2), 41*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 42*98d666d0SBrendan Jackman }, 43*98d666d0SBrendan Jackman .result = ACCEPT, 44*98d666d0SBrendan Jackman }, 45*98d666d0SBrendan Jackman { 46*98d666d0SBrendan Jackman "Can't use ATM_FETCH_ADD on frame pointer", 47*98d666d0SBrendan Jackman .insns = { 48*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 0), 49*98d666d0SBrendan Jackman BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), 50*98d666d0SBrendan Jackman BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_10, -8), 51*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 52*98d666d0SBrendan Jackman }, 53*98d666d0SBrendan Jackman .result = REJECT, 54*98d666d0SBrendan Jackman .errstr_unpriv = "R10 leaks addr into mem", 55*98d666d0SBrendan Jackman .errstr = "frame pointer is read only", 56*98d666d0SBrendan Jackman }, 57*98d666d0SBrendan Jackman { 58*98d666d0SBrendan Jackman "Can't use ATM_FETCH_ADD on uninit src reg", 59*98d666d0SBrendan Jackman .insns = { 60*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 0), 61*98d666d0SBrendan Jackman BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3), 62*98d666d0SBrendan Jackman BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_10, BPF_REG_2, -8), 63*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 64*98d666d0SBrendan Jackman }, 65*98d666d0SBrendan Jackman .result = REJECT, 66*98d666d0SBrendan Jackman /* It happens that the address leak check is first, but it would also be 67*98d666d0SBrendan Jackman * complain about the fact that we're trying to modify R10. 68*98d666d0SBrendan Jackman */ 69*98d666d0SBrendan Jackman .errstr = "!read_ok", 70*98d666d0SBrendan Jackman }, 71*98d666d0SBrendan Jackman { 72*98d666d0SBrendan Jackman "Can't use ATM_FETCH_ADD on uninit dst reg", 73*98d666d0SBrendan Jackman .insns = { 74*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 0), 75*98d666d0SBrendan Jackman BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_2, BPF_REG_0, -8), 76*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 77*98d666d0SBrendan Jackman }, 78*98d666d0SBrendan Jackman .result = REJECT, 79*98d666d0SBrendan Jackman /* It happens that the address leak check is first, but it would also be 80*98d666d0SBrendan Jackman * complain about the fact that we're trying to modify R10. 81*98d666d0SBrendan Jackman */ 82*98d666d0SBrendan Jackman .errstr = "!read_ok", 83*98d666d0SBrendan Jackman }, 84*98d666d0SBrendan Jackman { 85*98d666d0SBrendan Jackman "Can't use ATM_FETCH_ADD on kernel memory", 86*98d666d0SBrendan Jackman .insns = { 87*98d666d0SBrendan Jackman /* This is an fentry prog, context is array of the args of the 88*98d666d0SBrendan Jackman * kernel function being called. Load first arg into R2. 89*98d666d0SBrendan Jackman */ 90*98d666d0SBrendan Jackman BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, 0), 91*98d666d0SBrendan Jackman /* First arg of bpf_fentry_test7 is a pointer to a struct. 92*98d666d0SBrendan Jackman * Attempt to modify that struct. Verifier shouldn't let us 93*98d666d0SBrendan Jackman * because it's kernel memory. 94*98d666d0SBrendan Jackman */ 95*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_3, 1), 96*98d666d0SBrendan Jackman BPF_ATOMIC_OP(BPF_DW, BPF_ADD | BPF_FETCH, BPF_REG_2, BPF_REG_3, 0), 97*98d666d0SBrendan Jackman /* Done */ 98*98d666d0SBrendan Jackman BPF_MOV64_IMM(BPF_REG_0, 0), 99*98d666d0SBrendan Jackman BPF_EXIT_INSN(), 100*98d666d0SBrendan Jackman }, 101*98d666d0SBrendan Jackman .prog_type = BPF_PROG_TYPE_TRACING, 102*98d666d0SBrendan Jackman .expected_attach_type = BPF_TRACE_FENTRY, 103*98d666d0SBrendan Jackman .kfunc = "bpf_fentry_test7", 104*98d666d0SBrendan Jackman .result = REJECT, 105*98d666d0SBrendan Jackman .errstr = "only read is supported", 106*98d666d0SBrendan Jackman }, 107