[GH-ISSUE #721] chroot fs implementation #491

Closed
opened 2026-05-05 05:57:44 -06:00 by gitea-mirror · 15 comments
Owner

Originally created by @nuxwin on GitHub (Aug 16, 2016).
Original GitHub issue: https://github.com/netblue30/firejail/issues/721

The actual chroot fs implementation is badly designed.

Current behavior

When running firejail with the --chroot option, many parts of the system fs is remounted inside the chroot

Expected behavior

When runnin firejail with the --chroot option, no part of the system fs should be remounted inside the chroot. FireJail should act on the chroot fs only.

Scenario

An administrator will create a chroot fs using a tool such as debootstrap, makejail ... In such case, the chroot will already have its own fs tree (/proc, /dev, /sys, /etc ....)

The problem is that currently, firejail will acts on the system fs, even in the --chroot option usage case while it should only act on the fs chroot.

Acting on system fs is wrong. Let assume a restricted /dev already mounted in chroot fs. With current implementation, firejail will totally ignore it. It will remout /dev from system fs. That is a bad design.

How to solve

The chroot() system call should be done just after the chroot integrity check and before any remount.

Originally created by @nuxwin on GitHub (Aug 16, 2016). Original GitHub issue: https://github.com/netblue30/firejail/issues/721 The actual chroot fs implementation is badly designed. **Current behavior** When running firejail with the `--chroot` option, many parts of the system fs is remounted inside the chroot **Expected behavior** When runnin firejail with the `--chroot` option, no part of the system fs should be remounted inside the chroot. FireJail should act on the chroot fs only. **Scenario** An administrator will create a chroot fs using a tool such as debootstrap, makejail ... In such case, the chroot will already have its own fs tree (/proc, /dev, /sys, /etc ....) The problem is that currently, firejail will acts on the system fs, even in the `--chroot` option usage case while it should only act on the fs chroot. Acting on system fs is wrong. Let assume a restricted `/dev` already mounted in chroot fs. With current implementation, firejail will totally ignore it. It will remout /dev from system fs. That is a bad design. **How to solve** The chroot() system call should be done just after the chroot integrity check and before any remount.
gitea-mirror 2026-05-05 05:57:44 -06:00
Author
Owner

@manevich commented on GitHub (Aug 16, 2016):

You are right, lot of thing firejail do are unneeded for chroot, namely:
remounting /etc/passwd, /etc/group, /var/tmp, /var/log and alike.

But not everything you mention is unneeded:

  • Just looked on freshly built debootstrap chroot: obviously /sys and /proc are empty. Why mount them by hand or script and not using firejail?
  • Remounting /proc AFAIK required to get /proc limited by process namespace. Otherwise /proc containing all system processes will be exposed. Some remounting in /proc added to protect sensitive parts.
  • /run/firejail/ is remounted for internal purposes, so all depending features will be lost.
  • Firejail has own options for /dev restriction. /sys is also remounted to protect sensitive parts. Option for skipping /dev mounting will be nice, but why not rely on firejail for /dev protection by default?

PS: Thanks for rising chroot mater, it got not too much attention before.

<!-- gh-comment-id:240223812 --> @manevich commented on GitHub (Aug 16, 2016): You are right, lot of thing firejail do are unneeded for chroot, namely: remounting `/etc/passwd`, `/etc/group`, `/var/tmp`, `/var/log` and alike. But not everything you mention is unneeded: - Just looked on freshly built debootstrap chroot: obviously `/sys` and `/proc` are empty. Why mount them by hand or script and not using firejail? - Remounting `/proc` AFAIK required to get `/proc` limited by process namespace. Otherwise `/proc` containing all system processes will be exposed. Some remounting in `/proc` added to protect sensitive parts. - `/run/firejail/` is remounted for internal purposes, so all depending features will be lost. - Firejail has own options for `/dev` restriction. `/sys` is also remounted to protect sensitive parts. Option for skipping `/dev` mounting will be nice, but why not rely on firejail for `/dev` protection by default? PS: Thanks for rising chroot mater, it got not too much attention before.
Author
Owner

@nuxwin commented on GitHub (Aug 16, 2016):

@manevich

In my case, we have a jail builder which take care of that. Also, this allow the admin to choose what must be mounted in the chroot or not. FirJjail can remount fs from chroot instead of system. Eg, /proc from the chroot can be remounted by firejail.

For, instance, my jail builder config for bashshell:

...
    // GNU Bourne-Again SHell
    'bashshell'                     => array(
        'users'                     => array(
            $config['ROOT_USER'], 'syslog', 'www-data'
        ),
        'groups'                    => array(
            'adm', $config['ROOT_GROUP'], 'syslog', 'www-data'
        ),
        'paths'                     => array(
            'sh', 'bash', 'ls', 'cat', 'chmod', 'mkdir', 'cp', 'cpio', 'date', 'dd', 'echo', 'egrep', 'false', 'fgrep',
            'grep', 'gunzip', 'gzip', 'ln', 'mktemp', 'more', 'mv', 'pwd', 'rm', 'rmdir', 'ps', 'sed', 'sleep', 'sync',
            'tar', 'basename', 'touch', 'true', 'uncompress', 'zcat', '/etc/issue', '/etc/bash.bashrc', 'dircolors',
            'tput', 'awk', 'bzip2', 'bunzip2', 'ldd', 'less', 'clear', 'cut', 'du', 'find', 'head', 'md5sum', 'nice',
            'sort',  'tac', 'tail', 'tr', 'wc', 'watch', 'whoami', 'id', 'hostname', 'lzma', 'xz', 'pbzip2', 'env',
            'readlink', 'groups', '/usr/lib/locale/C.UTF-8', 'logger'
        ),
        'discard_paths'             => array(
            '/usr/share/doc', '/usr/share/info', '/usr/share/man', '/etc/fstab', '/etc/mtab', '/proc'
        ),
        'create_dirs'               => array(
            '/home'    => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            ),
            '/tmp'     => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 01777
            ),
            '/var/log' => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            )
        ),
        'jail_copy_file_to'         => array(
            __DIR__ . '/config/etc/profile' => array(
                'destination' => '/etc/profile',
                'preserve'    => false
            )
        ),
        'include_app_sections'      => array(
            'uidbasics', 'logbasics', 'terminfo'
        ),
        'devices'                   => array(
            '/dev/null', '/dev/ptmx', '/dev/random', '/dev/urandom', '/dev/zero'
        ),
        'fstab'                     => array(
            array(
                'fs_spec'    => 'devpts',
                'fs_file'    => '/dev/pts',
                'fs_vfstype' => 'devpts',
                'fs_mntops'  => 'gid=5,mode=620'
            ),
            array(
                'fs_spec'    => 'proc',
                'fs_file'    => '/proc',
                'fs_vfstype' => 'proc',
                'fs_mntops'  => 'defaults'
            ),
            array(
                'fs_spec'    => 'sysfs',
                'fs_file'    => '/sys',
                'fs_vfstype' => 'sysfs',
                'fs_mntops'  => 'defaults'
            ),
            array(
                'fs_spec'    => '/var/log/lastlog',
                'fs_file'    => '/var/log/lastlog',
                'fs_vfstype' => 'none',
                'fs_mntops'  => 'bind'
            )
        ),
        'create_sys_commands_args'  => array(
            'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl /var/log/lastlog',
            //'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl ' . $config['USER_WEB_DIR'] . '/*'
        ),
        'destroy_sys_commands_args' => array(
            'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl /var/log/lastlog',
            //'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl ' . $config['USER_WEB_DIR'] . '/*'
        ),
        'create_symlinks'           => array(
            '/bin/sh' => '/bin/bash',
        )
    ),
...

The fstab entries you can see are mounted from system fs to chroot fs. Firejail should acts on chroot fs (remount /dev and so on from chroot fs instead of system fs). It is only a partial part of my config files. There is other applications sections in which other fstab entries are added...

Anyway, I'll create a patch covering all this, adding also option to switch-back to current behavior ;)

<!-- gh-comment-id:240225578 --> @nuxwin commented on GitHub (Aug 16, 2016): @manevich In my case, we have a jail builder which take care of that. Also, this allow the admin to choose what must be mounted in the chroot or not. FirJjail can remount fs from chroot instead of system. Eg, /proc from the chroot can be remounted by firejail. For, instance, my jail builder config for bashshell: ``` php ... // GNU Bourne-Again SHell 'bashshell' => array( 'users' => array( $config['ROOT_USER'], 'syslog', 'www-data' ), 'groups' => array( 'adm', $config['ROOT_GROUP'], 'syslog', 'www-data' ), 'paths' => array( 'sh', 'bash', 'ls', 'cat', 'chmod', 'mkdir', 'cp', 'cpio', 'date', 'dd', 'echo', 'egrep', 'false', 'fgrep', 'grep', 'gunzip', 'gzip', 'ln', 'mktemp', 'more', 'mv', 'pwd', 'rm', 'rmdir', 'ps', 'sed', 'sleep', 'sync', 'tar', 'basename', 'touch', 'true', 'uncompress', 'zcat', '/etc/issue', '/etc/bash.bashrc', 'dircolors', 'tput', 'awk', 'bzip2', 'bunzip2', 'ldd', 'less', 'clear', 'cut', 'du', 'find', 'head', 'md5sum', 'nice', 'sort', 'tac', 'tail', 'tr', 'wc', 'watch', 'whoami', 'id', 'hostname', 'lzma', 'xz', 'pbzip2', 'env', 'readlink', 'groups', '/usr/lib/locale/C.UTF-8', 'logger' ), 'discard_paths' => array( '/usr/share/doc', '/usr/share/info', '/usr/share/man', '/etc/fstab', '/etc/mtab', '/proc' ), 'create_dirs' => array( '/home' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ), '/tmp' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 01777 ), '/var/log' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ) ), 'jail_copy_file_to' => array( __DIR__ . '/config/etc/profile' => array( 'destination' => '/etc/profile', 'preserve' => false ) ), 'include_app_sections' => array( 'uidbasics', 'logbasics', 'terminfo' ), 'devices' => array( '/dev/null', '/dev/ptmx', '/dev/random', '/dev/urandom', '/dev/zero' ), 'fstab' => array( array( 'fs_spec' => 'devpts', 'fs_file' => '/dev/pts', 'fs_vfstype' => 'devpts', 'fs_mntops' => 'gid=5,mode=620' ), array( 'fs_spec' => 'proc', 'fs_file' => '/proc', 'fs_vfstype' => 'proc', 'fs_mntops' => 'defaults' ), array( 'fs_spec' => 'sysfs', 'fs_file' => '/sys', 'fs_vfstype' => 'sysfs', 'fs_mntops' => 'defaults' ), array( 'fs_spec' => '/var/log/lastlog', 'fs_file' => '/var/log/lastlog', 'fs_vfstype' => 'none', 'fs_mntops' => 'bind' ) ), 'create_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl /var/log/lastlog', //'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl ' . $config['USER_WEB_DIR'] . '/*' ), 'destroy_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl /var/log/lastlog', //'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl ' . $config['USER_WEB_DIR'] . '/*' ), 'create_symlinks' => array( '/bin/sh' => '/bin/bash', ) ), ... ``` The fstab entries you can see are mounted from system fs to chroot fs. Firejail should acts on chroot fs (remount /dev and so on from chroot fs instead of system fs). It is only a partial part of my config files. There is other applications sections in which other fstab entries are added... Anyway, I'll create a patch covering all this, adding also option to switch-back to current behavior ;)
Author
Owner

