jail内でのmount

jail内でmount_nullfsができなくて嵌った。

mount_nullfs: Operation not permitted

とか言われる。


調べてみると、FreeBSD Handbookに「The root user is not allowed to mount or unmount file systems from within a jail(8). 」と書いてあった。。
15.5. Fine Tuning and Administration


jail(8)のmanに詳細があった:

   Jails and File Systems
     It is not possible to mount(8) or umount(8) any file system inside a jail
     unless the file system is marked jail-friendly.  See
     security.jail.mount_allowed in the Sysctl MIB Entries section.

jail-friendlyフラグが立っているファイルシステムでなければjail内でのマウントは不可能らしい。
更に"security.jail.mount_allowed" を見ろとある。

     security.jail.mount_allowed
          This MIB entry determines if a privileged user inside a jail will be
          able to mount and unmount file system types marked as jail-friendly.
          The lsvfs(1) command can be used to find file system types available
          for mount from within a jail.  This functionality is disabled by
          default, but can be enabled by setting this MIB entry to 1.

このフラグが立っていても、そのファイルシステムがjail-friendlyでなければjail内でマウントできないぽい。
ファイルシステムがjail-friendlyかどうか調べるには、「lsvfs(1)」が使えるとのこと。


lsvfs(1)をjailホストで実行してみる。

$ lsvfs 
Filesystem                        Refs Flags
-------------------------------- ----- ---------------
ufs                                  4 
procfs                               1 synthetic
nfs                                  0 network
devfs                                2 synthetic
msdosfs                              0 
cd9660                               0 read-only
nfs4                                 0 network
nullfs                               1 loopback
fdescfs                              1 synthetic

lsvfsのmanを見たが、「Flags」の意味が分からないのでソースを読む。

$ locate lsvfs
/usr/bin/lsvfs
/usr/jails/basejail/usr/bin/lsvfs
/usr/jails/tinderbox.dip.jp/basejail/usr/bin/lsvfs
/usr/share/man/man1/lsvfs.1.gz
/usr/src/usr.bin/lsvfs
/usr/src/usr.bin/lsvfs/Makefile
/usr/src/usr.bin/lsvfs/lsvfs.1
/usr/src/usr.bin/lsvfs/lsvfs.c


$ vim /usr/src/usr.bin/lsvfs/lsvfs.c
static const char *
fmt_flags(int flags)
{ 
  /*
   * NB: if you add new flags, don't forget to add them here vvvvvv too.
   */
  static char buf[sizeof
    "static, network, read-only, synthetic, loopback, unicode, jail"];
  int comma = 0;

  buf[0] = '\0';

  if(flags & VFCF_STATIC) {
    if(comma++) strcat(buf, ", ");
    strcat(buf, "static");
  }

  if(flags & VFCF_NETWORK) {
    if(comma++) strcat(buf, ", ");
    strcat(buf, "network");
  }

  if(flags & VFCF_READONLY) {
    if(comma++) strcat(buf, ", ");
    strcat(buf, "read-only");
  }

  if(flags & VFCF_SYNTHETIC) {
    if(comma++) strcat(buf, ", ");
    strcat(buf, "synthetic");
  }

  if(flags & VFCF_LOOPBACK) {
    if(comma++) strcat(buf, ", ");
    strcat(buf, "loopback");
  }

  if(flags & VFCF_UNICODE) {
    if(comma++) strcat(buf, ", ");
    strcat(buf, "unicode");
  }

  if(flags & VFCF_JAIL) {
    if(comma++) strcat(buf, ", ");
    strcat(buf, "jail");
  }

  return buf;
}

VFCF_*ヘッダの意味を調べる。

$ grep -nr VFCF_LOOPBACK /usr/include/
/usr/include/sys/mount.h:453:#define    VFCF_LOOPBACK   0x00100000      /* aliases some other mounted FS */

$ vi /usr/include/sys/mount.h
/*
 * NB: these flags refer to IMPLEMENTATION properties, not properties of
 * any actual mounts; i.e., it does not make sense to change the flags.
 */
#define VFCF_STATIC     0x00010000      /* statically compiled into kernel */
#define VFCF_NETWORK    0x00020000      /* may get data over the network */
#define VFCF_READONLY   0x00040000      /* writes are not implemented */
#define VFCF_SYNTHETIC  0x00080000      /* data does not represent real files */
#define VFCF_LOOPBACK   0x00100000      /* aliases some other mounted FS */
#define VFCF_UNICODE    0x00200000      /* stores file names as Unicode */
#define VFCF_JAIL       0x00400000      /* can be mounted from within a jail */

VFCF_JAILというフラグが立っているファイルシステムであれば、jail内からマウント可能らしい。改めてlsvfsの出力を見てみる。

$ lsvfs
Filesystem                        Refs Flags
-------------------------------- ----- ---------------
ufs                                  4 
procfs                               1 synthetic
nfs                                  0 network
devfs                                2 synthetic
msdosfs                              0 
cd9660                               0 read-only
nfs4                                 0 network
nullfs                               1 loopback
fdescfs                              1 synthetic

nullfsはjailフラグが立っていないのでjail内からのマウントはできない…。
他のファイルシステムを見てもjailフラグが立っているものは無いので、この中にはjail内からのマウントができるファイルシステムは無いということになる。。


以下のリンクでも同じことが議論されていた:
Re: mount_nullfs inside a jail
このリンク先の内容を信じると、以下のようにしたら、nullfsでもjail内でマウントできるようになったとのこと:

/usr/src/sys/fs/nullfs/null_vfsops.c の以下の行を編集

/* VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK); */
VFS_SET(null_vfsops, nullfs, VFCF_LOOPBACK | VFCF_JAIL);

たぶんカーネルの再構築が必要。
やったことないので調べる。
ttt: FreeBSD 6.3-RELEASEとiPod nano 8GB (第三世代) など参考にさせていただいて、あとでやってみる。

security.jail.enforce_statfs を 0 にセットする

これでjail内からでもnullfsマウントができるようになったらしい。

TODO

/usr/src/sys/fs/nullfs/null_vfsops.c を編集
FreeBSDのカーネル再構築方法を調べて実施。
yak shaving...