示例#1
0
def make_osroot(root_dir, app, data):
    """Creates mandatory system directories in the container chroot."""
    _LOGGER.info('Creating os root in: %s', root_dir)
    # Mount .../tickets .../keytabs on tempfs, so that they will be cleaned
    # up when the container exits.
    #
    for tmpfsdir in [
            '/var/spool/tickets', '/var/spool/keytabs', '/var/spool/tokens'
    ]:
        fs_linux.mount_tmpfs(root_dir, tmpfsdir)

    # /var/empty must be owned by root and not group or world-writable.
    os.chmod(os.path.join(root_dir, 'var/empty'), 0o711)

    # Mount a new sysfs for the container, bring in the /sys/fs subtree from
    # the host.
    fs_linux.mount_sysfs(root_dir)
    fs_linux.mount_bind(root_dir,
                        os.path.join(os.sep, 'sys', 'fs'),
                        recursive=True,
                        read_only=False)

    make_dev(root_dir)
    # Passthrough node devices per the node config data
    extra_devices = data.get('runtime', {}).get('passthrough_devices', [])
    make_extra_dev(root_dir, extra_devices, app.proid)

    # Per FHS3 /var/run should be a symlink to /run which should be tmpfs
    fs.symlink_safe(os.path.join(root_dir, 'var', 'run'), '/run')
    # We create an unbounded tmpfs mount so that runtime data can be written to
    # it, counting against the memory limit of the container.
    fs_linux.mount_tmpfs(root_dir, '/run')

    # /etc/docker is a file neceesary for docker daemon
    _docker.prepare_docker_daemon_path(root_dir, app, data)
示例#2
0
def make_dev(newroot_norm):
    """Make /dev.
    """
    fs_linux.mount_tmpfs(newroot_norm,
                         '/dev',
                         nodev=False,
                         noexec=False,
                         nosuid=True,
                         relatime=False,
                         mode='0755')

    devices = [
        ('/dev/null', 0o666, 1, 3),
        ('/dev/zero', 0o666, 1, 5),
        ('/dev/full', 0o666, 1, 7),
        ('/dev/tty', 0o666, 5, 0),
        ('/dev/random', 0o444, 1, 8),
        ('/dev/urandom', 0o444, 1, 9),
    ]
    prev_umask = os.umask(0000)
    for device, permissions, major, minor in devices:
        os.mknod(newroot_norm + device, permissions | stat.S_IFCHR,
                 os.makedev(major, minor))
    os.umask(prev_umask)
    st = os.stat('/dev/tty')
    os.chown(newroot_norm + '/dev/tty', st.st_uid, st.st_gid)

    symlinks = [
        ('/dev/fd', '/proc/self/fd'),
        ('/dev/stdin', '/proc/self/fd/0'),
        ('/dev/stdout', '/proc/self/fd/1'),
        ('/dev/stderr', '/proc/self/fd/2'),
        ('/dev/core', '/proc/kcore'),
    ]
    for link, target in symlinks:
        fs.symlink_safe(newroot_norm + link, target)

    for directory in ['/dev/shm', '/dev/pts', '/dev/mqueue']:
        fs.mkdir_safe(newroot_norm + directory)
    fs_linux.mount_tmpfs(newroot_norm,
                         '/dev/shm',
                         nodev=True,
                         noexec=False,
                         nosuid=True,
                         relatime=False)
    fs_linux.mount_devpts(newroot_norm,
                          '/dev/pts',
                          gid=st.st_gid,
                          mode='0620',
                          ptmxmode='0666')
    fs.symlink_safe(newroot_norm + '/dev/ptmx', 'pts/ptmx')
    fs_linux.mount_mqueue(newroot_norm, '/dev/mqueue')

    # Passthrough container log to host system logger.
    fs_linux.mount_bind(newroot_norm, '/dev/log', read_only=False)
示例#3
0
def mount_docker_daemon_path(newroot_norm, app):
    """Mount tmpfs for docker
    """
    if not _has_docker(app):
        return

    # /etc/docker as temp fs as dockerd create /etc/docker/key.json
    try:
        fs_linux.mount_tmpfs(newroot_norm, '/etc/docker')
    except FileNotFoundError as err:
        _LOGGER.error('Failed to mount docker tmpfs: %s', err)
        # this exception is caught by sproc run to generate abort event
        raise exc.ContainerSetupError(
            msg=str(err),
            reason=app_abort.AbortedReason.UNSUPPORTED,
        )