@nuxwin commented on GitHub (Aug 16, 2016):

@manevich

Best is to show you the full config file:

$config = iMSCP_Registry::get('config');

return array(
    // SSH daemon service name (default: ssh)
    'ssh_service_name'              => 'ssh',

    // SSH daemon configuration file path (default: /etc/ssh/sshd_config)
    'sshd_config_file_path'         => '/etc/ssh/sshd_config',

    // Base directory for SSH daemon authorized_keys files (default: /usr/local/etc/InstantSSH)
    // WARNING: Don't change this parameter unless you know what you are doing.
    'sshd_authorized_keys_base_dir' => '/etc/InstantSSH',

    // SSH user name prefix (default: imscp_)
    //
    // This is a security measurement which prevents usage of system users.
    // WARNING: You *must* never set this parameter to an empty value.
    'ssh_user_name_prefix'          => 'imscp_',

    // Passwordless authentication (default: false)
    //
    // When set to TRUE, passwordless authentication is enforced, meaning that the customers cannot set password for
    // their SSH users. This implies necessarily that the customers have to provide a SSH key. When set to FALSE, both
    // authentication methods (password and key) are available. In such a case, customers can provide either a password,
    // either a key, or both.
    //
    // Note: This applies only to newly created or updated SSH users
    'passwordless_authentication'   => false,

    // Default SSH authentication options for new SSH keys
    //
    // See man sshd(8) for a list of allowed authentication options.
    // e.g. command="dump /home",no-pty,no-port-forwarding
    //
    // WARNING: Any option defined here must be specified in the allowed_ssh_auth_options configuration option.
    'default_ssh_auth_options'      => 'no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-user-rc',

    // SSH authentication options that customers can setup when they are allowed to override defaults.
    //
    // Supported options are:
    //
    // \InstantSSH\Validate\SshAuthOptions::ALL (all options)
    // \InstantSSH\Validate\SshAuthOptions::CERT_AUTHORITY (cert-authority option)
    // \InstantSSH\Validate\SshAuthOptions::COMMAND (command option)
    // \InstantSSH\Validate\SshAuthOptions::ENVIRONMENT (environment option)
    // \InstantSSH\Validate\SshAuthOptions::FROM (from option)
    // \InstantSSH\Validate\SshAuthOptions::NO_AGENT_FORWARDING (no-agent-forwarding option)
    // \InstantSSH\Validate\SshAuthOptions::NO_PORT_FORWARDING (no-port-forwarding option)
    // \InstantSSH\Validate\SshAuthOptions::NO_PTY (no-pty option)
    // \InstantSSH\Validate\SshAuthOptions::NO_USER_RC (no-user-rc option)
    // \InstantSSH\Validate\SshAuthOptions::NO_X11_FORWARDING (no-x11-forwarding option)
    // \InstantSSH\Validate\SshAuthOptions::PERMITOPEN (permitopen option)
    // \InstantSSH\Validate\SshAuthOptions::PRINCIPALS (principals option)
    // \InstantSSH\Validate\SshAuthOptions::TUNNEL (tunnel option)
    'allowed_ssh_auth_options'      => array(
        \InstantSSH\Validate\SshAuthOptions::ALL
    ),

    // Root jail directory (default: /var/chroot/InstantSSH)
    //
    // Full path to the root jail directory. Be sure that the partition in which this directory is living has enough
    // space to host the jails.
    //
    // WARNING: Don't change this parameter unless you know what you are doing.
    'root_jail_dir'                 => '/var/chroot/InstantSSH',

    // Makejail script path
    'makejail_path'                 => __DIR__ . '/scripts/makejail',

    // Makejail configuration directory (default: <CONF_DIR>/InstantSSH)
    'makejail_confdir_path'         => $config['CONF_DIR'] . '/InstantSSH',

    // pam_chroot configuration file path (default: /etc/security/chroot.conf)
    'pam_chroot_conffile_path'      => '/etc/security/chroot.conf',

    // Jail builder (default: MakeJail)
    //
    // Available jail builders:
    //  MakeJail: Create jails using `makejail'. Only the filesystem is isolated using the chroot() system call.
    //  FireJail: Create jails using `makejail' and isolate them with `FireJail'. FireJail provides a full isolation
    //            through the Linux kernel, via Linux namespaces, seccomp-bpf and Linux capabilities features.
    //
    // Note that support for `FireJail' has been added lately and that it is still EXPERIMENTAL.
    'jail_builder'                  => 'FireJail',

    // Shared jail (default: true)
    //
    // When set to true, only one jail is created for all customers. A shared jail doesn't means that the customers will
    // be able to read, modify or delete files of other customers. This simply means that the jail will be shared
    // between the customers. The primary purpose of a jailed environment is to protect the main system. Having a jail
    // for each customer is interesting only when you want provide a different set of commands for each of them.
    //
    // Note: The creation of a jail per customer is currently useless because the per customer application feature is
    // not implemented yet. This will be implemented in near future.
    'shared_jail'                   => true,

    // Preserved files (default: <USER_WEB_DIR>)
    //
    // The plugin won't try to remove files or directories inside jails if their path begins with one of the strings
    // in this list.
    //
    // This option can be also defined in the application sections (see below).
    //
    // WARNING: Do not remove the default entries if you don't know what you are doing.
    'preserve_files'                => array(
        '/home'
    ),

    // Whether or not files from packages that are dependencies of packages listed in the 'packages' option of the
    // application sections must be copied within the jails
    'include_pkg_deps'              => false,

    // Application sections (default: 'ashshell', 'netutils', 'editors', 'imscp_web_tree')
    //
    // This is the list of application sections which are used to create/update the jails (see below).
    'app_sections'                  => array(
        //'ashshell',
        'bashshell',
        #'netutils',
        #'editors',
        //'composer'
        //'imscp_web_tree'
    ),

    // Application sections definitions
    //
    // Below, you can find the application sections for jailed shell environments. Those application sections are used
    // to create and update the jails. They allow you to define which softwares, libraries, devices... must be copied
    // inside the jail.
    //
    // You can select as many application sections as you want by adding them into the `app_sections' configuration
    // option above.
    //
    // It is not recommended to change an application section without understanding its meaning and how it is working.
    // Once you know how the a application sections are defined, you can define your own.
    //
    // Application section options
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //
    // The following options can be defined in application sections:
    //
    // paths: List of paths to copy inside the jails.
    // discard_paths: List of paths which must be discarded in any case (not copied). This option has a higher precedence
    //                than the `paths' options.
    // create_dirs: List of directories to create inside jail where each key is a directory path inside the jail, and
    //              the value, an associative array describing directory properties:
    //               - user: Directory owner
    //               - group: Directory group
    //               - mode: Directory permissions
    // create_symlinks: List of symlinks to create inside jail where keys are link paths and values are target paths.
    // packages: List of Debian packages. Files from those packages will be copied inside jail.
    // discard_packages: List of debian packages to discard. (Only relevant if the `include_pkg_deps' configuration
    //                   option is set to true).
    // sys_copy_file_to: List of files to copy outside the jail, each of them specified as a key/value pair, where the
    //                   key is the source file path and the value, an associative array describing copy options:
    //                    - destination: destination path
    //                    - preserve: Boolean indicating whether or not user, group and mode must be copied
    // jail_copy_file_to: List of files to copy inside the jail, each of them specified as a key/value pair, where the
    //                    key is the source file path and the value, an associative array describing copy options:
    //                     - destination: destination path
    //                     - preserve: Boolean indicating whether or not user, group and mode must be copied
    // include_apps_sections: List of applications sections to be included (e.g. for dependencies)
    // users: List of users to add inside the jail (e.g: in passwd/shadow files).
    // groups: List of groups to add inside the jail (e.g: in group/gshadow files).
    // preserve_files: List of files to preserve when the jails are updated.
    // devices: List of devices to copy inside the jail.
    // fstab: List of fstab entries to add where each value is an array describing an fstab entry (see man fstab).
    // create_sys_commands: List of commands to execute outside the jail once built or updated.
    // create_sys_commands_args: List of commands to execute outside the jail once built or updated. Any listed command
    //                           will receive the full jail path as argument.
    // destroy_sys_commands: List of command to execute outside jail before it get destroyed.
    // destroy_sys_commands_args: List of command to execute outside jail before it get destroyed. Any listed command
    //                            will receive the full jail path as argument.
    // create_jail_commands: List of commands to execute inside jail once built or updated.
    // create_jail_commands_args: List of commands to execute inside jail once built or updated. Any listed command will
    //                            receive the full jail path as argument.
    // destroy_jail_commands: List of commands to execute inside jail before it get destroyed.
    // destroy_jail_commands_args: List of commands to execute inside jail before it get destroyed. Any listed command
    //                             will receive the full jail path as argument.
    //
    // Notes:
    //  - The paths and devices options, both support the glob patterns.
    //  - The paths option support search path
    //  - Directories specified in paths option are copied recursively.
    //  - Any path which doesn't exists on the system is ignored.
    //  - Any package listed in a package option must be already installed on the system, else an error is raised.
    //  - Any device must exists on the system, else an error is raised. You can use glob patterns to avoid error.
    //  - File systems specified in the fstab option are mounted automatically inside jail.
    //  - fs_spec field defined in the fstab option must exists, else an error is raised
    //  - Mount points defined in the fstab option must be specified without the jail root path
    //  - Command run inside jails must exist inside them

    // Common files for jails that need user/group information
    'uidbasics'                     => array(
        'paths' => array(
            '/etc/ld.so.conf', '/etc/passwd', '/etc/group', '/etc/nsswitch.conf', '/lib/libnsl.so.1',
            '/lib64/libnsl.so.1', '/lib/i386-linux-gnu/libnsl.so.1', '/lib/x86_64-linux-gnu/libnsl.so.1',
            '/lib/libnss*.so.2', '/lib64/libnss*.so.2', '/lib/i386-linux-gnu/libnss*.so.2',
            '/lib/x86_64-linux-gnu/libnss*.so.2',
        )
    ),

    // Common files for jails that need internet connectivity
    'netbasics'                     => array(
        'paths' => array(
            '/etc/resolv.conf', '/etc/host.conf', '/etc/hosts', '/etc/protocols', '/etc/services', '/etc/ssl/certs',
            '/lib/libnss_dns.so.2', '/lib64/libnss_dns.so.2', '/lib/i386-linux-gnu/libnss_dns.so.2',
            '/lib/x86_64-linux-gnu/libnss_dns.so.2'
        )
    ),

    // Timezone information and log sockets
    'logbasics'                     => array(
        'paths'                     => array(
            '/etc/localtime', '/etc/timezone'
        ),
        'create_dirs'               => array(
            '/dev' => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            )
        ),
        'preserve_files'            => array(
            '/dev/log'
        ),
        'create_sys_commands_args'  => array(
            'perl ' . __DIR__ . '/scripts/syslogproxyd.pl add'
        ),
        'destroy_sys_commands_args' => array(
            'perl ' . __DIR__ . '/scripts/syslogproxyd.pl remove'
        )
    ),

    // Restricted ash shell (BusyBox built-in Almquist shell)
    'ashshell'                      => array(
        'users'                     => array(
            $config['ROOT_USER'], 'www-data', 'syslog'
        ),
        'groups'                    => array(
            'adm', $config['ROOT_GROUP'], 'syslog', 'www-data'
        ),
        'paths'                     => array(
            'dircolors', 'tput', '/usr/lib/locale/C.UTF-8'
        ),
        'discard_paths'             => array(
            '/usr/share/doc', '/usr/share/info', '/usr/share/man', '/etc/fstab', '/etc/mtab', '/proc'
        ),
        'create_dirs'               => array(
            '/bin' => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            ),
            '/home'    => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            ),
            '/tmp'     => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 01777
            ),
            '/var/log' => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            )
        ),
        'jail_copy_file_to'         => array(
            __DIR__ . '/config/etc/profile' => array(
                'destination' => '/etc/profile',
                'preserve'    => false
            )
        ),
        'include_app_sections'      => array(
           'uidbasics', 'logbasics', 'terminfo'
        ),
        'devices'                   => array(
            '/dev/null', '/dev/ptmx', '/dev/random', '/dev/urandom', '/dev/zero'
        ),
        'fstab'                     => array(
            array(
                'fs_spec'    => 'devpts',
                'fs_file'    => '/dev/pts',
                'fs_vfstype' => 'devpts',
                'fs_mntops'  => 'gid=5,mode=620'
            ),
            array(
                'fs_spec'    => 'proc',
                'fs_file'    => '/proc',
                'fs_vfstype' => 'proc',
                'fs_mntops'  => 'defaults'
            ),
            array(
                'fs_spec'    => 'sysfs',
                'fs_file'    => '/sys',
                'fs_vfstype' => 'sysfs',
                'fs_mntops'  => 'defaults'
            ),
            array(
                'fs_spec'    => '/var/log/lastlog',
                'fs_file'    => '/var/log/lastlog',
                'fs_vfstype' => 'none',
                'fs_mntops'  => 'bind'
            )
        ),
        'create_sys_commands_args'  => array(
            'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl /var/log/lastlog',
            'perl ' . __DIR__ . '/scripts/busybox_install.pl',
            //'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl ' . $config['USER_WEB_DIR'] . '/*'
        ),
        'destroy_sys_commands_args' => array(
            'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl /var/log/lastlog',
            //'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl ' . $config['USER_WEB_DIR'] . '/*'
        )
    ),

    // GNU Bourne-Again SHell
    'bashshell'                     => array(
        'users'                     => array(
            $config['ROOT_USER'], 'syslog', 'www-data'
        ),
        'groups'                    => array(
            'adm', $config['ROOT_GROUP'], 'syslog', 'www-data'
        ),
        'paths'                     => array(
            'sh', 'bash', 'ls', 'cat', 'chmod', 'mkdir', 'cp', 'cpio', 'date', 'dd', 'echo', 'egrep', 'false', 'fgrep',
            'grep', 'gunzip', 'gzip', 'ln', 'mktemp', 'more', 'mv', 'pwd', 'rm', 'rmdir', 'ps', 'sed', 'sleep', 'sync',
            'tar', 'basename', 'touch', 'true', 'uncompress', 'zcat', '/etc/issue', '/etc/bash.bashrc', 'dircolors',
            'tput', 'awk', 'bzip2', 'bunzip2', 'ldd', 'less', 'clear', 'cut', 'du', 'find', 'head', 'md5sum', 'nice',
            'sort',  'tac', 'tail', 'tr', 'wc', 'watch', 'whoami', 'id', 'hostname', 'lzma', 'xz', 'pbzip2', 'env',
            'readlink', 'groups', '/usr/lib/locale/C.UTF-8', 'logger'
        ),
        'discard_paths'             => array(
            '/usr/share/doc', '/usr/share/info', '/usr/share/man', '/etc/fstab', '/etc/mtab', '/proc'
        ),
        'create_dirs'               => array(
            '/home'    => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            ),
            '/tmp'     => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 01777
            ),
            '/var/log' => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            )
        ),
        'jail_copy_file_to'         => array(
            __DIR__ . '/config/etc/profile' => array(
                'destination' => '/etc/profile',
                'preserve'    => false
            )
        ),
        'include_app_sections'      => array(
            'uidbasics', 'logbasics', 'terminfo'
        ),
        'devices'                   => array(
            '/dev/null', '/dev/ptmx', '/dev/random', '/dev/urandom', '/dev/zero'
        ),
        'fstab'                     => array(
            array(
                'fs_spec'    => 'devpts',
                'fs_file'    => '/dev/pts',
                'fs_vfstype' => 'devpts',
                'fs_mntops'  => 'gid=5,mode=620'
            ),
            array(
                'fs_spec'    => 'proc',
                'fs_file'    => '/proc',
                'fs_vfstype' => 'proc',
                'fs_mntops'  => 'defaults'
            ),
            array(
                'fs_spec'    => 'sysfs',
                'fs_file'    => '/sys',
                'fs_vfstype' => 'sysfs',
                'fs_mntops'  => 'defaults'
            ),
            array(
                'fs_spec'    => '/var/log/lastlog',
                'fs_file'    => '/var/log/lastlog',
                'fs_vfstype' => 'none',
                'fs_mntops'  => 'bind'
            )
        ),
        'create_sys_commands_args'  => array(
            'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl /var/log/lastlog',
            //'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl ' . $config['USER_WEB_DIR'] . '/*'
        ),
        'destroy_sys_commands_args' => array(
            'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl /var/log/lastlog',
            //'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl ' . $config['USER_WEB_DIR'] . '/*'
        ),
        'create_symlinks'           => array(
            '/bin/sh' => '/bin/bash',
        )
    ),

    // Provides curl, wget, lynx, ftp, ssh, sftp, scp and rsync
    'netutils'                      => array(
        'paths'                => array(
            'curl', 'ftp', 'lynx', 'wget', '/etc/lynx-cur'
        ),
        'include_app_sections' => array(
            'netbasics', 'scp', 'sftp', 'ssh', 'rsync'
        ),
        'devices'              => array(
            '/dev/random', '/dev/urandom'
        )
    ),

    // Htpasswd utility
    'apacheutils'                   => array(
        'paths' => array(
            'htpasswd'
        )
    ),

    // SSH secure copy
    'scp'                           => array(
        'paths'                => array(
            'scp'
        ),
        'include_app_sections' => array(
            'netbasics'
        ),
        'devices'              => array(
            '/dev/urandom'
        )
    ),

    // SSH secure ftp
    'sftp'                          => array(
        'paths'                => array(
            'sftp', '/usr/lib/sftp-server', '/usr/lib/openssh/sftp-server'
        ),
        'include_app_sections' => array(
            'netbasics'
        ),
        'devices'              => array(
            '/dev/urandom', '/dev/null'
        )
    ),

    // SSH secure shell
    'ssh'                           => array(
        'paths'                => array(
            'ssh'
        ),
        'include_app_sections' => array(
            'netbasics'
        ),
        'devices'              => array(
            '/dev/urandom', '/dev/tty', '/dev/null'
        )
    ),

    // Rsync
    'rsync'                         => array(
        'paths'                => array(
            'rsync'
        ),
        'include_app_sections' => array(
            'uidbasics', 'netbasics'
        )
    ),

    // MySQL command-line tools (mysql, mysqldump)
    'mysqltools'                    => array(
        'groups'            => array(
            'mysql'
        ),
        'paths'             => array(
            'mysql', 'mysqldump', '/lib/libgcc_s.so.1', '/lib/i386-linux-gnu/libgcc_s.so.1', '/lib64/libgcc_s.so.1',
            '/lib/x86_64-linux-gnu/libgcc_s.so.1'
        ),
        'create_dirs'       => array(
            '/etc/mysql' => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            ),
            #'/var/run'   => array(
            #    'user'  => $config['ROOT_USER'],
            #    'group' => $config['ROOT_GROUP'],
            #    'mode'  => 0755
            #)
        ),
        'jail_copy_file_to' => array(
            __DIR__ . '/config/etc/mysql/my.cnf' => array(
                'destination' => '/etc/mysql/my.cnf',
                'preserve'    => false
            )
        )
    ),

    // Common editors
    'editors'                       => array(
        'paths'                => array(
            'joe', 'nano', 'vi', 'vim', '/etc/vim', '/etc/vimrc', '/etc/joe', '/usr/share/vim', '/etc/nanorc',
            '/usr/share/nano'
        ),
        'include_app_sections' => array(
            'terminfo'
        ),
        'create_symlinks'      => array(
            '/usr/bin/editor' => '/bin/nano'
        ),
        //'create_jail_commands' => array(
        //    '[ -f "/usr/bin/editor" ] || ln -s /bin/nano /usr/bin/editor'
        //)
    ),

    // Midnight Commander
    'midnightcommander'             => array(
        'paths'                => array(
            'mc', 'mcedit', 'mcview', '/usr/share/mc', '/etc/mc', '/usr/lib/mc'
        ),
        'include_app_sections' => array(
            'terminfo'
        )
    ),

    // Terminfo databases
    'terminfo'                      => array(
        'paths' => array(
            '/etc/terminfo', '/lib/terminfo', '/usr/share/terminfo'
        )
    ),

    // Git (Fast Version Control System)
    'git'                           => array(
        'paths'                => array(
            'basename', 'uname', '/usr/bin/git*', '/usr/lib/git-core', '/usr/share/git-core'
        ),
        'include_app_sections' => array(
            'editors', 'netbasics', 'perl'
        )
    ),

    // Perl 5 interpreter and libraries
    'perl'                          => array(
        'paths' => array(
            'perl', '/etc/perl', '/usr/lib/perl', '/usr/lib/perl5', '/usr/share/perl', '/usr/share/perl5',
            '/usr/lib/i386-linux-gnu/perl5', '/user/lib/i386-linux-gnu/perl', '/usr/lib/x86_64-linux-gnu/perl5',
            '/usr/lib/x86_64-linux-gnu/perl'
        )
    ),

    // PHP (CLI) and extensions
    'php'                           => array(
        'paths'                => array(
            'php', '/etc/php5/cli', '/etc/php/*/cli', PHP_EXTENSION_DIR, '/usr/share/zoneinfo'
        ),
        'include_app_sections' => array(
            'netutils'
        )
    ),

    // Composer (see https://getcomposer.org)
    'composer'                      => array(
        'create_dirs'          => array(
            '/root'          => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            ),
            '/usr/local/bin' => array(
                'user'  => $config['ROOT_USER'],
                'group' => $config['ROOT_GROUP'],
                'mode'  => 0755
            )
        ),
        'include_app_sections' => array(
            'git', 'php'
        ),
        'create_jail_commands' => array(
            'curl -sS https://getcomposer.org/installer | php -d date.timezone=UTC -d allow_url_fopen=1 ' .
            '-d suhosin.executor.include.whitelist=phar -- --install-dir=/usr/local/bin',
            'mv /usr/local/bin/composer.phar /usr/local/bin/composer',
            'rm -f /etc/php5/cli/conf.d/suhosin.ini'
        )
    ),

    // Mount i-MSCP Web tree (e.g. /var/www/virtual) within jail
    /*'imscp_web_tree'                => array(
        'preserve_files' => array(
            $config['USER_WEB_DIR'],
        ),
        'fstab'          => array(
            array(
                'fs_spec'    => $config['USER_WEB_DIR'],
                'fs_file'    => $config['USER_WEB_DIR'],
                'fs_vfstype' => 'none',
                'fs_mntops'  => 'bind'
            )
        )
    )*/
);

