FS#9384 - [initscripts] allow read only root
Attached to Project:
Arch Linux
Opened by Jeremy (loserMcloser) - Tuesday, 29 January 2008, 03:17 GMT
Last edited by Tom Gundersen (tomegun) - Tuesday, 13 December 2011, 22:28 GMT
Opened by Jeremy (loserMcloser) - Tuesday, 29 January 2008, 03:17 GMT
Last edited by Tom Gundersen (tomegun) - Tuesday, 13 December 2011, 22:28 GMT
|
Details
The orgignal request was for read-only root, this we can
revisit once all the relevant packages support it. Since
this was a request to initscripts, I'll state here what I
want to support:
initscripts should never directly write to the root partition, and remounting root rw should be optional (e.g. by kernel parameters or fstab entry). In other words initscripts should not block ro root. ================= Orgignal request: ================= New feature request for read-only root support -- see: http://bugs.archlinux.org/task/5378#comment24140 Main problem: mount won't follow a symlink for /etc/mtab so some functionality is lost in that case Proposed solution: * Use unionfs to overlay a write-able filesystem (probably using a small tmpfs) onto /etc -- see http://gentoo-wiki.com/HOWTO_Read-only_root_filesystem * Add a READONLY_ROOT config option to rc.conf -- with a warning that user should know what he/she is doing before enabling!! * Edit rc.sysinit and rc.shutdown so that if READONLY_ROOT is set: -- add -n option to some mount commands -- replace current handling of /etc/mtab in rc.sysinit with unionfs/tmpfs magic -- add somewhere near the end of rc.sysinit: status "Re-Mounting Root Read-only" /bin/mount -o remount,ro / -- in rc.shutdown, remount / rw before handling /etc/localtime Other affected files: /etc/HOSTNAME /etc/resolv.conf /etc/asound.state For asound.state, see http://bugs.archlinux.org/task/9383 HOSTNAME and resolv.conf -- these are probably best left up to the user to deal with See also: http://bugs.archlinux.org/task/5378 |
Closed by Tom Gundersen (tomegun)
Tuesday, 13 December 2011, 22:28 GMT
Reason for closing: Implemented
Tuesday, 13 December 2011, 22:28 GMT
Reason for closing: Implemented
FS#5445).An extra check should be added so if READONLY_ROOT=yes then /etc/localtime should not be touched in rc.sysinit/rc.shutdown.
So if user changes his/her timezone settings - (s)he should copy the correct timezone file to /etc/localtime manually.
/etc/rc.d/readonly-root start|stop
working OK from the command-line by having a helper script in /bin do the actual work, but
/etc/rc.d/readonly-root stop
when called by initscipts as a result of "telinit 1" or "poweroff|reboot" ends up with a "/etc busy" message from umount. I thought about adding the lazy option for the umount call, but then it makes it hard to put mtab back in its proper place for read-write / if we're being called from the command line.
Not quite sure the best way to proceed.
http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f84e3f521e1449300e0fdc314b7b43b418a66dc3
replacing /etc/mtab with unionfs/tmpfs magic will not be needed in future! :)
http://lkml.org/lkml/2008/3/17/274
-- probably will have to wait for an update to util-linux-ng after that too.
Replacing /etc/mtab with a symlink to /proc/mounts is still a less-than-perfect solution.
From the mount man page:
----------------------------
It is possible to replace /etc/mtab by a symbolic link to /proc/mounts, and especially when you have very large numbers of mounts things will be much faster with that symlink, but some information is lost that way, and in particular working with the loop device will be less convenient, and using the "user" option will fail.
----------------------------
One work-around that I've suggested before is to patch /usr/include/paths.h to change
#define _PATH_MOUNTED "/etc/mtab"
to something like
#define _PATH_MOUNTED "/var/run/mtab"
and then making sure any mount commands in /etc/rc.* that occur while /var may not be mounted use the -n option. (Note that this solution would require recompiling any pkg that provides a mount.* binary).
However patching a core pkg like glibc is frowned upon.
I can understand not wanting to patch glibc. IMO /var is really the proper place for mtab. /etc should really be only for static config files. But I would never bother trying to convince the glibc maintainers of that -- it's been /etc/mtab forever, so I guess it will stay that way unless/until /proc/mounts because a proper replacement for it.
The gentoo wiki suggests patching mount to make it follow symlinks, then making /etc/mtab a symlink to a writable partition. Probably also not a very attractive solution.
If you want to implement it in Arch, it only needs the attached scripts and some hard links added to initscripts -- no need to modify the existing initscripts at all.
Some notes:
* user should have /var on a separate (writable) partition for a readonly-root solution, or use some overall unionfs/aufs solution to allow writing to /var
* because of the writable aufs branch overtop of /etc, /etc can still actually be modified / written to, but all changes are lost when the script is stopped
* the attached readonly-root.sh script maybe should be a little more robust in its handling of /etc/mtab on "stop", eg. check for and/or use an /etc/mtab~ lock file
* among some other things in /etc that need to be taken care of by the user (eg. HOSTNAME, resolv.conf), console-kit-daemon seems to like to keep the directory /etc/ConsoleKit/run-session.d open while you are logged into an X session, so it can interfere with the script. Easily fixed by symlinking this directory somewhere writeable (I use /var/etc for such things).
Here's what I did:
# mkdir /bin/initscripts
# ln /etc/rc.multi /etc/rc.shutdown /etc/rc.single /etc/rc.sysinit /bin/initscripts/
Modify /etc/inittab changing the following lines
rc::sysinit:/bin/initscripts/rc.sysinit
rs:S1:wait:/bin/initscripts/rc.single
rm:2345:wait:/bin/initscripts/rc.multi
rh:06:wait:/bin/initscripts/rc.shutdown
Place readonly-root.sh into /bin/initscripts/
Place readonly-root into /etc/rc.d/
Place readonly-root.conf to /etc/conf.d/readonly-root
Now you can put readonly-root into the DAEMONS array in /etc/rc.conf or start it manually with /etc/rc.d/readonly-root
readonly-root (0.3 KiB)
readonly-root.conf (0.2 KiB)
Also, why not combine the two scripts into one, for simplicity - you already have the start/stop handling in there.
A third note - perhaps it would be more ideal to make the rw layer in /var instead of a tmpfs. This way your changes aren't lost, they just aren't "committed". An additional flag or something could be used to "commit" the rw layer at a later date. Perhaps like:
$ /etc/rc.d/readonly-root commit-changes
# stop the readonly-root
# copy files from the rw layer on top of the rootfs
# clean the rw layer
# start readonly-root
> Also, why not combine the two scripts into one, for simplicity -
> you already have the start/stop handling in there.
You can't do
umount -t aufs /etc
from a script which lives in /etc, umount will complain "/etc busy". Also can't umount /etc while init is running rc.single, rc.shutdown, etc., so I changed /etc/inittab to use the linked copies under /bin (I guess /sbin would be more appropriate...)
> A third note - perhaps it would be more ideal to make the rw layer
> in /var instead of a tmpfs.
> [snip]
Thanks for the suggestions, those are good ideas. Perhaps also an option in readonly-root.conf, like "COMMIT-ON-STOP", to automatically commit changes on stop. Though it took a year before I had time to work on this again (see my Feb 4 2008 post above), so it might be another while before I work on such extra features.
Anyways, I have a solution which requires minimal maintenance -- no more hacking initscripts / patching glibc, just have to refresh the hardlinks in /bin after an initscripts update. Thought I'd share it, but otherwise feel free to close this bug if you want.
If I get a chance I'll post an archwiki page on read-only root.
So just so I understand fully - read-only root works fine EXCEPT for /etc, correct?
And this is only because of /etc/mtab and /etc/resolv.conf ?
What about /var? Or is that on another partition?
mount -o bind /some-writable-partition/var /var
> So just so I understand fully - read-only root works fine EXCEPT for /etc, correct?
> And this is only because of /etc/mtab and /etc/resolv.conf ?
Well, yes and no. There are lots of other things that have to be tweaked, but in my opinion the only ones that are best handled at the package level are /etc/mtab and /etc/resolv.conf. Everything else should be left to the user to take care of (including where to put /var).
In fact, even /etc/resolv.conf is iffy -- to handle that, I have just wrapped
/etc/rc.d/readonly-root stop
inside a script that makes a copy of resolv.conf before stop and then writes it back in /etc when / is remounted rw. Although maybe I should make readonly-root.conf include an option to do this...
Some other things that I have bind-mounted to writable directories (at startup through fstab):
/root
/usr/var
/usr/src
/etc/samba/private
/usr/www
Also, as mentioned above, console-kit-daemon has an annoying habit of keeping /etc/ConsoleKit/run-session.d open while an X session is logged in. The developers of ConsoleKit should really put runtime data under /var/lib or something...
* support systems without /etc/mtab
- one API for work with mtab on systems with or without /etc/mtab
- maintain userspace specific mount options in /var/run/libmount
[#1] http://www.spinics.net/lists/util-linux-ng/msg03205.html
In principle, I'm in favor of supporting read-only root. That said, I think the best way to do it is for the various upstream projects to support /etc to be read-only, and not to do any overlay magic ourselves. I know work is underway to make this possible, so it should only be a matter of time...
From the initscripts side, we should fix our handling of localtime, either by never copying the files automatically (my preference), or by only doing so if /etc is mounted rw. Lastly, we could probably use fstab to indicate whether or not root should be ro/rw.
This could allow for working with the hard disks with a minimal amount of trouble from the tools.
At the very least, whatever final implementation is chosen, I should be able to get this pretend write access without much trouble, so I ask that assumptions about the use of a read-only root be minimized.
At any rate, I think your request is distinct from the current one. This FS is about making root ro, and yours is about having pretend write. I suggest you open a separate feature request with a usecase and a reason why your usecase is not covered by implementing ro root.
As far as I'm aware the upstream devs agree that programs should not write to /etc, so either they'll solve it soon or at least they should be open to patches.
We only have two minor issues left:
1) do not write /etc/profile.d/locale.sh (I think this will be solved once we have a solution to
FS#20911)2) only remount root rw if it is not in /etc/fstab, otherwise remount using the options found there
Suggestions/patches welcome ;-)
Except for that we are done (other packages might still not deal with this very well, but that is a different problem).
quote: Lastly, we could probably use fstab to indicate whether or not root should be ro/rw.
Love this one because it's annoying to see all fstab root options ignored!
Suggested patch to rc.sysinit:
status "Remounting Root Filesystem"
ROOTOPT=(`grep -w / /etc/fstab`)
MOUNTOPT="rw"
[ "${ROOTOPT[3]}" ] && [ "${ROOTOPT[0]:0:1}" != "#" ] && MOUNTOPT="${ROOTOPT[3]}"
mount -n -o remount,$MOUNTOPT /