#define BPF_REG_D      BPF_REG_8       /* data, callee-saved */
 #define BPF_REG_H      BPF_REG_9       /* hlen, callee-saved */
 
-/* Kernel hidden auxiliary/helper register for hardening step.
- * Only used by eBPF JITs. It's nothing more than a temporary
- * register that JITs use internally, only that here it's part
- * of eBPF instructions that have been rewritten for blinding
- * constants. See JIT pre-step in bpf_jit_blind_constants().
- */
+/* Kernel hidden auxiliary/helper register. */
 #define BPF_REG_AX             MAX_BPF_REG
 #define MAX_BPF_EXT_REG                (MAX_BPF_REG + 1)
 #define MAX_BPF_JIT_REG                MAX_BPF_EXT_REG
 
        BUILD_BUG_ON(BPF_REG_AX  + 1 != MAX_BPF_JIT_REG);
        BUILD_BUG_ON(MAX_BPF_REG + 1 != MAX_BPF_JIT_REG);
 
+       /* Constraints on AX register:
+        *
+        * AX register is inaccessible from user space. It is mapped in
+        * all JITs, and used here for constant blinding rewrites. It is
+        * typically "stateless" meaning its contents are only valid within
+        * the executed instruction, but not across several instructions.
+        * There are a few exceptions however which are further detailed
+        * below.
+        *
+        * Constant blinding is only used by JITs, not in the interpreter.
+        * The interpreter uses AX in some occasions as a local temporary
+        * register e.g. in DIV or MOD instructions.
+        *
+        * In restricted circumstances, the verifier can also use the AX
+        * register for rewrites as long as they do not interfere with
+        * the above cases!
+        */
+       if (from->dst_reg == BPF_REG_AX || from->src_reg == BPF_REG_AX)
+               goto out;
+
        if (from->imm == 0 &&
            (from->code == (BPF_ALU   | BPF_MOV | BPF_K) ||
             from->code == (BPF_ALU64 | BPF_MOV | BPF_K))) {