Minijail

repository·main·Indexed 18 days ago

https://github.com/google/minijail

A sandboxing and containment tool used in ChromeOS and Android. It provides a CLI executable (minijail0) for launching sandboxed programs and a library (libminijail) for self-sandboxing code. Features include user/group isolation, namespace configuration, filesystem isolation via chroot and pivot_root, and seccomp-bpf filter support. The project includes a Rust interface (version 0.2.3) and tools for generating seccomp policies from strace output or Linux audit logs.

Tokens
3.9K
Snippets
16
Records
22
Agent score
63%

What's inside minijail

  1. What is Minijail and its threat model

    main

    Minijail is a sandboxing and containment tool used in ChromeOS and Android. It provides two primary interfaces:

    1. An executable used to launch and sandbox other programs.
    2. A library used by code to sandbox itself.

    Purpose and Threat Model

    Minijail is designed to sandbox known binaries on a system to mitigate risks if a service is compromised via a bug or a confused-deputy scenario.

    Warning: It is not designed for safely running malicious code, such as attacker-controlled binaries or binaries using attacker-controlled shared object libraries.

  2. Follow Minijail source code style

    main

    When contributing code, follow these organizational patterns:

    • General Style: Use the Linux kernel coding style.
    • Utility Functions: Place functions with no side-effects in util.{h|c}.
    • System Functions: Place functions with side-effects or dependencies on OS details that do not take a struct minijail argument in system.{h|c}.
  3. Build a seccomp-bpf filter from strace output using generate_seccomp_policy.py

    main

    The generate_seccomp_policy.py script creates a Minijail seccomp-bpf filter by analyzing strace output. This is ideal for processes with a tight working domain.

    Important Considerations:

    • Failure Cases: Ensure you exercise failure scenarios (e.g., calls to abort(2)) to ensure the policy accounts for them.
    • Preloading: If using libminijail or minijail0 with preloading (default for dynamically-linked executables), the first few syscalls after execve(2) might be unnecessary because the filter is installed after that point.
    • Manual Review: When using minijail0, some syscalls might be misattributed to the sandboxed binary. Manually review allowable arguments for ioctl, socket, prctl, mmap, mprotect, and mmap2.
    strace -f -e raw=all -o strace.txt -- <program>
    ./tools/generate_seccomp_policy.py strace.txt > <program>.policy
  4. Get the Minijail source code

    main

    You can clone the official repository from the Chromium source host:

    $ git clone https://chromium.googlesource.com/chromiumos/platform/minijail
    $ cd minijail

    Releases are tagged using the linux-vXX format.

  5. Build Minijail for local experimentation

    main

    To build Minijail for local testing using the libraries from the source directory, run make with the LIBDIR variable set to your target library directory (e.g., /lib64). You can then run the minijail0.sh script to execute commands within a jail.

    Dependencies:

    • libcap
    • Linux kernel headers
    $ make LIBDIR=/lib64
    $ sudo ./minijail0.sh -u ${USER} -g 5000 -- /usr/bin/id
  6. Compile a seccomp-bpf policy using compile_seccomp_policy.py

    main

    The compile_seccomp_policy.py script is an external compiler that converts a .policy file into a highly-optimized BPF binary. This binary can be used with minijail0 via the --seccomp-bpf-binary flag or with libminijail via minijail_set_secomp_filters().

    Requirements:

    • An architecture-specific constants.json file must exist. This file maps syscall names to numbers and contains compile-time constants (like O_RDONLY).
    • You can generate this file using make minijail0 constants.json or via generate_constants_json.py.

    Workflow:

    1. Create a .policy file using the compiler's specific syntax.
    2. Compile the .policy file into a .bpf filter.
    3. Load the filter using minijail0.
    make minijail0 constants.json
    
    # Create the .policy file
    cat > test/seccomp.policy <<EOF
    read: allow
    write: allow
    rt_sigreturn: allow
    exit: allow
    EOF
    
    # Compile the .policy file into a .bpf filter
    ./tools/compile_seccomp_policy.py test/seccomp.policy test/seccomp.bpf
    
    # Load the filter to sandbox your program
    ./minijail0 --seccomp-bpf-binary=test/seccomp.bpf -- <program>
  7. Run Minijail unit tests

    main

    Minijail uses Google Test (gtest & gmock) for unit testing. To run tests:

    1. Download Google Test using the provided script.
    2. Run make tests to build and automatically execute the test suite.
    $ ./get_googletest.sh
    googletest-release-1.8.0/
    ...
    $ make tests
  8. Install Minijail for system-wide usage

    main

    To use Minijail system-wide, you must install the following components:

    1. libminijail.so and libminijailpreload.so to /lib64.
    2. The minijail0 binary to a directory included in your PATH (for example, /usr/bin).
  9. Build a seccomp-bpf filter from Linux audit logs using generate_seccomp_policy.py

    main

    For Linux kernel v4.14+, you can use SECCOMP_RET_LOG to log syscalls via the audit subsystem. This allows generate_seccomp_policy.py to inspect syscall arguments for finer-grained filtering. This method requires Python 3 bindings for auparse (e.g., python3-audit or python-audit packages).

    1. Setup Audit Rules

    Set up audit rules and an empty policy. Use a specific $UID to avoid logspam. The following rules enable SYSCALL auditing for specific syscalls to allow argument inspection:

    for arch in b32 b64; do
      auditctl -a exit,always -F uid=$UID -F arch=$arch -S ioctl -S socket \
               -S prctl -S mmap -S mprotect \
               $([ "$arch" = "b32" ] && echo "-S mmap2") -c
    done
    touch /tmp/empty.policy

    2. Run Program with Empty Policy

    Run your program under minijail0 using the empty policy to stimulate all corner cases and error conditions:

    minijail0 -u $UID -g $GID -L -S /tmp/empty.policy -- <program>

    3. Generate Policy

    Generate the policy from the resulting audit.log:

    ./tools/generate_seccomp_policy.py --audit-comm $PROGRAM_NAME audit.log > $PROGRAM_NAME.policy

    Note: The tool can consume multiple audit logs and/or strace traces to produce a single unified policy.

    # Setup audit rules
    for arch in b32 b64; do
      auditctl -a exit,always -F uid=$UID -F arch=$arch -S ioctl -S socket \
               -S prctl -S mmap -S mprotect \
               $([ "$arch" = "b32" ] && echo "-S mmap2") -c
    done
    touch /tmp/empty.policy
    
    # Run with empty policy
    minijail0 -u $UID -g $GID -L -S /tmp/empty.policy -- <program>
    
    # Generate policy
    ./tools/generate_seccomp_policy.py --audit-comm $PROGRAM_NAME audit.log > $PROGRAM_NAME.policy
  10. Change root to a specific user with minijail0

    main

    You can use the minijail0 executable to launch a process as a different user using the -u (user) and -g (group) flags.

    Example of changing the identity from root to a specific user:

    # Current identity (root)
    # id
    uid=0(root) gid=0(root) groups=0(root),128(pkcs11)
    
    # Launching /usr/bin/id as user 'jorgelo' with group '5000'
    # minijail0 -u jorgelo -g 5000 /usr/bin/id
    uid=72178(jorgelo) gid=5000(eng) groups=5000(eng)
    # minijail0 -u jorgelo -g 5000 /usr/bin/id
  11. Drop root while keeping specific capabilities

    main

    You can use minijail0 to drop root privileges while retaining specific capabilities using the -c flag. This is useful for limiting the effective capabilities of a process.

    Example of dropping root but keeping capability 3000:

    # minijail0 -u jorgelo -c 3000 -- /bin/cat /proc/self/status
    Name: cat
    ...
    CapInh: 0000000000003000
    CapPrm: 0000000000003000
    CapEff: 0000000000003000
    CapBnd: 0000000000003000
    # minijail0 -u jorgelo -c 3000 -- /bin/cat /proc/self/status