The configuration is passed-in to my jail builders as JSON data. My jail builders are written in Perl and Python.

<!-- gh-comment-id:240228762 --> @nuxwin commented on GitHub (Aug 16, 2016): @manevich Best is to show you the full config file: ``` php $config = iMSCP_Registry::get('config'); return array( // SSH daemon service name (default: ssh) 'ssh_service_name' => 'ssh', // SSH daemon configuration file path (default: /etc/ssh/sshd_config) 'sshd_config_file_path' => '/etc/ssh/sshd_config', // Base directory for SSH daemon authorized_keys files (default: /usr/local/etc/InstantSSH) // WARNING: Don't change this parameter unless you know what you are doing. 'sshd_authorized_keys_base_dir' => '/etc/InstantSSH', // SSH user name prefix (default: imscp_) // // This is a security measurement which prevents usage of system users. // WARNING: You *must* never set this parameter to an empty value. 'ssh_user_name_prefix' => 'imscp_', // Passwordless authentication (default: false) // // When set to TRUE, passwordless authentication is enforced, meaning that the customers cannot set password for // their SSH users. This implies necessarily that the customers have to provide a SSH key. When set to FALSE, both // authentication methods (password and key) are available. In such a case, customers can provide either a password, // either a key, or both. // // Note: This applies only to newly created or updated SSH users 'passwordless_authentication' => false, // Default SSH authentication options for new SSH keys // // See man sshd(8) for a list of allowed authentication options. // e.g. command="dump /home",no-pty,no-port-forwarding // // WARNING: Any option defined here must be specified in the allowed_ssh_auth_options configuration option. 'default_ssh_auth_options' => 'no-agent-forwarding,no-port-forwarding,no-X11-forwarding,no-user-rc', // SSH authentication options that customers can setup when they are allowed to override defaults. // // Supported options are: // // \InstantSSH\Validate\SshAuthOptions::ALL (all options) // \InstantSSH\Validate\SshAuthOptions::CERT_AUTHORITY (cert-authority option) // \InstantSSH\Validate\SshAuthOptions::COMMAND (command option) // \InstantSSH\Validate\SshAuthOptions::ENVIRONMENT (environment option) // \InstantSSH\Validate\SshAuthOptions::FROM (from option) // \InstantSSH\Validate\SshAuthOptions::NO_AGENT_FORWARDING (no-agent-forwarding option) // \InstantSSH\Validate\SshAuthOptions::NO_PORT_FORWARDING (no-port-forwarding option) // \InstantSSH\Validate\SshAuthOptions::NO_PTY (no-pty option) // \InstantSSH\Validate\SshAuthOptions::NO_USER_RC (no-user-rc option) // \InstantSSH\Validate\SshAuthOptions::NO_X11_FORWARDING (no-x11-forwarding option) // \InstantSSH\Validate\SshAuthOptions::PERMITOPEN (permitopen option) // \InstantSSH\Validate\SshAuthOptions::PRINCIPALS (principals option) // \InstantSSH\Validate\SshAuthOptions::TUNNEL (tunnel option) 'allowed_ssh_auth_options' => array( \InstantSSH\Validate\SshAuthOptions::ALL ), // Root jail directory (default: /var/chroot/InstantSSH) // // Full path to the root jail directory. Be sure that the partition in which this directory is living has enough // space to host the jails. // // WARNING: Don't change this parameter unless you know what you are doing. 'root_jail_dir' => '/var/chroot/InstantSSH', // Makejail script path 'makejail_path' => __DIR__ . '/scripts/makejail', // Makejail configuration directory (default: <CONF_DIR>/InstantSSH) 'makejail_confdir_path' => $config['CONF_DIR'] . '/InstantSSH', // pam_chroot configuration file path (default: /etc/security/chroot.conf) 'pam_chroot_conffile_path' => '/etc/security/chroot.conf', // Jail builder (default: MakeJail) // // Available jail builders: // MakeJail: Create jails using `makejail'. Only the filesystem is isolated using the chroot() system call. // FireJail: Create jails using `makejail' and isolate them with `FireJail'. FireJail provides a full isolation // through the Linux kernel, via Linux namespaces, seccomp-bpf and Linux capabilities features. // // Note that support for `FireJail' has been added lately and that it is still EXPERIMENTAL. 'jail_builder' => 'FireJail', // Shared jail (default: true) // // When set to true, only one jail is created for all customers. A shared jail doesn't means that the customers will // be able to read, modify or delete files of other customers. This simply means that the jail will be shared // between the customers. The primary purpose of a jailed environment is to protect the main system. Having a jail // for each customer is interesting only when you want provide a different set of commands for each of them. // // Note: The creation of a jail per customer is currently useless because the per customer application feature is // not implemented yet. This will be implemented in near future. 'shared_jail' => true, // Preserved files (default: <USER_WEB_DIR>) // // The plugin won't try to remove files or directories inside jails if their path begins with one of the strings // in this list. // // This option can be also defined in the application sections (see below). // // WARNING: Do not remove the default entries if you don't know what you are doing. 'preserve_files' => array( '/home' ), // Whether or not files from packages that are dependencies of packages listed in the 'packages' option of the // application sections must be copied within the jails 'include_pkg_deps' => false, // Application sections (default: 'ashshell', 'netutils', 'editors', 'imscp_web_tree') // // This is the list of application sections which are used to create/update the jails (see below). 'app_sections' => array( //'ashshell', 'bashshell', #'netutils', #'editors', //'composer' //'imscp_web_tree' ), // Application sections definitions // // Below, you can find the application sections for jailed shell environments. Those application sections are used // to create and update the jails. They allow you to define which softwares, libraries, devices... must be copied // inside the jail. // // You can select as many application sections as you want by adding them into the `app_sections' configuration // option above. // // It is not recommended to change an application section without understanding its meaning and how it is working. // Once you know how the a application sections are defined, you can define your own. // // Application section options // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // The following options can be defined in application sections: // // paths: List of paths to copy inside the jails. // discard_paths: List of paths which must be discarded in any case (not copied). This option has a higher precedence // than the `paths' options. // create_dirs: List of directories to create inside jail where each key is a directory path inside the jail, and // the value, an associative array describing directory properties: // - user: Directory owner // - group: Directory group // - mode: Directory permissions // create_symlinks: List of symlinks to create inside jail where keys are link paths and values are target paths. // packages: List of Debian packages. Files from those packages will be copied inside jail. // discard_packages: List of debian packages to discard. (Only relevant if the `include_pkg_deps' configuration // option is set to true). // sys_copy_file_to: List of files to copy outside the jail, each of them specified as a key/value pair, where the // key is the source file path and the value, an associative array describing copy options: // - destination: destination path // - preserve: Boolean indicating whether or not user, group and mode must be copied // jail_copy_file_to: List of files to copy inside the jail, each of them specified as a key/value pair, where the // key is the source file path and the value, an associative array describing copy options: // - destination: destination path // - preserve: Boolean indicating whether or not user, group and mode must be copied // include_apps_sections: List of applications sections to be included (e.g. for dependencies) // users: List of users to add inside the jail (e.g: in passwd/shadow files). // groups: List of groups to add inside the jail (e.g: in group/gshadow files). // preserve_files: List of files to preserve when the jails are updated. // devices: List of devices to copy inside the jail. // fstab: List of fstab entries to add where each value is an array describing an fstab entry (see man fstab). // create_sys_commands: List of commands to execute outside the jail once built or updated. // create_sys_commands_args: List of commands to execute outside the jail once built or updated. Any listed command // will receive the full jail path as argument. // destroy_sys_commands: List of command to execute outside jail before it get destroyed. // destroy_sys_commands_args: List of command to execute outside jail before it get destroyed. Any listed command // will receive the full jail path as argument. // create_jail_commands: List of commands to execute inside jail once built or updated. // create_jail_commands_args: List of commands to execute inside jail once built or updated. Any listed command will // receive the full jail path as argument. // destroy_jail_commands: List of commands to execute inside jail before it get destroyed. // destroy_jail_commands_args: List of commands to execute inside jail before it get destroyed. Any listed command // will receive the full jail path as argument. // // Notes: // - The paths and devices options, both support the glob patterns. // - The paths option support search path // - Directories specified in paths option are copied recursively. // - Any path which doesn't exists on the system is ignored. // - Any package listed in a package option must be already installed on the system, else an error is raised. // - Any device must exists on the system, else an error is raised. You can use glob patterns to avoid error. // - File systems specified in the fstab option are mounted automatically inside jail. // - fs_spec field defined in the fstab option must exists, else an error is raised // - Mount points defined in the fstab option must be specified without the jail root path // - Command run inside jails must exist inside them // Common files for jails that need user/group information 'uidbasics' => array( 'paths' => array( '/etc/ld.so.conf', '/etc/passwd', '/etc/group', '/etc/nsswitch.conf', '/lib/libnsl.so.1', '/lib64/libnsl.so.1', '/lib/i386-linux-gnu/libnsl.so.1', '/lib/x86_64-linux-gnu/libnsl.so.1', '/lib/libnss*.so.2', '/lib64/libnss*.so.2', '/lib/i386-linux-gnu/libnss*.so.2', '/lib/x86_64-linux-gnu/libnss*.so.2', ) ), // Common files for jails that need internet connectivity 'netbasics' => array( 'paths' => array( '/etc/resolv.conf', '/etc/host.conf', '/etc/hosts', '/etc/protocols', '/etc/services', '/etc/ssl/certs', '/lib/libnss_dns.so.2', '/lib64/libnss_dns.so.2', '/lib/i386-linux-gnu/libnss_dns.so.2', '/lib/x86_64-linux-gnu/libnss_dns.so.2' ) ), // Timezone information and log sockets 'logbasics' => array( 'paths' => array( '/etc/localtime', '/etc/timezone' ), 'create_dirs' => array( '/dev' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ) ), 'preserve_files' => array( '/dev/log' ), 'create_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/syslogproxyd.pl add' ), 'destroy_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/syslogproxyd.pl remove' ) ), // Restricted ash shell (BusyBox built-in Almquist shell) 'ashshell' => array( 'users' => array( $config['ROOT_USER'], 'www-data', 'syslog' ), 'groups' => array( 'adm', $config['ROOT_GROUP'], 'syslog', 'www-data' ), 'paths' => array( 'dircolors', 'tput', '/usr/lib/locale/C.UTF-8' ), 'discard_paths' => array( '/usr/share/doc', '/usr/share/info', '/usr/share/man', '/etc/fstab', '/etc/mtab', '/proc' ), 'create_dirs' => array( '/bin' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ), '/home' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ), '/tmp' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 01777 ), '/var/log' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ) ), 'jail_copy_file_to' => array( __DIR__ . '/config/etc/profile' => array( 'destination' => '/etc/profile', 'preserve' => false ) ), 'include_app_sections' => array( 'uidbasics', 'logbasics', 'terminfo' ), 'devices' => array( '/dev/null', '/dev/ptmx', '/dev/random', '/dev/urandom', '/dev/zero' ), 'fstab' => array( array( 'fs_spec' => 'devpts', 'fs_file' => '/dev/pts', 'fs_vfstype' => 'devpts', 'fs_mntops' => 'gid=5,mode=620' ), array( 'fs_spec' => 'proc', 'fs_file' => '/proc', 'fs_vfstype' => 'proc', 'fs_mntops' => 'defaults' ), array( 'fs_spec' => 'sysfs', 'fs_file' => '/sys', 'fs_vfstype' => 'sysfs', 'fs_mntops' => 'defaults' ), array( 'fs_spec' => '/var/log/lastlog', 'fs_file' => '/var/log/lastlog', 'fs_vfstype' => 'none', 'fs_mntops' => 'bind' ) ), 'create_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl /var/log/lastlog', 'perl ' . __DIR__ . '/scripts/busybox_install.pl', //'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl ' . $config['USER_WEB_DIR'] . '/*' ), 'destroy_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl /var/log/lastlog', //'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl ' . $config['USER_WEB_DIR'] . '/*' ) ), // GNU Bourne-Again SHell 'bashshell' => array( 'users' => array( $config['ROOT_USER'], 'syslog', 'www-data' ), 'groups' => array( 'adm', $config['ROOT_GROUP'], 'syslog', 'www-data' ), 'paths' => array( 'sh', 'bash', 'ls', 'cat', 'chmod', 'mkdir', 'cp', 'cpio', 'date', 'dd', 'echo', 'egrep', 'false', 'fgrep', 'grep', 'gunzip', 'gzip', 'ln', 'mktemp', 'more', 'mv', 'pwd', 'rm', 'rmdir', 'ps', 'sed', 'sleep', 'sync', 'tar', 'basename', 'touch', 'true', 'uncompress', 'zcat', '/etc/issue', '/etc/bash.bashrc', 'dircolors', 'tput', 'awk', 'bzip2', 'bunzip2', 'ldd', 'less', 'clear', 'cut', 'du', 'find', 'head', 'md5sum', 'nice', 'sort', 'tac', 'tail', 'tr', 'wc', 'watch', 'whoami', 'id', 'hostname', 'lzma', 'xz', 'pbzip2', 'env', 'readlink', 'groups', '/usr/lib/locale/C.UTF-8', 'logger' ), 'discard_paths' => array( '/usr/share/doc', '/usr/share/info', '/usr/share/man', '/etc/fstab', '/etc/mtab', '/proc' ), 'create_dirs' => array( '/home' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ), '/tmp' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 01777 ), '/var/log' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ) ), 'jail_copy_file_to' => array( __DIR__ . '/config/etc/profile' => array( 'destination' => '/etc/profile', 'preserve' => false ) ), 'include_app_sections' => array( 'uidbasics', 'logbasics', 'terminfo' ), 'devices' => array( '/dev/null', '/dev/ptmx', '/dev/random', '/dev/urandom', '/dev/zero' ), 'fstab' => array( array( 'fs_spec' => 'devpts', 'fs_file' => '/dev/pts', 'fs_vfstype' => 'devpts', 'fs_mntops' => 'gid=5,mode=620' ), array( 'fs_spec' => 'proc', 'fs_file' => '/proc', 'fs_vfstype' => 'proc', 'fs_mntops' => 'defaults' ), array( 'fs_spec' => 'sysfs', 'fs_file' => '/sys', 'fs_vfstype' => 'sysfs', 'fs_mntops' => 'defaults' ), array( 'fs_spec' => '/var/log/lastlog', 'fs_file' => '/var/log/lastlog', 'fs_vfstype' => 'none', 'fs_mntops' => 'bind' ) ), 'create_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl /var/log/lastlog', //'perl ' . __DIR__ . '/scripts/dovecot_ignore_mount.pl ' . $config['USER_WEB_DIR'] . '/*' ), 'destroy_sys_commands_args' => array( 'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl /var/log/lastlog', //'perl ' . __DIR__ . '/scripts/dovecot_rm_mount.pl ' . $config['USER_WEB_DIR'] . '/*' ), 'create_symlinks' => array( '/bin/sh' => '/bin/bash', ) ), // Provides curl, wget, lynx, ftp, ssh, sftp, scp and rsync 'netutils' => array( 'paths' => array( 'curl', 'ftp', 'lynx', 'wget', '/etc/lynx-cur' ), 'include_app_sections' => array( 'netbasics', 'scp', 'sftp', 'ssh', 'rsync' ), 'devices' => array( '/dev/random', '/dev/urandom' ) ), // Htpasswd utility 'apacheutils' => array( 'paths' => array( 'htpasswd' ) ), // SSH secure copy 'scp' => array( 'paths' => array( 'scp' ), 'include_app_sections' => array( 'netbasics' ), 'devices' => array( '/dev/urandom' ) ), // SSH secure ftp 'sftp' => array( 'paths' => array( 'sftp', '/usr/lib/sftp-server', '/usr/lib/openssh/sftp-server' ), 'include_app_sections' => array( 'netbasics' ), 'devices' => array( '/dev/urandom', '/dev/null' ) ), // SSH secure shell 'ssh' => array( 'paths' => array( 'ssh' ), 'include_app_sections' => array( 'netbasics' ), 'devices' => array( '/dev/urandom', '/dev/tty', '/dev/null' ) ), // Rsync 'rsync' => array( 'paths' => array( 'rsync' ), 'include_app_sections' => array( 'uidbasics', 'netbasics' ) ), // MySQL command-line tools (mysql, mysqldump) 'mysqltools' => array( 'groups' => array( 'mysql' ), 'paths' => array( 'mysql', 'mysqldump', '/lib/libgcc_s.so.1', '/lib/i386-linux-gnu/libgcc_s.so.1', '/lib64/libgcc_s.so.1', '/lib/x86_64-linux-gnu/libgcc_s.so.1' ), 'create_dirs' => array( '/etc/mysql' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ), #'/var/run' => array( # 'user' => $config['ROOT_USER'], # 'group' => $config['ROOT_GROUP'], # 'mode' => 0755 #) ), 'jail_copy_file_to' => array( __DIR__ . '/config/etc/mysql/my.cnf' => array( 'destination' => '/etc/mysql/my.cnf', 'preserve' => false ) ) ), // Common editors 'editors' => array( 'paths' => array( 'joe', 'nano', 'vi', 'vim', '/etc/vim', '/etc/vimrc', '/etc/joe', '/usr/share/vim', '/etc/nanorc', '/usr/share/nano' ), 'include_app_sections' => array( 'terminfo' ), 'create_symlinks' => array( '/usr/bin/editor' => '/bin/nano' ), //'create_jail_commands' => array( // '[ -f "/usr/bin/editor" ] || ln -s /bin/nano /usr/bin/editor' //) ), // Midnight Commander 'midnightcommander' => array( 'paths' => array( 'mc', 'mcedit', 'mcview', '/usr/share/mc', '/etc/mc', '/usr/lib/mc' ), 'include_app_sections' => array( 'terminfo' ) ), // Terminfo databases 'terminfo' => array( 'paths' => array( '/etc/terminfo', '/lib/terminfo', '/usr/share/terminfo' ) ), // Git (Fast Version Control System) 'git' => array( 'paths' => array( 'basename', 'uname', '/usr/bin/git*', '/usr/lib/git-core', '/usr/share/git-core' ), 'include_app_sections' => array( 'editors', 'netbasics', 'perl' ) ), // Perl 5 interpreter and libraries 'perl' => array( 'paths' => array( 'perl', '/etc/perl', '/usr/lib/perl', '/usr/lib/perl5', '/usr/share/perl', '/usr/share/perl5', '/usr/lib/i386-linux-gnu/perl5', '/user/lib/i386-linux-gnu/perl', '/usr/lib/x86_64-linux-gnu/perl5', '/usr/lib/x86_64-linux-gnu/perl' ) ), // PHP (CLI) and extensions 'php' => array( 'paths' => array( 'php', '/etc/php5/cli', '/etc/php/*/cli', PHP_EXTENSION_DIR, '/usr/share/zoneinfo' ), 'include_app_sections' => array( 'netutils' ) ), // Composer (see https://getcomposer.org) 'composer' => array( 'create_dirs' => array( '/root' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ), '/usr/local/bin' => array( 'user' => $config['ROOT_USER'], 'group' => $config['ROOT_GROUP'], 'mode' => 0755 ) ), 'include_app_sections' => array( 'git', 'php' ), 'create_jail_commands' => array( 'curl -sS https://getcomposer.org/installer | php -d date.timezone=UTC -d allow_url_fopen=1 ' . '-d suhosin.executor.include.whitelist=phar -- --install-dir=/usr/local/bin', 'mv /usr/local/bin/composer.phar /usr/local/bin/composer', 'rm -f /etc/php5/cli/conf.d/suhosin.ini' ) ), // Mount i-MSCP Web tree (e.g. /var/www/virtual) within jail /*'imscp_web_tree' => array( 'preserve_files' => array( $config['USER_WEB_DIR'], ), 'fstab' => array( array( 'fs_spec' => $config['USER_WEB_DIR'], 'fs_file' => $config['USER_WEB_DIR'], 'fs_vfstype' => 'none', 'fs_mntops' => 'bind' ) ) )*/ ); ``` The configuration is passed-in to my jail builders as JSON data. My jail builders are written in Perl and Python.
Author
Owner

