[email protected] wrote:
> 31.12.2012, 15:18, "Tetsuo Handa" <[email protected]>:
> >
> > What if filesystem namespace is unshared and pivot_root is used for bringing
> > /home/backup to somewhere else?
> 
> What will happen? I verified by experiment that when I have

See http://www.kernel.org/doc/man-pages/online/pages/man2/pivot_root.2.html for
manual. Below is a demo program.

---------- demo.c start ----------
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mount.h>
#include <sched.h>
#include <errno.h>
int pivot_root(const char *new_root, const char *put_old);

int main(int argc, char *argv[])
{
        /* Unshare mount namespace */
        {
                if (unshare(CLONE_NEWNS)) {
                        const int err = errno;
                        fprintf(stderr, "unshare() failed: %d\n", err);
                        return 1;
                }
        }
        /* Mount tmpfs on /tmp */
        {
                if (mount("none", "/tmp", "tmpfs", 0, NULL)) {
                        const int err = errno;
                        fprintf(stderr, "mount() failed: %d\n", err);
                        return 1;
                }
        }
        /* Create /tmp/dir/ */
        {
                if (mkdir("/tmp/dir", 0755)) {
                        const int err = errno;
                        fprintf(stderr, "mkdir() failed: %d\n", err);
                        return 1;
                }
        }
        /* Create /tmp/file */
        {
                const int fd = open("/tmp/file", O_CREAT | O_WRONLY, 0644);
                if (fd == EOF || write(fd, "hello\n", 6) != 6 || close(fd)) {
                        const int err = errno;
                        fprintf(stderr, "open()/write()/close() failed: %d\n",
                                err);
                        return 1;
                }
        }
        /* /tmp/file was accessible as /tmp/file */
        {
                char c;
                const int fd = open("/tmp/file", O_RDONLY, 0666);
                if (fd == EOF) {
                        const int err = errno;
                        fprintf(stderr, "open(\"/tmp/file\") failed: %d\n",
                                err);
                        return 1;
                }
                fprintf(stderr, "Content of /tmp/file\n");
                while (read(fd, &c, 1) == 1 && write(1, &c, 1));
                close(fd);
        }
        /* Make /tmp/ the new / */
        {
                if (pivot_root("/tmp/", "/tmp/dir/")) {
                        const int err = errno;
                        fprintf(stderr, "pivot_root() failed: %d\n", err);
                        return 1;
                }
        }
        /* /tmp/file is now accessible as /file */
        {
                char c;
                const int fd = open("/file", O_RDONLY);
                if (fd == EOF) {
                        const int err = errno;
                        fprintf(stderr, "open(\"/file\") failed: %d\n", err);
                        return 1;
                }
                fprintf(stderr, "Content of /file\n");
                while (read(fd, &c, 1) == 1 && write(1, &c, 1));
                close(fd);
        }
        return 0;
}
---------- demo.c end ----------

Usage of this demo program is:

(Step 1) Compile this demo program.

  # gcc -Wall -O3 -o a.out demo.c

(Step 2) Add CaitSith's policy that audits reading files on tmpfs.

  # echo 'quota audit[0] allowed=0 denied=1024 unmatched=1024' | 
caitsith-loadpolicy
  # echo '1 acl read path.fsmagic=0x01021994' | caitsith-loadpolicy

(Step 3) Discard the CaitSith's audit log.

  # cat /proc/caitsith/audit > /dev/null

(Step 4) Run this demo program.

  # ./a.out

(Step 5) Check the CaitSith's audit log.

 # cat /proc/caitsith/audit

An example of audit log looks like

  #2013/01/02 04:41:58# global-pid=1298 result=unmatched priority=1 / read 
path="/tmp/file" task.pid=1298 task.ppid=1262 task.uid=0 task.gid=0 task.euid=0 
task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 
task.type!=execute_handler task.exe="/root/a.out" task.domain="<kernel>" 
path.uid=0 path.gid=0 path.perm=0644 path.type=file path.ino=9374 path.major=0 
path.minor=21 path.fsmagic=0x1021994 path.parent.uid=0 path.parent.gid=0 
path.parent.perm=01777 path.parent.ino=9372 path.parent.major=0 
path.parent.minor=21 path.parent.fsmagic=0x1021994
  #2013/01/02 04:41:58# global-pid=1298 result=unmatched priority=1 / read 
path="/file" task.pid=1298 task.ppid=1262 task.uid=0 task.gid=0 task.euid=0 
task.egid=0 task.suid=0 task.sgid=0 task.fsuid=0 task.fsgid=0 
task.type!=execute_handler task.exe="/root/a.out" task.domain="<kernel>" 
path.uid=0 path.gid=0 path.perm=0644 path.type=file path.ino=9374 path.major=0 
path.minor=21 path.fsmagic=0x1021994 path.parent.uid=0 path.parent.gid=0 
path.parent.perm=01777 path.parent.ino=9372 path.parent.major=0 
path.parent.minor=21 path.parent.fsmagic=0x1021994

where the difference is only value of "path" variable.

You will find that the location of a file has changed by pivot_root and you
will also find that the inode's attributes (e.g. path.ino ) remain unchanged.

The pathname calculation logic used by TOMOYO, AppArmor, AKARI and CaitSith is
not affected by chroot but is affected by pivot_root .

> 
> 1 acl create path="/home/backup/data1/\(\*\)/\*"
>   1 deny
> 
> And I do `chroot /home/backup /touch /data1/x` I have access properly denied 
> as expected by me. Realpath seems properly accounted for chroot.
> 
> 2013/01/01 11:17:37# global-pid=31896 result=denied priority=1 / create 
> path="/home/backup/data1/x"  ... task.exe="/home/backup/touch" 
> task.domain="/usr/sbin/sshd" ...
> 
> So I don't need to care about pivot_root in my case.

You tested chroot case but didn't test pivot_root case.
You need to care about pivot_root in your case.

_______________________________________________
tomoyo-users-en mailing list
[email protected]
http://lists.sourceforge.jp/mailman/listinfo/tomoyo-users-en

Reply via email to