Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 11 Apr 2017 11:55:21 -0700
From:      Maxim Sobolev <sobomax@freebsd.org>
To:        Kirk McKusick <mckusick@mckusick.com>
Cc:        FreeBSD Filesystems <freebsd-fs@freebsd.org>
Subject:   Re: mksnap_ffs(8) is not working while chrooted
Message-ID:  <CAH7qZfsqNgK1FtZbZ5gm55iCJTvb29AR0DqUNsW%2BEnEjzyUrcw@mail.gmail.com>
In-Reply-To: <CAH7qZfsS61LEO1eR1T3uoYgiuOgLvnPZRpsScR--a3OnxLK3zw@mail.gmail.com>
References:  <CAH7qZfvO9AjiZM0FyHqRBzp-KN4u=7Pq4Y2xNhQ2W4t53rApTQ@mail.gmail.com> <201704111807.v3BI7PGM001952@chez.mckusick.com> <CAH7qZfsS61LEO1eR1T3uoYgiuOgLvnPZRpsScR--a3OnxLK3zw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help
Kirk, yes, indeed, it works just fine if I chop out the chroot prefix
manually here:

[/builder.trunk/usr/src/sbin/mksnap_ffs]$ sudo chroot /builder.trunk sh
# truncate -s 100m /tmp/fsimage
# mdconfig -a -f /tmp/fsimage
md0
# newfs /dev/md0
/dev/md0: 100.0MB (204800 sectors) block size 32768, fragment size 4096
        using 4 cylinder groups of 25.03MB, 801 blks, 3328 inodes.
super-block backups (for fsck_ffs -b #) at:
 192, 51456, 102720, 153984
# mount /dev/md0 /mnt
# /usr/src/sbin/mksnap_ffs/mksnap_ffs /mnt/mysnap
# ls -l /mnt/mysnap
-r--r-----  1 root  operator  104857672 Apr 11 18:42 /mnt/mysnap
# ^D
[/builder.trunk/usr/src/sbin/mksnap_ffs]$ git diff
diff --git a/sbin/mksnap_ffs/mksnap_ffs.c b/sbin/mksnap_ffs/mksnap_ffs.c
index efd9c6b33..b1fba5e16 100644
--- a/sbin/mksnap_ffs/mksnap_ffs.c
+++ b/sbin/mksnap_ffs/mksnap_ffs.c
@@ -116,7 +116,7 @@ main(int argc, char **argv)
        iovlen = 0;
        build_iovec(&iov, &iovlen, "fstype", "ffs", 4);
        build_iovec(&iov, &iovlen, "from", snapname, (size_t)-1);
-       build_iovec(&iov, &iovlen, "fspath", stfsbuf.f_mntonname,
(size_t)-1);
+       build_iovec(&iov, &iovlen, "fspath", stfsbuf.f_mntonname + 14,
(size_t)-1);
        build_iovec(&iov, &iovlen, "errmsg", errmsg, sizeof(errmsg));
        build_iovec(&iov, &iovlen, "update", NULL, 0);
        build_iovec(&iov, &iovlen, "snapshot", NULL, 0);

So my point is that by making this scenario working OOB I don't think we
would add any new security issue. This already works if you pass proper
path into the nmount(2) and the mount path is inside chroot. In principle I
can possibly do some clever trick on the userland only to strip offending
prefix f_mntonname here component by component until we can locate the
mount dir, but it's likely to be somewhat fuzzy and clearly not suitable
for the basesrc repo.

-Max

On Tue, Apr 11, 2017 at 11:23 AM, Maxim Sobolev <sobomax@freebsd.org> wrote:

> Kirk, what you are saying in not applying in our case. The whole FS is
> mounted *inside* the chroot. The reason why we are trying to use mksnap_ffs
> is to take a clean snapshot to make a compressed version of it without the
> need to forcefully zero out free space.
>
> So it looks like the following:
>
> parent# chroot /mnt/chroot /bin/sh
> chroot# truncate /tmp/diskimage
> chroot# mdconfig -a -f /tmp/diskimage
> md0
> chroot# newfs md0
> chroot# mount /dev/md0 /mnt
> [...do stuff with /mnt...]
> chroot# mksnap_ffs /mnt/snap
> mksnap_ffs: No such file or directory
>
> Perhaps, to work around your concern is to add some flag for the statfs(1)
> to normalize f_mntonname for use inside chroot then? I have not tested it
> here, but I believe that if I'd strip "/mnt/chroot" prefix inside
> mksnap_ffs(8) that would work in our scenario just fine.
>
> -Max
>
> On Tue, Apr 11, 2017 at 11:07 AM, Kirk McKusick <mckusick@mckusick.com>
> wrote:
>
>> > From: Maxim Sobolev <sobomax@freebsd.org>
>> > Date: Tue, 11 Apr 2017 10:40:58 -0700
>> > Subject: mksnap_ffs(8) is not working while chrooted
>> > To: Kirk McKusick <mckusick@mckusick.com>,
>> >         FreeBSD Filesystems <freebsd-fs@freebsd.org>
>> >
>> > Hi Kirk et al,
>> >
>> > I've stumbled upon problem that it is impossible to use mksnap_ffs(8)
>> while
>> > in the chrooted environment. Other utilities that manipulate fs'es (i.e.
>> > mount(8) / umount(8)) work just fine. Quick glance through the code
>> shows
>> > that the problem stems from the fact that mksnap_ffs uses f_mntonname
>> > returned by the statfs(2) system call to fill fspath parameter for the
>> > nmount call. And the statfs() returns f_mntonname path outside chroot.
>> As
>> > far as I can see, there are two options to address this issue.
>> >
>> > 1. Adjust statfs(2) system call to substract chroot prefix while
>> > returning f_mntonname. Similar to what prison_enforce_statfs() function
>> > does for jails.
>> >
>> > 2. Enhance nmount(2) to allow taking FSID in place of mount path to do
>> > resolution using existing flag MNT_BYFSID and adjust mksnap_ffs to use
>> that
>> > instead. This is what umount(8) does to work around the problem.
>> >
>> > Which of two approaches would be preferred solution if any? The second
>> one
>> > seems a bit simpler to me. Please advise. Thanks!
>> >
>> > -Max
>>
>> It is not secure to allow mksnap_ffs(8) to work inside a jail. The issue
>> is that mksnap_ffs takes a snapshot of the entire filesystem. Based on the
>> way that snapshots work in FFS, it is not possible to snapshot only the
>> part of the filesystem that is in the jail. Thus, if you take a snapshot
>> of the entire filesystem and then mount it inside the jail, you will
>> expose parts of the filesystem from outside of the jail to the jail.
>> As such, you should only be able to snapshot a filesystem if it is
>> entirely contained within the jail.
>>
>> If snapshots within jails are important to you, I recommend that you use
>> ZFS which allows you to create per-jail filesystems which you can then
>> snapshot.
>>
>>         Kirk McKusick
>>
>>
>



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAH7qZfsqNgK1FtZbZ5gm55iCJTvb29AR0DqUNsW%2BEnEjzyUrcw>