@nuxwin commented on GitHub (Aug 16, 2016):

@manevich

To answer you clearly:

Just looked on freshly built debootstrap chroot: obviously /sys and /proc are empty. Why mount them by hand or script and not using firejail?

FireJail should mount them only if not already done.

Remounting /proc AFAIK required to get /proc limited by process namespace. Otherwise /proc containing all system processes will be exposed. Some remounting in /proc added to protect sensitive parts.

I agreed on this point; bu nthing prevent firejail to act on /proc from the chroot instead of /proc from the system (if /proc is mounted in chroot).

/run/firejail/ is remounted for internal purposes, so all depending features will be lost.

You can still do that. This should not pose any problem.

Firejail has own options for /dev restriction.

I know about --private-dev, but with or without this option, firejail remount the full /dev from the system in the chroot while the administrator could have mounted a /dev (restricted) in the chroot already. Firejail should operate on /dev from the chroot if present instead of operate on /dev from the system.

/sys is also remounted to protect sensitive parts.

Again, nothing prevent firejail to operate on /sys from the chroot if already mounted.

PS: Thanks for rising chroot mater, it got not too much attention before.

You're welcome. I want help make firejail the best jail tool ever seen ;)

<!-- gh-comment-id:240234992 --> @nuxwin commented on GitHub (Aug 16, 2016): @manevich To answer you clearly: > Just looked on freshly built debootstrap chroot: obviously /sys and /proc are empty. Why mount them by hand or script and not using firejail? FireJail should mount them only if not already done. > Remounting /proc AFAIK required to get /proc limited by process namespace. Otherwise /proc containing all system processes will be exposed. Some remounting in /proc added to protect sensitive parts. I agreed on this point; bu nthing prevent firejail to act on `/proc` from the chroot instead of `/proc` from the system (if /proc is mounted in chroot). > /run/firejail/ is remounted for internal purposes, so all depending features will be lost. You can still do that. This should not pose any problem. > Firejail has own options for /dev restriction. I know about `--private-dev`, but with or without this option, firejail remount the full `/dev` from the system in the chroot while the administrator could have mounted a `/dev` (restricted) in the chroot already. Firejail should operate on `/dev` from the chroot if present instead of operate on `/dev` from the system. > /sys is also remounted to protect sensitive parts. Again, nothing prevent firejail to operate on `/sys` from the chroot if already mounted. > PS: Thanks for rising chroot mater, it got not too much attention before. You're welcome. I want help make firejail the best jail tool ever seen ;)
Author
Owner

