To answer my own question:
This is easily fixed by enabling the Magisk built-in module ‘
Systemless Hosts’.
Magisk was already installed on my phone. (I had patched the boot image with Magisk, as per the procedure
here, and the first time I tried to run
su it triggered a full install of the Magisk app.) I started the Magisk app, opened the Modules tab, and the ‘
Systemless Hosts’ module was already listed; I just had to enable it and reboot.
After doing that,
/etc/hosts is fully writable!
(There seems to be a lot going on under the covers… First,
/etc is a symbolic link to
/system, so
/etc/hosts really means
/system/etc/hosts. Second, it looks like Magisk mounts a huge number of separate filesystems — e.g. one for every executable in
/system/bin, and loads of others I don't understand. Enabling the ‘Systemless Hosts’ module causes one more filesystem to be mounted, on
/system/etc/hosts itself. And that filesystem is writeable — no need to remount it each time — and seems to have plenty of space.)
One caveat:
only /etc/hosts is writable; no other files in that directory are writable (because they're on a different filesystem). This means that if you use e.g.
vi to edit the file, it will give an error because it can't create a swap file in that directory. The workaround for that is simply to tell it not to use a swap file, with
vi -n.
(Another idea I had was to make (
/system)
/etc/hosts a symbolic link to a file that I
could write — but I couldn't get that to work. I eventually found a location to write a hosts file that could be read by all users, and symlinked to it, but it had no effect: the system just didn't use it for looking up hostnames (as confirmed by commands such as
ping). I'm not sure why. I suspect that the hosts file must be a regular file and not a symlink; I've seen that claim on platforms such as macOS and Docker, though not on Android.)
Anyone interested in controlling hostname lookup should also be aware of
AdAway, which is an app that takes care of mapping host names for you.
It can work by setting up a hosts file (if you have root), or by setting up a local VPN (which works even if you don't have root); it can run a local webserver (if you redirect to 127.0.0.1); and it has a huge list of adservers etc. that it updates regularly.
I tried it, and it seems to work well. (In fact, it was through researching an error it initially gave me that I discovered the Systemless Hosts module.)
(I probably won't be keeping it, though, as I have a fair number of personal entries to add for to devices on my LAN or at work, and although AdAway can do that, it's quite fiddly. Also, I already have a hosts file on my desktop machines, so it's easy just to copy that across whenever I update it.)