Making the GOT read only is problematic as the dynamic linking is lazy by default, and R^X'ing the GOT would make the deferred dynamic symbol resolution or subsequent dlopen calls fail.
It would be simpler to statically link sshd (or, more generically, all sensitive system binaries) and launch them in the R^X mode via, say, specifying the required capability either in the binary descriptor or at the system configuration level (SELinux) – to force-launch the process in the R^X mode for its code pages. The problem, of course, is that not every Linux distribution comes with SELinux enabled as a default.
As someone else pointed out, sshd is set to be eagerly linked which sidesteps the problem of subsequent dlopen calls. But even subsequent dlopen calls should work in my scheme if every library gets its own protected GOT - a dlopen would create a new GOT for that library, populate it & seal it. It wouldn't have access to modify any other GOT because those would be sealed & subsequent dlopens of other libraries would use new GOTs.
It would be simpler to statically link sshd (or, more generically, all sensitive system binaries) and launch them in the R^X mode via, say, specifying the required capability either in the binary descriptor or at the system configuration level (SELinux) – to force-launch the process in the R^X mode for its code pages. The problem, of course, is that not every Linux distribution comes with SELinux enabled as a default.