@manevich commented on GitHub (Aug 16, 2016):

OK, now I understand your point: if user already set up the chroot - base on this and don't redo all from scratch.
I agree that firejaill need option(s) for that, while don't think this is best default behavior.
You look on firejail as part of other system. Very powerful already, as seems.
But, I believe this is not only use for firejail. Regular users will run debootstrap ... or somethig similar, firejail --chroot=chrootdir and expect firejail to restrict /dev, /sys, etc.

<!-- gh-comment-id:240269362 --> @manevich commented on GitHub (Aug 16, 2016): OK, now I understand your point: if user already set up the chroot - base on this and don't redo all from scratch. I agree that firejaill need option(s) for that, while don't think this is best default behavior. You look on firejail as part of other system. Very powerful already, as seems. But, I believe this is not only use for firejail. Regular users will run `debootstrap ...` or somethig similar, `firejail --chroot=chrootdir` and expect firejail to restrict `/dev`, `/sys`, etc.
Author
Owner

@nuxwin commented on GitHub (Aug 16, 2016):

@manevich

I would be fine with a option allowing to disable/enable expected behavior. I'll surely add that layer and provide a patch.

BTW:

I've coded my plugin by taking ideas from both: makejail and jailkit projects ;) It is really a powerfull tool but FireJail add isolation layer which is missing in my plugin. I could it my self but why doing this if I can reuse an existing project and help to improve it. I plan to add also support for systemd-nspawn ;)

