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
Task Type Feature Request
Category Arch Projects
Status Closed
Assigned To Aaron Griffin (phrakture)
Thomas Bächler (brain0)
Roman Kyrylych (Romashka)
Tom Gundersen (tomegun)
Architecture All
Severity Very Low
Priority Normal
Reported Version 2007.08-2
Due in Version Undecided
Due Date Undecided
Percent Complete 100%
Votes 9
Private No

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
Comment by Roman Kyrylych (Romashka) - Tuesday, 29 January 2008, 10:53 GMT
Note that in case of read-only root support added - we should also take care of /etc/localtime being copied in rc.sysinit/rc.shutdown ( 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.
Comment by Jeremy (loserMcloser) - Saturday, 02 February 2008, 19:47 GMT
Actually, instead of modifying initscripts, I think this can be done quite easily as an /etc/rc.d script. I'll try to post something today.
Comment by Jeremy (loserMcloser) - Monday, 04 February 2008, 15:00 GMT
Well, maybe an rc.d script is not the best way to go -- seems a unionfs on /etc doesn't like being unmounted from a script which is in /etc. I can get

/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.
Comment by Roman Kyrylych (Romashka) - Saturday, 09 February 2008, 17:35 GMT
Great news:
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! :)
Comment by Jeremy (loserMcloser) - Sunday, 10 February 2008, 18:44 GMT
Cool! Though, I tried 2.6.24-git21, and /proc/mounts certainly does contain more information, but still doesn't work with "mount -o user=joeblow". The changelog does say they want /proc/mounts to work as an mtab replacement though, so I hope this will get resolved. I'll keep an eye out, and see what comes of it.
Comment by Roman Kyrylych (Romashka) - Sunday, 10 February 2008, 19:41 GMT
I guess that's because util-linux-ng needs an update as well, keep an eye on their git as well.
Comment by Jeremy (loserMcloser) - Thursday, 20 March 2008, 15:42 GMT
Looks like the "user" mount option is going to be supported in /proc/mounts soon:

http://lkml.org/lkml/2008/3/17/274

-- probably will have to wait for an update to util-linux-ng after that too.
Comment by Glenn Matthys (RedShift) - Tuesday, 17 June 2008, 13:51 GMT
What's the status of this issue? Is this worth implementing/has util-linux-ng been updated to have the features needed for this to work?
Comment by Aaron Griffin (phrakture) - Tuesday, 22 July 2008, 22:11 GMT
Closing the alsa bug will help here. Regarding resolv.conf, this can be solved at the with /etc/conf.d/dhcpcd as well. The only one left would be hostname then, correct?
Comment by Jeremy (loserMcloser) - Thursday, 07 August 2008, 17:50 GMT
In response to RedShift:

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.
Comment by Glenn Matthys (RedShift) - Thursday, 07 August 2008, 22:45 GMT
Whoah that patch is damn ugly IMO. I wonder how other distros solve this?
Comment by Jeremy (loserMcloser) - Saturday, 09 August 2008, 06:19 GMT
They don't -- for most people, a symlink to /proc/mounts works just fine.

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.
Comment by Jeremy (loserMcloser) - Sunday, 22 February 2009, 22:49 GMT
OK, I found a solution using unionfs. (Actually, I'm using aufs, but would only need to change a couple of lines to use unionfs instead.) I don't know why I didn't think of this before.

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
Comment by Jeremy (loserMcloser) - Sunday, 22 February 2009, 22:51 GMT
Oh, should also have mentioned that solution posted in above comment DOES NOT require patching glibc.
Comment by Aaron Griffin (phrakture) - Wednesday, 25 February 2009, 23:10 GMT
Curious - what's the point of symlinking things in /bin like that?
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
Comment by Jeremy (loserMcloser) - Thursday, 26 February 2009, 22:05 GMT
> Curious - what's the point of symlinking things in /bin like that?
> 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.
Comment by Aaron Griffin (phrakture) - Thursday, 26 February 2009, 22:22 GMT
Ah I see about the "/etc busy" thing

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?
Comment by Jeremy (loserMcloser) - Friday, 27 February 2009, 21:56 GMT
I have /var on a separate partition, but you could also do

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...
Comment by Gerardo Exequiel Pozzi (djgera) - Monday, 05 July 2010, 18:17 GMT
Next util-linux-ng (2.19) [#1] will help in this context:
* 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
Comment by Tom Gundersen (tomegun) - Saturday, 26 March 2011, 17:54 GMT
I'm just adding my two cents to this old request as I'm going through the initscript reports:

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.
Comment by Michael Witten (mfwitten) - Saturday, 16 April 2011, 00:40 GMT
However, Tom Gundersen, I would like to be able to boot my system up so that the hard disks are accessed in a read only state, but use something like a UnionFS/tmpfs combination to make it seem as though the WHOLE system has read/write access as per usual.

This could allow for working with the hard disks with a minimal amount of trouble from the tools.
Comment by Tom Gundersen (tomegun) - Saturday, 16 April 2011, 01:18 GMT
@Michael: The way I see it, for any program to require write access to /etc is a bug and should be fixed (as far as I know there are no known unsolvable problems, it is just a matter of waiting for patches to trickle their way down). The question is then: can you provide examples of programs that truly need write access to /etc, or is there other directories (other than /var) that you need write access to?
Comment by Michael Witten (mfwitten) - Saturday, 16 April 2011, 01:26 GMT
I should have clarified: I'm interested in having pretend write access to all of my file systems, including, say, the root file system; in this scheme, having pretend write access to just /etc is but a particular configuration.

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.
Comment by Tom Gundersen (tomegun) - Saturday, 16 April 2011, 01:37 GMT
@Michael: this I understood. I am just trying to understand why. What is your usecase?

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.
Comment by Leonid Isaev (lisaev) - Tuesday, 10 May 2011, 19:19 GMT
@Tom: Regarding writing to /etc, are we considering NM and dhcpcd/dhclient?
Comment by Tom Gundersen (tomegun) - Tuesday, 10 May 2011, 20:44 GMT
@Leonid: I'm aware that they write to /etc. However, those problems should be resolved upstream, and we should just make sure that whatever solutions upstream decide on will work well on Arch.

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.
Comment by Tom Gundersen (tomegun) - Friday, 24 June 2011, 23:57 GMT
Status update:

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).
Comment by Matt (laforge) - Thursday, 04 August 2011, 10:43 GMT
I'm a big fan of a ro root option! Will save a lot of flash memory wear and increase boot time significantly on portable media.

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 /
Comment by Tom Gundersen (tomegun) - Tuesday, 13 December 2011, 22:27 GMT
This is now implemented in git. To enable ro-root, simply set "ro" as an option in fstab. Otherwise it will be remounted rw.

Loading...