atomic_cmpxchg.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. {
  2. "atomic compare-and-exchange smoketest - 64bit",
  3. .insns = {
  4. /* val = 3; */
  5. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3),
  6. /* old = atomic_cmpxchg(&val, 2, 4); */
  7. BPF_MOV64_IMM(BPF_REG_1, 4),
  8. BPF_MOV64_IMM(BPF_REG_0, 2),
  9. BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
  10. /* if (old != 3) exit(2); */
  11. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
  12. BPF_MOV64_IMM(BPF_REG_0, 2),
  13. BPF_EXIT_INSN(),
  14. /* if (val != 3) exit(3); */
  15. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
  16. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
  17. BPF_MOV64_IMM(BPF_REG_0, 3),
  18. BPF_EXIT_INSN(),
  19. /* old = atomic_cmpxchg(&val, 3, 4); */
  20. BPF_MOV64_IMM(BPF_REG_1, 4),
  21. BPF_MOV64_IMM(BPF_REG_0, 3),
  22. BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
  23. /* if (old != 3) exit(4); */
  24. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
  25. BPF_MOV64_IMM(BPF_REG_0, 4),
  26. BPF_EXIT_INSN(),
  27. /* if (val != 4) exit(5); */
  28. BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_10, -8),
  29. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 4, 2),
  30. BPF_MOV64_IMM(BPF_REG_0, 5),
  31. BPF_EXIT_INSN(),
  32. /* exit(0); */
  33. BPF_MOV64_IMM(BPF_REG_0, 0),
  34. BPF_EXIT_INSN(),
  35. },
  36. .result = ACCEPT,
  37. },
  38. {
  39. "atomic compare-and-exchange smoketest - 32bit",
  40. .insns = {
  41. /* val = 3; */
  42. BPF_ST_MEM(BPF_W, BPF_REG_10, -4, 3),
  43. /* old = atomic_cmpxchg(&val, 2, 4); */
  44. BPF_MOV32_IMM(BPF_REG_1, 4),
  45. BPF_MOV32_IMM(BPF_REG_0, 2),
  46. BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -4),
  47. /* if (old != 3) exit(2); */
  48. BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
  49. BPF_MOV32_IMM(BPF_REG_0, 2),
  50. BPF_EXIT_INSN(),
  51. /* if (val != 3) exit(3); */
  52. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4),
  53. BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
  54. BPF_MOV32_IMM(BPF_REG_0, 3),
  55. BPF_EXIT_INSN(),
  56. /* old = atomic_cmpxchg(&val, 3, 4); */
  57. BPF_MOV32_IMM(BPF_REG_1, 4),
  58. BPF_MOV32_IMM(BPF_REG_0, 3),
  59. BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -4),
  60. /* if (old != 3) exit(4); */
  61. BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 3, 2),
  62. BPF_MOV32_IMM(BPF_REG_0, 4),
  63. BPF_EXIT_INSN(),
  64. /* if (val != 4) exit(5); */
  65. BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4),
  66. BPF_JMP32_IMM(BPF_JEQ, BPF_REG_0, 4, 2),
  67. BPF_MOV32_IMM(BPF_REG_0, 5),
  68. BPF_EXIT_INSN(),
  69. /* exit(0); */
  70. BPF_MOV32_IMM(BPF_REG_0, 0),
  71. BPF_EXIT_INSN(),
  72. },
  73. .result = ACCEPT,
  74. },
  75. {
  76. "Can't use cmpxchg on uninit src reg",
  77. .insns = {
  78. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 3),
  79. BPF_MOV64_IMM(BPF_REG_0, 3),
  80. BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_2, -8),
  81. BPF_EXIT_INSN(),
  82. },
  83. .result = REJECT,
  84. .errstr = "!read_ok",
  85. },
  86. {
  87. "BPF_W cmpxchg should zero top 32 bits",
  88. .insns = {
  89. /* r0 = U64_MAX; */
  90. BPF_MOV64_IMM(BPF_REG_0, 0),
  91. BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, 1),
  92. /* u64 val = r0; */
  93. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
  94. /* r0 = (u32)atomic_cmpxchg((u32 *)&val, r0, 1); */
  95. BPF_MOV32_IMM(BPF_REG_1, 1),
  96. BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
  97. /* r1 = 0x00000000FFFFFFFFull; */
  98. BPF_MOV64_IMM(BPF_REG_1, 1),
  99. BPF_ALU64_IMM(BPF_LSH, BPF_REG_1, 32),
  100. BPF_ALU64_IMM(BPF_SUB, BPF_REG_1, 1),
  101. /* if (r0 != r1) exit(1); */
  102. BPF_JMP_REG(BPF_JEQ, BPF_REG_0, BPF_REG_1, 2),
  103. BPF_MOV32_IMM(BPF_REG_0, 1),
  104. BPF_EXIT_INSN(),
  105. /* exit(0); */
  106. BPF_MOV32_IMM(BPF_REG_0, 0),
  107. BPF_EXIT_INSN(),
  108. },
  109. .result = ACCEPT,
  110. },
  111. {
  112. "Dest pointer in r0 - fail",
  113. .insns = {
  114. /* val = 0; */
  115. BPF_ST_MEM(BPF_DW, BPF_REG_10, -8, 0),
  116. /* r0 = &val */
  117. BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
  118. /* r0 = atomic_cmpxchg(&val, r0, 1); */
  119. BPF_MOV64_IMM(BPF_REG_1, 1),
  120. BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
  121. /* if (r0 != 0) exit(1); */
  122. BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 2),
  123. BPF_MOV64_IMM(BPF_REG_0, 1),
  124. BPF_EXIT_INSN(),
  125. /* exit(0); */
  126. BPF_MOV64_IMM(BPF_REG_0, 0),
  127. BPF_EXIT_INSN(),
  128. },
  129. .result = ACCEPT,
  130. .result_unpriv = REJECT,
  131. .errstr_unpriv = "R0 leaks addr into mem",
  132. },
  133. {
  134. "Dest pointer in r0 - succeed",
  135. .insns = {
  136. /* r0 = &val */
  137. BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
  138. /* val = r0; */
  139. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
  140. /* r0 = atomic_cmpxchg(&val, r0, 0); */
  141. BPF_MOV64_IMM(BPF_REG_1, 0),
  142. BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_1, -8),
  143. /* r1 = *r0 */
  144. BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
  145. /* exit(0); */
  146. BPF_MOV64_IMM(BPF_REG_0, 0),
  147. BPF_EXIT_INSN(),
  148. },
  149. .result = ACCEPT,
  150. .result_unpriv = REJECT,
  151. .errstr_unpriv = "R0 leaks addr into mem",
  152. },
  153. {
  154. "Dest pointer in r0 - succeed, check 2",
  155. .insns = {
  156. /* r0 = &val */
  157. BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
  158. /* val = r0; */
  159. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
  160. /* r5 = &val */
  161. BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
  162. /* r0 = atomic_cmpxchg(&val, r0, r5); */
  163. BPF_ATOMIC_OP(BPF_DW, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
  164. /* r1 = *r0 */
  165. BPF_LDX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8),
  166. /* exit(0); */
  167. BPF_MOV64_IMM(BPF_REG_0, 0),
  168. BPF_EXIT_INSN(),
  169. },
  170. .result = ACCEPT,
  171. .result_unpriv = REJECT,
  172. .errstr_unpriv = "R0 leaks addr into mem",
  173. },
  174. {
  175. "Dest pointer in r0 - succeed, check 3",
  176. .insns = {
  177. /* r0 = &val */
  178. BPF_MOV64_REG(BPF_REG_0, BPF_REG_10),
  179. /* val = r0; */
  180. BPF_STX_MEM(BPF_DW, BPF_REG_10, BPF_REG_0, -8),
  181. /* r5 = &val */
  182. BPF_MOV64_REG(BPF_REG_5, BPF_REG_10),
  183. /* r0 = atomic_cmpxchg(&val, r0, r5); */
  184. BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
  185. /* exit(0); */
  186. BPF_MOV64_IMM(BPF_REG_0, 0),
  187. BPF_EXIT_INSN(),
  188. },
  189. .result = REJECT,
  190. .errstr = "invalid size of register fill",
  191. .errstr_unpriv = "R0 leaks addr into mem",
  192. },
  193. {
  194. "Dest pointer in r0 - succeed, check 4",
  195. .insns = {
  196. /* r0 = &val */
  197. BPF_MOV32_REG(BPF_REG_0, BPF_REG_10),
  198. /* val = r0; */
  199. BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8),
  200. /* r5 = &val */
  201. BPF_MOV32_REG(BPF_REG_5, BPF_REG_10),
  202. /* r0 = atomic_cmpxchg(&val, r0, r5); */
  203. BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
  204. /* r1 = *r10 */
  205. BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -8),
  206. /* exit(0); */
  207. BPF_MOV64_IMM(BPF_REG_0, 0),
  208. BPF_EXIT_INSN(),
  209. },
  210. .result = ACCEPT,
  211. .result_unpriv = REJECT,
  212. .errstr_unpriv = "R10 partial copy of pointer",
  213. },
  214. {
  215. "Dest pointer in r0 - succeed, check 5",
  216. .insns = {
  217. /* r0 = &val */
  218. BPF_MOV32_REG(BPF_REG_0, BPF_REG_10),
  219. /* val = r0; */
  220. BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -8),
  221. /* r5 = &val */
  222. BPF_MOV32_REG(BPF_REG_5, BPF_REG_10),
  223. /* r0 = atomic_cmpxchg(&val, r0, r5); */
  224. BPF_ATOMIC_OP(BPF_W, BPF_CMPXCHG, BPF_REG_10, BPF_REG_5, -8),
  225. /* r1 = *r0 */
  226. BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, -8),
  227. /* exit(0); */
  228. BPF_MOV64_IMM(BPF_REG_0, 0),
  229. BPF_EXIT_INSN(),
  230. },
  231. .result = REJECT,
  232. .errstr = "R0 invalid mem access",
  233. .errstr_unpriv = "R10 partial copy of pointer",
  234. .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS,
  235. },