Right now, my FireJail jail builder implementation extend the MakeJail jail builder which is responsible to create the chroot. I expect from FireJail to enforce security with linux namespaces and so on.

<!-- gh-comment-id:240271423 --> @nuxwin commented on GitHub (Aug 16, 2016): @manevich I would be fine with a option allowing to disable/enable expected behavior. I'll surely add that layer and provide a patch. BTW: I've coded my plugin by taking ideas from both: makejail and jailkit projects ;) It is really a powerfull tool but FireJail add isolation layer which is missing in my plugin. I could it my self but why doing this if I can reuse an existing project and help to improve it. I plan to add also support for systemd-nspawn ;) Right now, my FireJail jail builder implementation extend the MakeJail jail builder which is responsible to create the chroot. I expect from FireJail to enforce security with linux namespaces and so on.
Author
Owner

@nuxwin commented on GitHub (Aug 17, 2016):

@manevich

Furthermore:

nuxwin@dev:~$ ssh nuxwin@192.168.1.133
nuxwin@192.168.1.133's password: 

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Error: cannot find /dev in chroot directory
Error: invalid chroot
Connection to 192.168.1.133 closed.

After fixing by creating /dev directory:

nuxwin@dev:~$ ssh nuxwin@192.168.1.133
nuxwin@192.168.1.133's password:

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Aug 17 02:17:24 2016 from 192.168.1.100
Error: cannot find /proc in chroot directory
Error: invalid chroot
Connection to 192.168.1.133 closed.

Firejail complains when /dev or /proc directories don't exist in chroot. This is another inconsistency in my eyes (in regard of the current implementation). FireJail should be able to create those mount point if missing.

I also get:

Warning: failed to unmount /sys

when /sys is not already mounted in chroot.

<!-- gh-comment-id:240279223 --> @nuxwin commented on GitHub (Aug 17, 2016): @manevich Furthermore: ``` nuxwin@dev:~$ ssh nuxwin@192.168.1.133 nuxwin@192.168.1.133's password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Error: cannot find /dev in chroot directory Error: invalid chroot Connection to 192.168.1.133 closed. ``` After fixing by creating /dev directory: ``` nuxwin@dev:~$ ssh nuxwin@192.168.1.133 nuxwin@192.168.1.133's password: The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Wed Aug 17 02:17:24 2016 from 192.168.1.100 Error: cannot find /proc in chroot directory Error: invalid chroot Connection to 192.168.1.133 closed. ``` Firejail complains when /dev or /proc directories don't exist in chroot. This is another inconsistency in my eyes (in regard of the current implementation). FireJail should be able to create those mount point if missing. I also get: ``` Warning: failed to unmount /sys ``` when /sys is not already mounted in chroot.
Author
Owner

@nuxwin commented on GitHub (Aug 17, 2016):

@manevich

Here is my current FireJail jail builder implementation (which extends the MakeJail jail builder). Look at the _init() method, you will understand how I process. The comments are interesting for FireJail.

=head1 NAME

 InstantSSH::JailBuilder::FireJail

=cut

# i-MSCP InstantSSH plugin
#
# @author Laurent Declercq <l.declercq@nuxwin.com>
# @copyright (C) 2014-2016 Laurent Declercq <l.declercq@nuxwin.com>
# @license i-MSCP License <http://www.i-mscp.net/license-agreement.html>

package InstantSSH::JailBuilder::FireJail;

use strict;
use warnings;
use iMSCP::Debug;
use iMSCP::Dir;
use InstantSSH::FileUtils 'normalizePath';
use parent 'InstantSSH::JailBuilder::MakeJail';

my $LOGIN_USERS_FILE = '/usr/local/etc/firejail/login.users';

=head1 DESCRIPTION

  This library allow building of restricted environments using FireJail SUID program.

  See https://firejail.wordpress.com/

=head1 PUBLIC METHODS

=over 4

=item jailUser($user [, \%options ])

 See InstantSSH::JailBuilder::Abstract

=cut

sub jailUser
{
    my ($self, $user, $options) = @_;

    $options = { } unless defined $options && ref $options eq 'HASH';

    my @pwEntry = getpwnam( $user );
    unless (@pwEntry) {
        error( sprintf( "Could not find `%s' unix user", $user ) );
        return 1;
    }

    $options->{'shell'} //= $pwEntry[8];

    my $group = getgrgid( $pwEntry[3] );
    unless (defined $group) {
        error( sprintf( "Could not find `%s' unix user group", $user ) );
        return 1;
    }

    unless ($options->{'skip_home'}) {
        my $homeDir = normalizePath( $pwEntry[7] );
        unless (defined $homeDir) {
            error( sprintf( "Could not find `%s' unix user homedir", $user ) );
            return 1;
        }

        # Create user home dir within jail
        my $rs = iMSCP::Dir->new( dirname => $self->{'jail_dir'}.$homeDir )->make(
            { user => $user, group => $group, mode => 0755 }
        );
        return $rs if $rs;
    }

    my $rs = $self->addPasswdFile( '/etc/passwd', $user, $options->{'shell'} );
    $rs ||= $self->addPasswdFile( '/etc/group', $group ) unless $options->{'skip_group'};
    return $rs if $rs;

    # Add user into firejail login.users file
    my $file = iMSCP::File->new( filename => $LOGIN_USERS_FILE );
    my $fileContent = $file->get();
    unless (defined $fileContent) {
        error( sprintf( "Could not read %s file", $LOGIN_USERS_FILE ) );
        return 1;
    }
    debug( sprintf( "Adding `%s' user entry in %s", $user, $LOGIN_USERS_FILE ) );
    $fileContent =~ s/^\Q$user\E:[^\n]+\n//gm;
    $fileContent .= <<"EOF";
$user:--chroot=$self->{'jail_dir'} --name=$user --dns=8.8.8.8 --dns=8.8.4.4 --shell=$options->{'shell'}
EOF
    $rs = $file->set( $fileContent );
    $rs ||= $file->save();
}

=item unjailUser($user [, \%options ])

 See InstantSSH::JailBuilder::Abstract

=cut

sub unjailUser
{
    my ($self, $user, $options) = @_;

    $options = { } unless defined $options && ref $options eq 'HASH';

    my @pwEntry = getpwnam( $user );
    unless (@pwEntry) {
        error( sprintf( "Could not find `%s' unix user", $user ) );
        return 1;
    }

    my $homeDir = normalizePath( $pwEntry[7] );
    unless (defined $homeDir) {
        error( sprintf( "Could not find `%s' unix user homedir", $user ) );
        return 1;
    }

    if (-d $self->{'jail_dir'}) {
        unless ($options->{'skip_home'}) {
            my $rs = iMSCP::Dir->new( dirname => $self->{'jail_dir'}.$homeDir )->remove();
            $rs ||= $self->removePasswdFile( '/etc/passwd', $user );
            return $rs if $rs;
        }

        unless ($options->{'skip_group'}) {
            my $group = getgrgid( $pwEntry[3] );
            unless (defined $group) {
                error( sprintf( "Could not to find `%s' unix group", $user ) );
                return 1;
            }

            my $rs = $self->removePasswdFile( '/etc/group', $group );
            return $rs if $rs;
        }
    }

    # Removing user from firejail login.users file
    if (-f $LOGIN_USERS_FILE) {
        my $file = iMSCP::File->new( filename => $LOGIN_USERS_FILE );
        my $fileContent = $file->get();
        unless (defined $fileContent) {
            error( sprintf( "Could not read `%s' file", $LOGIN_USERS_FILE ) );
            return 1;
        }
        debug( sprintf( "Removing `%s' entry from %s", $user, $LOGIN_USERS_FILE ) );
        $fileContent =~ s/^\Q$user\E:+[^\n]+\n//gm;
        my $rs = $file->set( $fileContent );
        $rs ||= $file->save();
        return $rs if $rs;
    }

    0;
}

=back

=head1 PRIVATE METHODS

=over 4

=item _init()

 Initialize instance

 Return InstantSSH:JailBuilder, die on failure

=cut