示例#4
0
def make_fsroot(root_dir, app, data):
    """Initializes directory structure for the container in a new root.

    The container uses pretty much a blank a FHS 3 layout.

     - Bind directories in parent / (with exceptions - see below.)
     - Skip /tmp, create /tmp in the new root with correct permissions.
     - Selectively create / bind /var.
       - /var/tmp (new)
       - /var/log (new)
       - /var/spool - create empty with dirs.
     - Bind everything in /var, skipping /spool/tickets

    :param ``str`` root_dit:
        Container root directory.
    :param app:
        Container app manifest.
    :param ``dict`` data:
        Local configuration data.
    """
    newroot_norm = fs.norm_safe(root_dir)

    emptydirs = [
        '/bin',
        '/dev',
        '/etc',
        '/home',
        '/lib',
        '/lib64',
        '/opt',
        '/proc',
        '/root',
        '/run',
        '/sbin',
        '/sys',
        '/tmp',
        '/usr',
        '/var/cache',
        '/var/empty',
        '/var/empty/sshd',
        '/var/lib',
        '/var/lock',
        '/var/log',
        '/var/opt',
        '/var/spool',
        '/var/tmp',
        '/var/spool/keytabs',
        '/var/spool/tickets',
        '/var/spool/tokens',
        # for SSS
        '/var/lib/sss',
    ]

    stickydirs = [
        '/opt',
        '/run',
        '/tmp',
        '/var/cache',
        '/var/lib',
        '/var/lock',
        '/var/log',
        '/var/opt',
        '/var/tmp',
        '/var/spool/keytabs',
        '/var/spool/tickets',
        '/var/spool/tokens',
    ]

    # these folders are shared with underlying host and other containers,
    mounts = [
        '/bin',
        '/etc',  # TODO: Add /etc/opt
        '/lib',
        '/lib64',
        '/root',
        '/sbin',
        '/usr',
        # for SSS
        '/var/lib/sss',
        # TODO: Remove below once PAM UDS is implemented
        os.path.expandvars('${TREADMILL_APPROOT}/env'),
        os.path.expandvars('${TREADMILL_APPROOT}/spool'),
    ]

    for directory in emptydirs:
        fs.mkdir_safe(newroot_norm + directory)

    for directory in stickydirs:
        os.chmod(newroot_norm + directory, 0o777 | stat.S_ISVTX)

    # /var/empty must be owned by root and not group or world-writable.
    os.chmod(os.path.join(newroot_norm, 'var/empty'), 0o711)

    # Mount a new sysfs for the container, bring in the /sys/fs subtree from
    # the host.
    fs_linux.mount_sysfs(newroot_norm)
    fs_linux.mount_bind(newroot_norm,
                        os.path.join(os.sep, 'sys', 'fs'),
                        recursive=True,
                        read_only=False)

    make_dev(newroot_norm)
    # Passthrough node devices per the node config data
    extra_devices = data.get('runtime', {}).get('passthrough_devices', [])
    make_extra_dev(newroot_norm, extra_devices, app.proid)

    # Per FHS3 /var/run should be a symlink to /run which should be tmpfs
    fs.symlink_safe(os.path.join(newroot_norm, 'var', 'run'), '/run')
    # We create an unbounded tmpfs mount so that runtime data can be written to
    # it, counting against the memory limit of the container.
    fs_linux.mount_tmpfs(newroot_norm, '/run')

    # Make shared directories/files readonly to container
    for mount in mounts:
        if os.path.exists(mount):
            fs_linux.mount_bind(newroot_norm,
                                mount,
                                recursive=True,
                                read_only=True)

    # /etc/docker is a file neceesary for docker daemon
    _docker.mount_docker_daemon_path(newroot_norm, app)
示例#5
0
def _mount_docker_tmpfs(newroot_norm):
    """Mount tmpfs for docker
    """
    # /etc/docker as temp fs as dockerd create /etc/docker/key.json
    fs_linux.mount_tmpfs(newroot_norm, '/etc/docker')
