{
        if (type_may_be_null(reg->type) && reg->id == id &&
            !WARN_ON_ONCE(!reg->id)) {
-               if (WARN_ON_ONCE(reg->smin_value || reg->smax_value ||
-                                !tnum_equals_const(reg->var_off, 0) ||
-                                reg->off)) {
-                       /* Old offset (both fixed and variable parts) should
-                        * have been known-zero, because we don't allow pointer
-                        * arithmetic on pointers that might be NULL. If we
-                        * see this happening, don't convert the register.
-                        */
+               /* Old offset (both fixed and variable parts) should have been
+                * known-zero, because we don't allow pointer arithmetic on
+                * pointers that might be NULL. If we see this happening, don't
+                * convert the register.
+                *
+                * But in some cases, some helpers that return local kptrs
+                * advance offset for the returned pointer. In those cases, it
+                * is fine to expect to see reg->off.
+                */
+               if (WARN_ON_ONCE(reg->smin_value || reg->smax_value || !tnum_equals_const(reg->var_off, 0)))
+                       return;
+               if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC | PTR_MAYBE_NULL) && WARN_ON_ONCE(reg->off))
                        return;
-               }
                if (is_null) {
                        reg->type = SCALAR_VALUE;
                        /* We don't need id and ref_obj_id from this point