sub _init
{
    my $self = shift;

    # logbasics application section is useless in case of FireJail.
    # FireJail will remount system log socket in tmpfs.
    $self->{'config'}->{'logbasics'} = { };

    # FireJail is managing fs itself ATM. See https://github.com/netblue30/firejail/issues/721
    # Thus, we need to delete fstab and devices options in application sections 
    for my $candidate(keys $self->{'config'}) {
        next unless ref $self->{'config'}->{$candidate} eq 'HASH';
        delete $self->{'config'}->{$candidate}->{'devices'};
        delete $self->{'config'}->{$candidate}->{'fstab'};
    }

    # Meet the FirejJail requirements by defining dedicated application sections for it
    $self->{'config'}->{'firejail'} = {
        paths                    => [
            # We need this. Copied from the logbasics application sections which is discarded in case of Firejail.
            '/etc/localtime', '/etc/timezone'
        ],
        discard_paths            => [
            # FireJail doesn't support symlinked resolv.conf file. It will create its own.
            # TODO: TO BE REPORTED TO FireJail Upstream author; FireJail should not fail (as stated in their code but it
            # will ATM....
            '/etc/resolv.conf',
        ],
        create_dirs              => {
            # FireJail complains if the mount point is not present
            '/dev'      => {
                user  => $main::imscpConfig{'ROOT_USER'},
                group => $main::imscpConfig{'ROOT_GROUP'},
                mode  => 0755
            },
            # FireJail complains if the mount point is not present
            '/proc'     => {
                user  => $main::imscpConfig{'ROOT_USER'},
                group => $main::imscpConfig{'ROOT_GROUP'},
                mode  => 0755
            },
            '/var'      => {
                user  => $main::imscpConfig{'ROOT_USER'},
                group => $main::imscpConfig{'ROOT_GROUP'},
                mode  => 0755
            },
            '/var/tmp'  => {
                user  => $main::imscpConfig{'ROOT_USER'},
                group => $main::imscpConfig{'ROOT_GROUP'},
                mode  => 01777
            },
            '/run'      => {
                user  => $main::imscpConfig{'ROOT_USER'},
                group => $main::imscpConfig{'ROOT_GROUP'},
                mode  => 0755
            },
            '/run/lock' => {
                user  => $main::imscpConfig{'ROOT_USER'},
                group => $main::imscpConfig{'ROOT_GROUP'},
                mode  => 01777
            }
        },
        fstab                    => [
            {
                fs_spec    => '/run/utmp',
                fs_file    => '/run/utmp',
                fs_vfstype => 'none',
                fs_mntops  => 'bind'
            },
            # Totally useless since FireJail will umount it and remount restricted system sysfs.. However, FireJail will
            # not remount system sysfs if it cannot first, umount it in the chroot. WTF...
            # See https://github.com/netblue30/firejail/issues/721
            {
                fs_spec    => 'sysfs',
                fs_file    => '/sys',
                fs_vfstype => 'sysfs',
                fs_mntops  => 'defaults'
            }
        ],
        create_sys_commands_args => [
            # Ensure that there is no proxied log socket (FireJail remount log socket inside jail)
            # Cover case where user switched from other jail builder to FireJail jailbuilder
            'perl '.$main::imscpConfig{'PLUGINS_DIR'}.'/InstantSSH/scripts/syslogproxyd.pl remove'
        ],
        create_symlinks          => {
            '/var/run'  => '/run',
            '/var/lock' => '/run/lock'
        }
    };
    # If /dev/log is a symlink and /run/systemd/journal/dev-log socket exists,
    # we need also mount /run/systemd/journal/dev-log inside the chroot
    if (-l '/dev/log' && -S '/run/systemd/journal/dev-log') {
        $self->{'config'}->{'firejail_systemd_dev_log'} = {
            create_dirs => {
                '/run/systemd/journal' => {
                    user  => $main::imscpConfig{'ROOT_USER'},
                    group => $main::imscpConfig{'ROOT_GROUP'},
                    mode  => 0755
                },
            },
            fstab       => [
                {
                    fs_spec    => '/run/systemd/journal/dev-log',
                    fs_file    => '/run/systemd/journal/dev-log',
                    fs_vfstype => 'none',
                    fs_mntops  => 'bind,ro'
                },
            ],
        };
    }

    # Add FireJail application sections to list of selected application sections
    push @{$self->{'config'}->{'app_sections'}},
        'firejail',
        (defined $self->{'config'}->{'firejail_systemd_dev_log'} ? 'firejail_systemd_dev_log' : ());

    $self->SUPER::_init();
}

=back

=head1 AUTHOR

 Laurent Declercq <l.declercq@nuxwin.com>

=cut

1;
__END__
<!-- gh-comment-id:240281917 --> @nuxwin commented on GitHub (Aug 17, 2016): @manevich Here is my current FireJail jail builder implementation (which extends the MakeJail jail builder). Look at the `_init()` method, you will understand how I process. The comments are interesting for FireJail. ``` perl =head1 NAME InstantSSH::JailBuilder::FireJail =cut # i-MSCP InstantSSH plugin # # @author Laurent Declercq <l.declercq@nuxwin.com> # @copyright (C) 2014-2016 Laurent Declercq <l.declercq@nuxwin.com> # @license i-MSCP License <http://www.i-mscp.net/license-agreement.html> package InstantSSH::JailBuilder::FireJail; use strict; use warnings; use iMSCP::Debug; use iMSCP::Dir; use InstantSSH::FileUtils 'normalizePath'; use parent 'InstantSSH::JailBuilder::MakeJail'; my $LOGIN_USERS_FILE = '/usr/local/etc/firejail/login.users'; =head1 DESCRIPTION This library allow building of restricted environments using FireJail SUID program. See https://firejail.wordpress.com/ =head1 PUBLIC METHODS =over 4 =item jailUser($user [, \%options ]) See InstantSSH::JailBuilder::Abstract =cut sub jailUser { my ($self, $user, $options) = @_; $options = { } unless defined $options && ref $options eq 'HASH'; my @pwEntry = getpwnam( $user ); unless (@pwEntry) { error( sprintf( "Could not find `%s' unix user", $user ) ); return 1; } $options->{'shell'} //= $pwEntry[8]; my $group = getgrgid( $pwEntry[3] ); unless (defined $group) { error( sprintf( "Could not find `%s' unix user group", $user ) ); return 1; } unless ($options->{'skip_home'}) { my $homeDir = normalizePath( $pwEntry[7] ); unless (defined $homeDir) { error( sprintf( "Could not find `%s' unix user homedir", $user ) ); return 1; } # Create user home dir within jail my $rs = iMSCP::Dir->new( dirname => $self->{'jail_dir'}.$homeDir )->make( { user => $user, group => $group, mode => 0755 } ); return $rs if $rs; } my $rs = $self->addPasswdFile( '/etc/passwd', $user, $options->{'shell'} ); $rs ||= $self->addPasswdFile( '/etc/group', $group ) unless $options->{'skip_group'}; return $rs if $rs; # Add user into firejail login.users file my $file = iMSCP::File->new( filename => $LOGIN_USERS_FILE ); my $fileContent = $file->get(); unless (defined $fileContent) { error( sprintf( "Could not read %s file", $LOGIN_USERS_FILE ) ); return 1; } debug( sprintf( "Adding `%s' user entry in %s", $user, $LOGIN_USERS_FILE ) ); $fileContent =~ s/^\Q$user\E:[^\n]+\n//gm; $fileContent .= <<"EOF"; $user:--chroot=$self->{'jail_dir'} --name=$user --dns=8.8.8.8 --dns=8.8.4.4 --shell=$options->{'shell'} EOF $rs = $file->set( $fileContent ); $rs ||= $file->save(); } =item unjailUser($user [, \%options ]) See InstantSSH::JailBuilder::Abstract =cut sub unjailUser { my ($self, $user, $options) = @_; $options = { } unless defined $options && ref $options eq 'HASH'; my @pwEntry = getpwnam( $user ); unless (@pwEntry) { error( sprintf( "Could not find `%s' unix user", $user ) ); return 1; } my $homeDir = normalizePath( $pwEntry[7] ); unless (defined $homeDir) { error( sprintf( "Could not find `%s' unix user homedir", $user ) ); return 1; } if (-d $self->{'jail_dir'}) { unless ($options->{'skip_home'}) { my $rs = iMSCP::Dir->new( dirname => $self->{'jail_dir'}.$homeDir )->remove(); $rs ||= $self->removePasswdFile( '/etc/passwd', $user ); return $rs if $rs; } unless ($options->{'skip_group'}) { my $group = getgrgid( $pwEntry[3] ); unless (defined $group) { error( sprintf( "Could not to find `%s' unix group", $user ) ); return 1; } my $rs = $self->removePasswdFile( '/etc/group', $group ); return $rs if $rs; } } # Removing user from firejail login.users file if (-f $LOGIN_USERS_FILE) { my $file = iMSCP::File->new( filename => $LOGIN_USERS_FILE ); my $fileContent = $file->get(); unless (defined $fileContent) { error( sprintf( "Could not read `%s' file", $LOGIN_USERS_FILE ) ); return 1; } debug( sprintf( "Removing `%s' entry from %s", $user, $LOGIN_USERS_FILE ) ); $fileContent =~ s/^\Q$user\E:+[^\n]+\n//gm; my $rs = $file->set( $fileContent ); $rs ||= $file->save(); return $rs if $rs; } 0; } =back =head1 PRIVATE METHODS =over 4 =item _init() Initialize instance Return InstantSSH:JailBuilder, die on failure =cut sub _init { my $self = shift; # logbasics application section is useless in case of FireJail. # FireJail will remount system log socket in tmpfs. $self->{'config'}->{'logbasics'} = { }; # FireJail is managing fs itself ATM. See https://github.com/netblue30/firejail/issues/721 # Thus, we need to delete fstab and devices options in application sections for my $candidate(keys $self->{'config'}) { next unless ref $self->{'config'}->{$candidate} eq 'HASH'; delete $self->{'config'}->{$candidate}->{'devices'}; delete $self->{'config'}->{$candidate}->{'fstab'}; } # Meet the FirejJail requirements by defining dedicated application sections for it $self->{'config'}->{'firejail'} = { paths => [ # We need this. Copied from the logbasics application sections which is discarded in case of Firejail. '/etc/localtime', '/etc/timezone' ], discard_paths => [ # FireJail doesn't support symlinked resolv.conf file. It will create its own. # TODO: TO BE REPORTED TO FireJail Upstream author; FireJail should not fail (as stated in their code but it # will ATM.... '/etc/resolv.conf', ], create_dirs => { # FireJail complains if the mount point is not present '/dev' => { user => $main::imscpConfig{'ROOT_USER'}, group => $main::imscpConfig{'ROOT_GROUP'}, mode => 0755 }, # FireJail complains if the mount point is not present '/proc' => { user => $main::imscpConfig{'ROOT_USER'}, group => $main::imscpConfig{'ROOT_GROUP'}, mode => 0755 }, '/var' => { user => $main::imscpConfig{'ROOT_USER'}, group => $main::imscpConfig{'ROOT_GROUP'}, mode => 0755 }, '/var/tmp' => { user => $main::imscpConfig{'ROOT_USER'}, group => $main::imscpConfig{'ROOT_GROUP'}, mode => 01777 }, '/run' => { user => $main::imscpConfig{'ROOT_USER'}, group => $main::imscpConfig{'ROOT_GROUP'}, mode => 0755 }, '/run/lock' => { user => $main::imscpConfig{'ROOT_USER'}, group => $main::imscpConfig{'ROOT_GROUP'}, mode => 01777 } }, fstab => [ { fs_spec => '/run/utmp', fs_file => '/run/utmp', fs_vfstype => 'none', fs_mntops => 'bind' }, # Totally useless since FireJail will umount it and remount restricted system sysfs.. However, FireJail will # not remount system sysfs if it cannot first, umount it in the chroot. WTF... # See https://github.com/netblue30/firejail/issues/721 { fs_spec => 'sysfs', fs_file => '/sys', fs_vfstype => 'sysfs', fs_mntops => 'defaults' } ], create_sys_commands_args => [ # Ensure that there is no proxied log socket (FireJail remount log socket inside jail) # Cover case where user switched from other jail builder to FireJail jailbuilder 'perl '.$main::imscpConfig{'PLUGINS_DIR'}.'/InstantSSH/scripts/syslogproxyd.pl remove' ], create_symlinks => { '/var/run' => '/run', '/var/lock' => '/run/lock' } }; # If /dev/log is a symlink and /run/systemd/journal/dev-log socket exists, # we need also mount /run/systemd/journal/dev-log inside the chroot if (-l '/dev/log' && -S '/run/systemd/journal/dev-log') { $self->{'config'}->{'firejail_systemd_dev_log'} = { create_dirs => { '/run/systemd/journal' => { user => $main::imscpConfig{'ROOT_USER'}, group => $main::imscpConfig{'ROOT_GROUP'}, mode => 0755 }, }, fstab => [ { fs_spec => '/run/systemd/journal/dev-log', fs_file => '/run/systemd/journal/dev-log', fs_vfstype => 'none', fs_mntops => 'bind,ro' }, ], }; } # Add FireJail application sections to list of selected application sections push @{$self->{'config'}->{'app_sections'}}, 'firejail', (defined $self->{'config'}->{'firejail_systemd_dev_log'} ? 'firejail_systemd_dev_log' : ()); $self->SUPER::_init(); } =back =head1 AUTHOR Laurent Declercq <l.declercq@nuxwin.com> =cut 1; __END__ ```
Author
Owner