示例#6
0
def make_fsroot(root_dir, app):
    """Initializes directory structure for the container in a new root.

    The container uses pretty much a blank a FHS 3 layout.

     - Bind directories in parent / (with exceptions - see below.)
     - Skip /tmp, create /tmp in the new root with correct permissions.
     - Selectively create / bind /var.
       - /var/tmp (new)
       - /var/log (new)
       - /var/spool - create empty with dirs.
     - Bind everything in /var, skipping /spool/tickets

     tm_env is used to deliver abort events
     """
    newroot_norm = fs.norm_safe(root_dir)

    emptydirs = [
        '/bin',
        '/dev',
        '/etc',
        '/home',
        '/lib',
        '/lib64',
        '/opt',
        '/proc',
        '/root',
        '/run',
        '/sbin',
        '/sys',
        '/tmp',
        '/usr',
        '/var/cache',
        '/var/empty',
        '/var/empty/sshd',
        '/var/lib',
        '/var/lock',
        '/var/log',
        '/var/opt',
        '/var/spool',
        '/var/tmp',
        '/var/spool/keytabs',
        '/var/spool/tickets',
        '/var/spool/tokens',
        # for SSS
        '/var/lib/sss',
    ]

    stickydirs = [
        '/opt',
        '/run',
        '/tmp',
        '/var/cache',
        '/var/lib',
        '/var/lock',
        '/var/log',
        '/var/opt',
        '/var/tmp',
        '/var/spool/keytabs',
        '/var/spool/tickets',
        '/var/spool/tokens',
    ]

    # these folders are shared with underlying host and other containers,
    mounts = [
        '/bin',
        '/etc',  # TODO: Add /etc/opt
        '/lib',
        '/lib64',
        '/root',
        '/sbin',
        '/usr',
        # for SSS
        '/var/lib/sss',
        # TODO: Remove below once PAM UDS is implemented
        os.path.expandvars('${TREADMILL_APPROOT}/env'),
        os.path.expandvars('${TREADMILL_APPROOT}/spool'),
    ]

    for directory in emptydirs:
        fs.mkdir_safe(newroot_norm + directory)

    for directory in stickydirs:
        os.chmod(newroot_norm + directory, 0o777 | stat.S_ISVTX)

    # /var/empty must be owned by root and not group or world-writable.
    os.chmod(os.path.join(newroot_norm, 'var/empty'), 0o711)

    fs_linux.mount_bind(newroot_norm,
                        os.path.join(os.sep, 'sys'),
                        source='/sys',
                        recursive=True,
                        read_only=False)

    make_dev(newroot_norm)

    # Per FHS3 /var/run should be a symlink to /run which should be tmpfs
    fs.symlink_safe(os.path.join(newroot_norm, 'var', 'run'), '/run')
    # We create an unbounded tmpfs mount so that runtime data can be written to
    # it, counting against the memory limit of the container.
    fs_linux.mount_tmpfs(newroot_norm, '/run')

    # Make shared directories/files readonly to container
    for mount in mounts:
        if os.path.exists(mount):
            fs_linux.mount_bind(newroot_norm,
                                mount,
                                recursive=True,
                                read_only=True)

    if hasattr(app, 'docker') and app.docker:
        # If unable to mount docker directory, we throw Aborted events
        try:
            _mount_docker_tmpfs(newroot_norm)
        except FileNotFoundError as err:
            _LOGGER.error('Failed to mount docker tmpfs: %s', err)
            # this exception is caught by sproc run to generate abort event
            raise exc.ContainerSetupError(
                msg=str(err),
                reason=app_abort.AbortedReason.UNSUPPORTED,
            )
示例#7
0
def make_fsroot(root_dir):
    """Initializes directory structure for the container in a new root.

    The container uses pretty much a blank a FHS 3 layout.

     - Bind directories in parent / (with exceptions - see below.)
     - Skip /tmp, create /tmp in the new root with correct permissions.
     - Selectively create / bind /var.
       - /var/tmp (new)
       - /var/log (new)
       - /var/spool - create empty with dirs.
     - Bind everything in /var, skipping /spool/tickets
     """
    newroot_norm = fs.norm_safe(root_dir)

    emptydirs = [
        '/bin',
        '/dev',
        '/etc',
        '/home',
        '/lib',
        '/lib64',
        '/opt',
        '/proc',
        '/root',
        '/run',
        '/sbin',
        '/sys',
        '/tmp',
        '/usr',
        '/var/cache',
        '/var/empty',
        '/var/lib',
        '/var/lock',
        '/var/log',
        '/var/opt',
        '/var/spool',
        '/var/tmp',
        '/var/spool/keytabs',
        '/var/spool/tickets',
        '/var/spool/tokens',
        # for SSS
        '/var/lib/sss',
    ]

    stickydirs = [
        '/opt',
        '/run',
        '/tmp',
        '/var/cache',
        '/var/lib',
        '/var/lock',
        '/var/log',
        '/var/opt',
        '/var/tmp',
        '/var/spool/keytabs',
        '/var/spool/tickets',
        '/var/spool/tokens',
    ]

    # these folders are shared with underlying host and other containers,
    mounts = [
        '/bin',
        '/etc',  # TODO: Add /etc/opt
        '/lib',
        '/lib64',
        '/root',
        '/sbin',
        '/usr',
        # for SSS
        '/var/lib/sss',
        # TODO: Remove below once PAM UDS is implemented
        '/var/tmp/treadmill/env',
        '/var/tmp/treadmill/spool',
    ]

    # Add everything under /opt
    mounts += glob.glob('/opt/*')

    for directory in emptydirs:
        fs.mkdir_safe(newroot_norm + directory)

    for directory in stickydirs:
        os.chmod(newroot_norm + directory, 0o777 | stat.S_ISVTX)

    # /var/empty must be owned by root and not group or world-writable.
    os.chmod(os.path.join(newroot_norm, 'var/empty'), 0o711)

    fs_linux.mount_bind(newroot_norm,
                        os.path.join(os.sep, 'sys'),
                        source='/sys',
                        recursive=True,
                        read_only=False)
    # TODO: For security, /dev/ should be minimal and separated to each
    #       container.
    fs_linux.mount_bind(newroot_norm,
                        os.path.join(os.sep, 'dev'),
                        source='/dev',
                        recursive=True,
                        read_only=False)
    # Per FHS3 /var/run should be a symlink to /run which should be tmpfs
    fs.symlink_safe(os.path.join(newroot_norm, 'var', 'run'), '/run')
    # We create an unbounded tmpfs mount so that runtime data can be written to
    # it, counting against the memory limit of the container.
    fs_linux.mount_tmpfs(newroot_norm, '/run')

    # Make shared directories/files readonly to container
    for mount in mounts:
        if os.path.exists(mount):
            fs_linux.mount_bind(newroot_norm,
                                mount,
                                recursive=True,
                                read_only=True)