The ptrace APIs also can’t write to read only memory, at least not on modern Linux running on CPUs with modern MMUs. But SMC doesn’t require that, because you can always map (or remap) executable pages as writable.
Executable code is only read-only by default, you can always change that (or just not do it, in the case of a JIT).
Executable code is only read-only by default, you can always change that (or just not do it, in the case of a JIT).