@netblue30 commented on GitHub (Aug 20, 2016):

When running firejail with the --chroot option, many parts of the system fs is remounted inside the chroot

It mounts /dev in order to allow nvidia and amd video drivers, it copies /etc/resolv.conf to get networking up and running, cleans up several directories in /var (this is mainly to be able to run multiple web servers from the same chroot, generates new /etc/passwd and /etc/chroot and a new /home directory only with the current user, remounts /sys and /proc. The idea is to allow the user to run desktop applications inside chroot, as if it was on a real system.

If you need it, I can add a config flag in /etc/firejail/firejail.config that disables most of the default changes - probably you still need /etc/resolv.conf, /proc and /sys.

<!-- gh-comment-id:241198616 --> @netblue30 commented on GitHub (Aug 20, 2016): > When running firejail with the --chroot option, many parts of the system fs is remounted inside the chroot It mounts /dev in order to allow nvidia and amd video drivers, it copies /etc/resolv.conf to get networking up and running, cleans up several directories in /var (this is mainly to be able to run multiple web servers from the same chroot, generates new /etc/passwd and /etc/chroot and a new /home directory only with the current user, remounts /sys and /proc. The idea is to allow the user to run desktop applications inside chroot, as if it was on a real system. If you need it, I can add a config flag in /etc/firejail/firejail.config that disables most of the default changes - probably you still need /etc/resolv.conf, /proc and /sys.
Author
Owner

@nuxwin commented on GitHub (Aug 20, 2016):

@netblue30

If you look at my config file above (see https://github.com/netblue30/firejail/issues/721#issuecomment-240228762 ), you'll see that my chroot will have /proc and /sys already mounted.

The point here is: in case of chroot, we need have a flags telling firejail to operate on the chrooted fs (remount things from the chroot instead of the system fs).

<!-- gh-comment-id:241198924 --> @nuxwin commented on GitHub (Aug 20, 2016): @netblue30 If you look at my config file above (see https://github.com/netblue30/firejail/issues/721#issuecomment-240228762 ), you'll see that my chroot will have /proc and /sys already mounted. The point here is: in case of chroot, we need have a flags telling firejail to operate on the chrooted fs (remount things from the chroot instead of the system fs).
Author
Owner

@netblue30 commented on GitHub (Aug 21, 2016):

Grab the latest from git, and after install edit /etc/firejail/firejail.config. I added a flag to disable remounting of /proc and /sys ("remount-proc-sys no"). I'll add tomorrow something similar for the rest of chroot, so you'll have your own /dev and so on.

<!-- gh-comment-id:241232841 --> @netblue30 commented on GitHub (Aug 21, 2016): Grab the latest from git, and after install edit /etc/firejail/firejail.config. I added a flag to disable remounting of /proc and /sys ("remount-proc-sys no"). I'll add tomorrow something similar for the rest of chroot, so you'll have your own /dev and so on.
Author
Owner

@netblue30 commented on GitHub (Aug 23, 2016):

All fixed. In /etc/firejail/firejail.config add:

chroot-desktop no
remount-proc-sys no

Let me know if you need more fixes.

<!-- gh-comment-id:241729441 --> @netblue30 commented on GitHub (Aug 23, 2016): All fixed. In /etc/firejail/firejail.config add: ``` chroot-desktop no remount-proc-sys no ``` Let me know if you need more fixes.
Author
Owner

@nuxwin commented on GitHub (Aug 24, 2016):

@netblue30

Thank for your work ;) I'll have a look soon and post my feedbacks.

<!-- gh-comment-id:241980377 --> @nuxwin commented on GitHub (Aug 24, 2016): @netblue30 Thank for your work ;) I'll have a look soon and post my feedbacks.
Author
Owner

@nuxwin commented on GitHub (Sep 5, 2016):

@netblue30

Just to let you know that this is working as expected. The chroot-desktop option is much appreciated.

However, the remount-proc-sys option is pretty useless because if we use it (set it to no), the pid namespace is not updated. This is explained by the fact that normally once you call CLONE(2), you must remount system /proc. Therefore, We don't use that option ATM. Our firejail.config file look as follow:

# Firejail system-wide configuration file - auto-generated by i-MSCP InstantSSH plugin
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN

chroot yes
chroot-desktop no
quiet-by-default yes
remount-proc-sys yes
x11 no

Result:

nuxwin@dev:~$ ssh imscp_nuxwin@192.168.1.136

  ___           _              _     ____ ____  _   _
 |_ _|_ __  ___| |_ __ _ _ __ | |_  / ___/ ___|| | | |
  | || '_ \/ __| __/ _` | '_ \| __| \___ \___ \| |_| |
  | || | | \__ \ || (_| | | | | |_   ___) |__) |  _  |
 |___|_| |_|___/\__\__,_|_| |_|\__| |____/____/|_| |_|


Welcome to your shell.

If you need a specific command, get in contact with your reseller.

i-MSCP InstantSSH plugin v5.0.0
Copyright (c) 2014-2016 Laurent Declercq <l.declercq@nuxwin.com>

Last login: Mon Sep  5 21:18:07 2016 from 192.168.1.100
imscp_nuxwin@stretch:~$ env
XDG_SESSION_ID=518
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=192.168.1.100 45963 22
SSH_TTY=/dev/pts/3
LC_ALL=C.UTF-8
USER=imscp_nuxwin
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
QT_X11_NO_MITSHM=1
MAIL=/var/mail/imscp_nuxwin
PATH=/usr/local/bin:/usr/bin:/bin
PWD=/home/imscp_nuxwin/./
LANG=C.UTF-8
SHLVL=1
HOME=/home/imscp_nuxwin/./
LOGNAME=imscp_nuxwin
SSH_CONNECTION=192.168.1.100 45963 192.168.1.136 22
XDG_RUNTIME_DIR=/run/user/1002
container=firejail
_=/bin/env
imscp_nuxwin@stretch:~$ ls /proc
1              buddyinfo      consoles       diskstats      fb             iomem          kcore          kpagecgroup    locks          mounts         partitions     softirqs       sysrq-trigger  timer_stats    vmallocinfo
2              bus            cpuinfo        dma            filesystems    ioports        key-users      kpagecount     meminfo        mtrr           sched_debug    stat           sysvipc        tty            vmstat
9              cgroups        crypto         driver         fs             irq            keys           kpageflags     misc           net            self           swaps          thread-self    uptime         zoneinfo
acpi           cmdline        devices        execdomains    interrupts     kallsyms       kmsg           loadavg        modules        pagetypeinfo   slabinfo       sys            timer_list     version
imscp_nuxwin@stretch:~$
<!-- gh-comment-id:244802444 --> @nuxwin commented on GitHub (Sep 5, 2016): @netblue30 Just to let you know that this is working as expected. The `chroot-desktop` option is much appreciated. However, the `remount-proc-sys` option is pretty useless because if we use it (set it to `no`), the pid namespace is not updated. This is explained by the fact that normally once you call `CLONE(2)`, you must remount system /proc. Therefore, We don't use that option ATM. Our firejail.config file look as follow: ``` # Firejail system-wide configuration file - auto-generated by i-MSCP InstantSSH plugin # DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN chroot yes chroot-desktop no quiet-by-default yes remount-proc-sys yes x11 no ``` Result: ``` nuxwin@dev:~$ ssh imscp_nuxwin@192.168.1.136 ___ _ _ ____ ____ _ _ |_ _|_ __ ___| |_ __ _ _ __ | |_ / ___/ ___|| | | | | || '_ \/ __| __/ _` | '_ \| __| \___ \___ \| |_| | | || | | \__ \ || (_| | | | | |_ ___) |__) | _ | |___|_| |_|___/\__\__,_|_| |_|\__| |____/____/|_| |_| Welcome to your shell. If you need a specific command, get in contact with your reseller. i-MSCP InstantSSH plugin v5.0.0 Copyright (c) 2014-2016 Laurent Declercq <l.declercq@nuxwin.com> Last login: Mon Sep 5 21:18:07 2016 from 192.168.1.100 imscp_nuxwin@stretch:~$ env XDG_SESSION_ID=518 TERM=xterm SHELL=/bin/bash SSH_CLIENT=192.168.1.100 45963 22 SSH_TTY=/dev/pts/3 LC_ALL=C.UTF-8 USER=imscp_nuxwin LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36: QT_X11_NO_MITSHM=1 MAIL=/var/mail/imscp_nuxwin PATH=/usr/local/bin:/usr/bin:/bin PWD=/home/imscp_nuxwin/./ LANG=C.UTF-8 SHLVL=1 HOME=/home/imscp_nuxwin/./ LOGNAME=imscp_nuxwin SSH_CONNECTION=192.168.1.100 45963 192.168.1.136 22 XDG_RUNTIME_DIR=/run/user/1002 container=firejail _=/bin/env imscp_nuxwin@stretch:~$ ls /proc 1 buddyinfo consoles diskstats fb iomem kcore kpagecgroup locks mounts partitions softirqs sysrq-trigger timer_stats vmallocinfo 2 bus cpuinfo dma filesystems ioports key-users kpagecount meminfo mtrr sched_debug stat sysvipc tty vmstat 9 cgroups crypto driver fs irq keys kpageflags misc net self swaps thread-self uptime zoneinfo acpi cmdline devices execdomains interrupts kallsyms kmsg loadavg modules pagetypeinfo slabinfo sys timer_list version imscp_nuxwin@stretch:~$ ```
Author
Owner

@netblue30 commented on GitHub (Sep 6, 2016):

No problem, let me know if you need some other fixes.

<!-- gh-comment-id:244932605 --> @netblue30 commented on GitHub (Sep 6, 2016): No problem, let me know if you need some other fixes.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: github-starred/firejail#491
No description provided.