struct bpf_reg_state *reg, u32 regno)
 {
        const char *targ_name = btf_type_name(kptr_field->kptr.btf, kptr_field->kptr.btf_id);
-       int perm_flags = PTR_MAYBE_NULL | PTR_TRUSTED | MEM_RCU;
+       int perm_flags;
        const char *reg_name = "";
 
-       /* Only unreferenced case accepts untrusted pointers */
-       if (kptr_field->type == BPF_KPTR_UNREF)
-               perm_flags |= PTR_UNTRUSTED;
+       if (btf_is_kernel(reg->btf)) {
+               perm_flags = PTR_MAYBE_NULL | PTR_TRUSTED | MEM_RCU;
+
+               /* Only unreferenced case accepts untrusted pointers */
+               if (kptr_field->type == BPF_KPTR_UNREF)
+                       perm_flags |= PTR_UNTRUSTED;
+       } else {
+               perm_flags = PTR_MAYBE_NULL | MEM_ALLOC;
+       }
 
        if (base_type(reg->type) != PTR_TO_BTF_ID || (type_flag(reg->type) & ~perm_flags))
                goto bad_type;
 
-       if (!btf_is_kernel(reg->btf)) {
-               verbose(env, "R%d must point to kernel BTF\n", regno);
-               return -EINVAL;
-       }
        /* We need to verify reg->type and reg->btf, before accessing reg->btf */
        reg_name = btf_type_name(reg->btf, reg->btf_id);
 
        if (__check_ptr_off_reg(env, reg, regno, true))
                return -EACCES;
 
-       /* A full type match is needed, as BTF can be vmlinux or module BTF, and
+       /* A full type match is needed, as BTF can be vmlinux, module or prog BTF, and
         * we also need to take into account the reg->off.
         *
         * We want to support cases like:
                        verbose(env, "verifier internal error: unimplemented handling of MEM_ALLOC\n");
                        return -EFAULT;
                }
-               /* Handled by helper specific checks */
+               if (meta->func_id == BPF_FUNC_kptr_xchg) {
+                       if (map_kptr_match_type(env, meta->kptr_field, reg, regno))
+                               return -EACCES;
+               }
                break;
        case PTR_TO_BTF_ID | MEM_PERCPU:
        case PTR_TO_BTF_ID | MEM_PERCPU | PTR_TRUSTED: