Skip to contentSkip to conversation

per-process namespaces for Linux

PATCH In review Manfred Spraul 11 participants 22 messages Feb 25, 2001 – Feb 28, 2001

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 per-process namespaces for Linux

Quoted 2 lines

* large cleanup of boot process (ramdisk handling, etc.)

Have you thought about supporting .tar.gz into ramfs? Creating custom boot images would be simpler.

--
Manfred

#1 lore raw
Quoted 5 lines · Manfred Spraul
Quoted 2 lines

* large cleanup of boot process (ramdisk handling, etc.)

Have you thought about supporting .tar.gz into ramfs? Creating custom boot images would be simpler.

*uh*. It's definitely easier to do than it used to be, but I'm seriously sceptical about adding more cruft into the thing. Let's sort it out and then see what can be added to the sequences. At least now it's in one place and doesn't have to pull the tricks it used to need for dealing with IO...

(I presume that you mean "unpacking tar.gz into initrd/floppy-loaded ramdisk" and not "adding into ramfs a loader of tarballs" - the latter is out of question, as far as I'm concerned; such code belongs to do_mounts.c if it belongs anywhere at all)

IOW, look into init/do_mounts.c - that's the right place to do that stuff.
Cheers,
Al

#2 lore raw
Quoted 9 lines · Alexander Viro
Quoted 2 lines

Have you thought about supporting .tar.gz into ramfs? Creating custom boot images would be simpler.

*uh*. It's definitely easier to do than it used to be, but I'm seriously sceptical about adding more cruft into the thing. ...

(I presume that you mean "unpacking tar.gz into initrd/floppy-loaded ramdisk" and not "adding into ramfs a loader of tarballs" - the latter is out of question, as far as I'm concerned;

Yes, indeed.

Quoted 4 lines

such code belongs to do_mounts.c if it belongs anywhere at all)

IOW, look into init/do_mounts.c - that's the right place to do that stuff.

Methinks there are at least two possibilities that could do everything we might need here without unnecessary complications.

One is just mount a ramdisk and extract a tarball into its root. Yes, this has some problems -- how do you load tar when you haven't set up your root? -- but I suspect they can be solved. At worst, this would involve some strictly limited kluge to do that.

A better approach might be to find or invent a generic compressed file system. Given that, you just build a compressed root, copy an image of it into ramdisk and let the compressed FS driver handle it from there. I suspect such a driver might be useful elsewhere as well. Does one exist?

#3 lore raw
Quoted 4 lines · Sandy Harris

One is just mount a ramdisk and extract a tarball into its root. Yes, this has some problems -- how do you load tar when you haven't set up your root? -- but I suspect they can be solved. At worst, this would involve some strictly limited kluge to do that.

No kludges actually needed. "Simplified boot sequence" _is_ simplified - we overmount the "final" root over ramfs. Initially empty. So you have the normal environment when you load ramdisk, etc.

IOW, with the namespaces patch you can have root (empty, writable) as soon as you've registered ramfs driver. I.e. _very_ early - before device initialization, for one thing. Actual mounting of the "final" root happen very late, along with all initrd games, etc. That stuff (in do_mounts.c) could be executed as userland process, actually - see the comments in init/do_mounts.c and actual code there.
Cheers,
Al

#4 lore raw
In reply to Sandy Harris
Quoted 3 lines · Alexander Viro

No kludges actually needed. "Simplified boot sequence" _is_ simplified - we overmount the "final" root over ramfs. Initially empty. So you have the normal environment when you load ramdisk, etc.

So is this the Holy Grail, err, union mount we've discussed about one year ago ? I.e.

stat foo # output A
mount /dev/whatever /
stat foo # output B

with A != B ?

If yes, is there also a way to destroy/empty ramfs after this ?

- Werner

Signature · 3 lines
  _________________________________________________________________________
 / Werner Almesberger, ICA, EPFL, CH           [email protected] /
/_IN_N_032__Tel_+41_21_693_6621__Fax_+41_21_693_6610_____________________/
#5 lore raw
Quoted 7 lines · Werner Almesberger
Quoted 3 lines · Alexander Viro

No kludges actually needed. "Simplified boot sequence" _is_ simplified - we overmount the "final" root over ramfs. Initially empty. So you have the normal environment when you load ramdisk, etc.

So is this the Holy Grail, err, union mount we've discussed about one year ago ? I.e.

No. Just an overmount. Final root ends up mounted atop of absolute root - see comments in fs/super.c:mount_root() and in init/do_mounts.c

Quoted 5 lines

stat foo # output A
mount /dev/whatever /
stat foo # output B

with A != B ?

We end with forced chroot to covering one. Due to details of path_walk() it's unbreakable even for root (well, barring the direct access to kernel data structures via /dev/kmem ;-)

So yes, you'll see the covering fs. Chech do_chroot() in init/do_mounts.c

Quoted 1 line

If yes, is there also a way to destroy/empty ramfs after this ?

At the end of boot process we are left with (at most) 8 dentries, 8 inodes and no data pages on ramfs. Is it worth emptying? I can do that (reduce to 1 dentry/1 inode), just add sys_rmdir() and sys_unlink() calls in the end of init/do_mounts.c:prepare_namespace(), but I don't really see the point of it.

Fs _is_ covered - you don't get its objects after mouting the final root.

BTW, Werner - could you take a look at the prepare_namespace()/handle_initrd()? That's our late boot process taken into one place. I'm really not happy about the following:
a) initrd with /linuxrc exec'ing init leaves init with PID > 1.
Is it a good idea? I've reproduced the behaviour we have in the main tree, but I have a bad feeling about it. For one thing, init is killable that way. Not good...
b) can we _please_ kill the real_root_dev sysctl?
c) you had plans for mandating non-exiting /linuxrc. What's the status
of these plans? I'd be glad if we could pull that one off... More than half of handle_initrd() implements the behaviour for the case when /linuxrc does exit and I would be only happy to remove that cruft. AFAICS both RH and Debian have /linuxrc that _does_ exit, though...

Again, current patch reproduces the behaviour of the main tree. Every boot setup that used to work should stay working - that was the design goal. I want to, erm, concentrate the existing logics in one place and make it readable before even thinking of changing behaviour.

I've tested it with all combinations that end up with root on local fs (initrd or not, ramdisks from floppies, devfs mounted or not and their combinations, with different variants of /linuxrc in cases that did initrd). I didn't do exhaustive testing for NFS-root. If someone can find a setup that works with official tree and doesn't work with the patched one - yell. I consider that as a bug.

BTW, people with rootfs=... patches may find that in this variant their patches would become _much_ simpler - they can actually call sys_mount() to mount the final root.

Don't get me wrong - I would be glad to see both rootfs=... and tar patches done atop of that namespace/s_lock (and archive them, keep up-to-date, put on FTP, etc). Just don't expect me to _merge_ them until their counterparts get merged into the Linus' tree (or this patch ends up these, but that won't happen until 2.5).

IOW, I consider the boot-process part of the patch as cleanup of existing code. If it makes some experiments easier - great, but in _that_ respect namespace patch is in permanent feature freeze. Unless behaviour is accepted by Linus - it won't get merged.

Cheers,
Al

#6 lore raw
In reply to Werner Almesberger
Quoted 1 line · Alexander Viro

No. Just an overmount.

Ah, too bad. Union mounts would have been really elegant (allowing the operation to be repeated without residues, and also allowing umounting of the covered FS as a sanity check). But I guess there's no way to implement them without performance penalty ...

Quoted 1 line

Is it worth emptying?

Probably not ... the only interesting case would be if you could completely umount it.

Quoted 2 lines

BTW, Werner - could you take a look at the
prepare_namespace()/handle_initrd()?

Okay, I'll have a look.

Quoted 2 lines

That's our late boot process taken into one place. I'm really not happy about the following:

Agreed on all three counts. Also, change_root might just die by evolution, just like most of NFS-root-from-initrd (using change_root) died.

What we need is a migration plan. Right now, it seems that most people still use change_root. Hopefully they read the little message I left them in linux/Documentation/initrd.txt:

Current kernels still support it, but you should _not_ rely on its continued availability.

So with some luck, distributors will switch to pivot_root sometime soon, when deploying 2.4. So if we drop all the old junk in 2.5, the amount of letter bombs should be small ;-)

Quoted 1 line

Again, current patch reproduces the behaviour of the main tree.

Since you've already done all the work ... ;-) It's good if we can make one change at a time.

- Werner

Signature · 3 lines
  _________________________________________________________________________
 / Werner Almesberger, ICA, EPFL, CH           [email protected] /
/_IN_N_032__Tel_+41_21_693_6621__Fax_+41_21_693_6610_____________________/
#7 lore raw
Quoted 7 lines · Werner Almesberger
Quoted 1 line · Alexander Viro

No. Just an overmount.

Ah, too bad. Union mounts would have been really elegant (allowing the operation to be repeated without residues, and also allowing umounting of the covered FS as a sanity check). But I guess there's no way to implement them without performance penalty ...

There is no way to implement them without credentials' cache. Which needs to be done for many other reasons, but that's a separate patch and separate story. If it's done - no serious penalty involved. However, I doubt that we want a union on / itself. /dev - sure, /bin and /lib - maybe, but /... What for?

Quoted 4 lines
Quoted 1 line

Is it worth emptying?

Probably not ... the only interesting case would be if you could completely umount it.

What's the point in unmounting it? Let the root of the mount tree be fixed - it actually simplifies the things big way. Not that we had any performance penalty for having the thing in place - after this forced chroot we never touch it in lookups. BTW, pivot_root() is simpler that way.

BTW, we probably want to add mount --move <old> <new> - atomically moving a subtree from one place to another. Code is there, we just need to decide on API. Andries?

Quoted 3 lines

So with some luck, distributors will switch to pivot_root sometime soon, when deploying 2.4. So if we drop all the old junk in 2.5, the amount of letter bombs should be small ;-)

Tomorrow I'll try to catch Erik and talk with him about that. I'm not sure that I know anyone in Debian Install System Team (oh, boy... somebody sure loved capital letters). And I've absolutely no idea who is doing that stuff in other distributions...
Cheers,
Al

#8 lore raw
In reply to Werner Almesberger
Quoted 5 lines · Alexander Viro

There is no way to implement them without credentials' cache. Which needs to be done for many other reasons, but that's a separate patch and separate story. If it's done - no serious penalty involved. However, I doubt that we want a union on / itself. /dev - sure, /bin and /lib - maybe, but /... What for?

What I'd really like to do is remount / somewhere with mount --bind, mount over it another skeleton file system which hides setuid programs and some directories and then run a chrooted sshd in the new root. If I'm not missing something, this would make creation of secure chroot environments very easy.

Quoted 2 lines

Tomorrow I'll try to catch Erik and talk with him about that. I'm not sure that I know anyone in Debian Install System Team (oh, boy... somebody sure

Just write to [email protected].

Signature · 2 lines
ciao,
Marco
#9 lore raw
Quoted 7 lines · Marco d'Itri
Quoted 5 lines · Alexander Viro

There is no way to implement them without credentials' cache. Which needs to be done for many other reasons, but that's a separate patch and separate story. If it's done - no serious penalty involved. However, I doubt that we want a union on / itself. /dev - sure, /bin and /lib - maybe, but /... What for?

Quoted 5 lines

What I'd really like to do is remount / somewhere with mount --bind, mount over it another skeleton file system which hides setuid programs and some directories and then run a chrooted sshd in the new root. If I'm not missing something, this would make creation of secure chroot environments very easy.

I'm making NOSUID per-mountpoint. So

	pid = clone(CLONE_NEWNS,0);
	if (!pid) {
		...
		remount everything with nosuid
		exec sshd
	}

should be OK
As for hiding the directories - also easy, mount --bind an empty immutable directory over each of them.

NODEV is also easy to make per-mountpoint, but readonly may be trickier; we need permission() to take vfsmount+dentry instead of inode for that. Doable, but will touch quite a few places.

#10 lore raw

New version uploaded on ftp.math.psu.edu/pub/viro/namespaces-a-S2.gz
Changes:
* nosuid, nodev and noexec are per-mountpoint now.
* new flag for mount() - MS_MOVE (move a subtree, probable syntax
for mount(8) - mount --move old new; old must be a mountpoint)
* Fixes for "lazy" umount.
* CLONE_NEWNS is made root-only (CAP_SYS_ADMIN, actually)

Folks, please help with testing. Again, It Works Here(tm).
Cheers,
Al

#11 lore raw

New version uploaded on ftp.math.psu.edu/pub/viro/namespaces-d-S2.gz

Changes:
* fixed an idiotic bug in get_filesystem_info() that din't
unfortunately) show up on UP.
* nosuid/nodev/noexec work in any combinations (had been b0rken in
previous version).
* fixed multiple-mount (had been b0rken; --bind worked, but attempt
to mount the device you've already had mounted did bad things).
* sanity checks for mount --move were missing. Fixed.
* Assorted cleanups.

Folks, please help with testing.
Cheers,
Al

#12 lore raw
In reply to Alexander Viro
Quoted 1 line · Alexander Viro

* CLONE_NEWNS is made root-only (CAP_SYS_ADMIN, actually)

Would an unprivileged version that killed setuid be OK to have?

Evil idea of the day: non-directory (even non-existant) mount points and non-directory mounts. So then "mount --bind /etc/foo /dev/bar" works.

#13 lore raw
Quoted 5 lines · Albert D. Cahalan
Quoted 1 line · Alexander Viro

* CLONE_NEWNS is made root-only (CAP_SYS_ADMIN, actually)

Would an unprivileged version that killed setuid be OK to have?

Not until we get decent resource accounting here.

Quoted 2 lines

Evil idea of the day: non-directory (even non-existant) mount points and non-directory mounts. So then "mount --bind /etc/foo /dev/bar" works.

Try it. It _does_ work.

#14 lore raw
Quoted 4 lines · Alexander Viro
Quoted 2 lines

Evil idea of the day: non-directory (even non-existant) mount points and non-directory mounts. So then "mount --bind /etc/foo /dev/bar" works.

Try it. It _does_ work.

Yeah, mount --bind is cool, I've been using it on one of my projects today. But - maybe I'm just not thinking creatively enough - what are the advantages of mount --bind versus just symlinking?

Also, I tried mount --bind fileone filetwo, and it fails if filetwo doesn't exist. ('mount point filetwo doesn't exist'). Is that supposed to work? (using mount from latest redhat beta)

BTW, pivot_root is nifty, too. ;-)

regards,
David

Signature · 3 lines
David L. Parsley
Network Administrator
Roanoke College
#15 lore raw
Quoted 9 lines · David L. Parsley
Quoted 4 lines · Alexander Viro
Quoted 2 lines

Evil idea of the day: non-directory (even non-existant) mount points and non-directory mounts. So then "mount --bind /etc/foo /dev/bar" works.

Try it. It _does_ work.

Yeah, mount --bind is cool, I've been using it on one of my projects today. But - maybe I'm just not thinking creatively enough - what are the advantages of mount --bind versus just symlinking?

1) Correctly working ".." (obviously relevant only for directories)
2) Try to create symlinks on read-only NFS mount. For bonus points, try to do that one one client without disturbing everybody else.
3) Try to make it different for different users, for that matter.

Quoted 3 lines

Also, I tried mount --bind fileone filetwo, and it fails if filetwo doesn't exist. ('mount point filetwo doesn't exist'). Is that supposed to work? (using mount from latest redhat beta)

Nope. It does exactly what it should - changing that is a too large can of worms I simply don't want to touch.

Quoted 1 line

BTW, pivot_root is nifty, too. ;-)

Thank Werner for that ;-)

#16 lore raw
Quoted 10 lines · Alexander Viro
Quoted 3 lines · David L. Parsley

Yeah, mount --bind is cool, I've been using it on one of my projects today. But - maybe I'm just not thinking creatively enough - what are the advantages of mount --bind versus just symlinking?

1) Correctly working ".." (obviously relevant only for directories)
2) Try to create symlinks on read-only NFS mount. For bonus points, try to do that one one client without disturbing everybody else.
3) Try to make it different for different users, for that matter.

And disadvantages: you can't have broken symlinks.

This actually turns out to be quite a bit of a problem when one tries to use bind mounts with autofs. For one thing, it's perfectly legal to have /autofs/foo as a symlink to /autofs/bar/foo, where /autofs/bar is not yet mounted -- but a bind mount can't handle that...

Ion

Signature · 2 lines
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.
#17 lore raw
Quoted 13 lines · Ion Badulescu
Quoted 10 lines · Alexander Viro
Quoted 3 lines · David L. Parsley

Yeah, mount --bind is cool, I've been using it on one of my projects today. But - maybe I'm just not thinking creatively enough - what are the advantages of mount --bind versus just symlinking?

1) Correctly working ".." (obviously relevant only for directories)
2) Try to create symlinks on read-only NFS mount. For bonus points, try to do that one one client without disturbing everybody else.
3) Try to make it different for different users, for that matter.

Quoted 6 lines

And disadvantages: you can't have broken symlinks.

This actually turns out to be quite a bit of a problem when one tries to use bind mounts with autofs. For one thing, it's perfectly legal to have /autofs/foo as a symlink to /autofs/bar/foo, where /autofs/bar is not yet mounted -- but a bind mount can't handle that...

First of all, you still have symlinks. What's more, the right solution is to use local objects at the mountpoints. And forget about having a small tree full of links to real mountpoints. Think of autofs-with-one-node.

#18 lore raw
Quoted 8 lines · Alexander Viro
Quoted 6 lines

And disadvantages: you can't have broken symlinks.

This actually turns out to be quite a bit of a problem when one tries to use bind mounts with autofs. For one thing, it's perfectly legal to have /autofs/foo as a symlink to /autofs/bar/foo, where /autofs/bar is not yet mounted -- but a bind mount can't handle that...

First of all, you still have symlinks.

Oh yeah, of course. :-)

Quoted 3 lines

What's more, the right solution is to use local objects at the mountpoints. And forget about having a small tree full of links to real mountpoints. Think of autofs-with-one-node.

That's what Sun's autofs and am-utils call 'direct mounts', which are not yet supported by our autofs (unless I missed something recently). Direct mounts are good for some things, but not for everything. In particular, they are useless for cascading auto-triggered mounts (think /usr/local/src, /usr/local, and /usr, all automounted).

[and, btw, Linux _still_ doesn't properly support am-utils' direct mounts, although all that's needed is to remove LOOKUP_FOLLOW from path_init in sys_umount...]

As for bind mounts, I'll probably revisit them after I'm done with the Solaris autofs support in am-utils -- which will probably be a while. If I can get the thing to chain-trigger all the necessary mounts, we might be able to do something useful with it..

Thanks,
Ion

Signature · 2 lines
  It is better to keep your mouth shut and be thought a fool,
            than to open it and remove all doubt.
#19 lore raw
In reply to Albert D. Cahalan
Quoted 8 lines · Albert D. Cahalan
Quoted 1 line · Alexander Viro

* CLONE_NEWNS is made root-only (CAP_SYS_ADMIN, actually)

Would an unprivileged version that killed setuid be OK to have?

Evil idea of the day: non-directory (even non-existant) mount points and non-directory mounts. So then "mount --bind /etc/foo /dev/bar" works.

BTW, out of curiosity: what's that evil about non-directory mounts? You obviously shouldn't mix directories with non-directories in that context (userland will not take that lightly, same as with rename(), etc.), but binding a non-directory over non-directory... Why not? Me, I'm playing with
% mount -t devloop /tmp/image /dev/loop0 -o offset=4096
Yes, in that order. /dev/loop0 is the mountpoint here. ioctls? We don't need on stinkin' ioctls. Now, _that_ I would call evil... Pretty simple, actually - filesystem with ->read_super() making ->s_root not a directory but a block device. And setting it up (lo_set_fd() with small modifications). Still alpha, requires namespace patch (or at least s_lock one), but seems to be working. Simpler than loop.c in official tree, BTW - no ioctls, no handling pending requests since we unset device only upon umount, when we have nobody keeping it open. losetup? What losetup? Shell script, if somebody would bother to write it (going through losetup options and turning them into mount ones).

#20 lore raw
In reply to Alexander Viro
Quoted 4 lines · In article <[email protected]> you wrote:

A better approach might be to find or invent a generic compressed file system. Given that, you just build a compressed root, copy an image of it into ramdisk and let the compressed FS driver handle it from there. I suspect such a driver might be useful elsewhere as well. Does one exist?

cramfs is compressed but read-only, jffs has the potential to do compressed writes as well....

Greetings,
Arjan van de Ven

#21 lore raw
In reply to Alexander Viro
Quoted 5 lines · [email protected] said:
Quoted 2 lines

Have you thought about supporting .tar.gz into ramfs? Creating custom boot images would be simpler.

*uh*. It's definitely easier to do than it used to be, but I'm seriously sceptical about adding more cruft into the thing.

The really neat part of untarring into a ramfs-root is that it allows you to remove a whole pile of other unnecessary cruft - ll_rw_blk and all the other crap for dealing with block devices and buffer_heads.

CONFIG_BLK_DEV=n

--
dwmw2