//
// Syd: rock-solid application kernel
// src/sandbox.rs: Sandbox configuration
//
// Copyright (c) 2023, 2024, 2025, 2026 Ali Polatel <alip@chesswob.org>
// Based in part upon HardenedBSD's sys/hardenedbsd/hbsd_pax_segvguard.c which is:
//   Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
//   Copyright (c) 2013-2017, by Oliver Pinter <oliver.pinter@hardenedbsd.org>
//   Copyright (c) 2014, by Shawn Webb <shawn.webb@hardenedbsd.org>
//   Copyright (c) 2014, by Danilo Egea Gondolfo <danilo at FreeBSD.org>
//   All rights reserved.
//   SPDX-License-Identifier: BSD-3-Clause
// Based in part upon GrSecurity's grsecurity/grsec_tpe.c (4.9 LTS) which is:
//   Copyright (C) 2001–2017 PaX Team, Bradley Spengler, Open Source Security Inc.
//   SPDX-License-Identifier: GPL-2.0
//
// SPDX-License-Identifier: GPL-3.0

use std::{
    borrow::Cow,
    clone::Clone,
    env,
    ffi::{CString, OsStr, OsString},
    fmt,
    fs::File,
    io::{BufRead, BufReader, Read, Write},
    net::{IpAddr, Ipv4Addr, Ipv6Addr},
    ops::{Deref, DerefMut},
    os::{
        fd::{AsFd, AsRawFd, IntoRawFd, RawFd},
        unix::{ffi::OsStrExt, process::CommandExt},
    },
    process::{Command, Stdio},
    str::FromStr,
    sync::{atomic::AtomicBool, LazyLock, Once, RwLockReadGuard, RwLockWriteGuard},
};

use bitflags::bitflags;
use btoi::btoi;
use data_encoding::{HEXLOWER, HEXLOWER_PERMISSIVE};
use dur::Duration;
use expiringmap::ExpiringMap;
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use iprange::IpRange;
use libseccomp::ScmpArch;
use memchr::{
    arch::all::{is_equal, is_prefix, is_suffix},
    memmem,
};
use nix::{
    errno::Errno,
    fcntl::{OFlag, AT_FDCWD},
    sched::CloneFlags,
    sys::{
        resource::{rlim_t, RLIM_INFINITY},
        signal::Signal,
        stat::{umask, Mode, SFlag},
    },
    unistd::{getcwd, getgroups, setsid, ttyname, Gid, Pid, Uid},
    NixPath,
};
#[cfg(feature = "oci")]
use oci_spec::runtime::Spec;
use serde::{
    ser::{SerializeMap, SerializeSeq, SerializeStruct},
    Serialize, Serializer,
};
use subtle::ConstantTimeEq;

#[cfg(not(target_os = "android"))]
use crate::wordexp::WordExp;
use crate::{
    compat::{
        fs_type_t, fstatx, openat2, statx, FsType, OpenHow, ResolveFlag, STATX_MNT_ID,
        STATX_MNT_ID_UNIQUE, STATX_MODE, STATX_UID,
    },
    config::*,
    confine::{
        extend_ioctl, scmp_arch, scmp_arch_raw, ScmpNotifReq, SydMountAttrFlags, CLONE_NEWTIME,
        NAMESPACE_FLAGS_ALL, SCMP_ARCH,
    },
    debug,
    dns::resolve_rand,
    err::{err2no, SydError, SydResult},
    error,
    fd::{close, closefrom, AT_BADFD},
    hash::{HashAlgorithm, KeySerial, Secret, SydHashMap, SydHashSet, SydIndexMap},
    human_size, info,
    ioctl::IoctlMap,
    landlock::{AccessFs, CompatLevel},
    landlock_policy::LandlockPolicy,
    log_enabled,
    lookup::{file_type, safe_open, safe_open_abs, safe_open_path, FileInfo, MaybeFd},
    mount::api::MountAttrFlags,
    parse_group, parse_user,
    parsers::sandbox::{
        parse_bind_cmd, parse_force_cmd, parse_fs_cmd, parse_landlock_cmd, parse_netlink_cmd,
        parse_scmp_cmd, parse_setid_cmd, str2i64, str2micros, str2secs, str2u64, BindCmd, ForceCmd,
        FsCmd, LandlockCmd, NetlinkCmd, NetlinkOp, PortRange, ScmpCmd, ScmpPattern, SetIdCmd,
    },
    path::{XPath, XPathBuf, PATH_MAX},
    retry::retry_on_eintr,
    rng::{duprand, rand_version},
    rwrite,
    sealbox::{Sealable, SealableSydHashMap, SealableVec, SealableVecDeque},
    syslog::LogLevel,
    uts::{UtsName, UTSNAME_LEN},
    wildmatch::{get_prefix, globmatch, is_literal, litmatch, MatchMethod},
};

// Whether proc_pid_mem(5) should be forced.
//
// This is set using SYD_NO_CROSS_MEMORY_ATTACH.
pub(crate) static PROC_PID_MEM_FORCE: AtomicBool = AtomicBool::new(false);

// Whether proc_pid_mem(5) fallback should be enabled.
//
// By default this is disabled because it's insecure.
// This is set using SYD_PROC_PID_MEM_FALLBACK.
pub(crate) static PROC_PID_MEM_FBACK: AtomicBool = AtomicBool::new(false);

pub(crate) const LINE_MAX: usize = 4096;
const PORT_MIN: u16 = 0;
const PORT_MAX: u16 = 0xFFFF;

const DEF_ACT: &[Action] = &[
    Action::Deny, // fs
    Action::Deny, // walk
    Action::Deny, // stat
    Action::Deny, // read
    Action::Deny, // write
    Action::Deny, // exec
    Action::Deny, // ioctl
    Action::Deny, // create
    Action::Deny, // delete
    Action::Deny, // truncate
    Action::Deny, // rename
    Action::Deny, // symlink
    Action::Deny, // chdir
    Action::Deny, // readdir
    Action::Deny, // mkdir
    Action::Deny, // rmdir
    Action::Deny, // chown
    Action::Deny, // chgrp
    Action::Deny, // chmod
    Action::Deny, // chattr
    Action::Deny, // chroot
    Action::Deny, // utime
    Action::Deny, // mkbdev
    Action::Deny, // mkcdev
    Action::Deny, // mkfifo
    Action::Deny, // mktemp
    Action::Deny, // net/bind
    Action::Deny, // net/connect
    Action::Deny, // net/sendfd
    Action::Deny, // net/block
    Action::Deny, // mem
    Action::Kill, // pid
    Action::Deny, // tpe
    Action::Deny, // force
    Action::Deny, // segvguard
    Action::Kill, // landlock (kill=hard-req, deny=soft-req, warn=best-effort)
];

const DEF_ACT_FS_IDX: usize = 0;
const DEF_ACT_WALK_IDX: usize = 1;
const DEF_ACT_STAT_IDX: usize = 2;
const DEF_ACT_READ_IDX: usize = 3;
const DEF_ACT_WRITE_IDX: usize = 4;
const DEF_ACT_EXEC_IDX: usize = 5;
const DEF_ACT_IOCTL_IDX: usize = 6;
const DEF_ACT_CREATE_IDX: usize = 7;
const DEF_ACT_DELETE_IDX: usize = 8;
const DEF_ACT_TRUNCATE_IDX: usize = 9;
const DEF_ACT_RENAME_IDX: usize = 10;
const DEF_ACT_SYMLINK_IDX: usize = 11;
const DEF_ACT_CHDIR_IDX: usize = 12;
const DEF_ACT_READDIR_IDX: usize = 13;
const DEF_ACT_MKDIR_IDX: usize = 14;
const DEF_ACT_RMDIR_IDX: usize = 15;
const DEF_ACT_CHOWN_IDX: usize = 16;
const DEF_ACT_CHGRP_IDX: usize = 17;
const DEF_ACT_CHMOD_IDX: usize = 18;
const DEF_ACT_CHATTR_IDX: usize = 19;
const DEF_ACT_CHROOT_IDX: usize = 20;
const DEF_ACT_UTIME_IDX: usize = 21;
const DEF_ACT_MKBDEV_IDX: usize = 22;
const DEF_ACT_MKCDEV_IDX: usize = 23;
const DEF_ACT_MKFIFO_IDX: usize = 24;
const DEF_ACT_MKTEMP_IDX: usize = 25;
const DEF_ACT_NET_BIND_IDX: usize = 26;
const DEF_ACT_NET_CONNECT_IDX: usize = 27;
const DEF_ACT_NET_SENDFD_IDX: usize = 28;
const DEF_ACT_NET_BLOCK_IDX: usize = 29;
const DEF_ACT_MEM_IDX: usize = 30;
const DEF_ACT_PID_IDX: usize = 31;
const DEF_ACT_TPE_IDX: usize = 32;
const DEF_ACT_FORCE_IDX: usize = 33;
const DEF_ACT_SEGVGUARD_IDX: usize = 34;
const DEF_ACT_LANDLOCK_IDX: usize = 35;

type AliasMap<'a> = SydHashMap<&'a str, Vec<&'a str>>;
static MAP_NETALIAS: LazyLock<AliasMap> = LazyLock::new(|| {
    let mut map = SydHashMap::default();
    map.insert("any4", vec!["0.0.0.0/0"]);
    map.insert("any6", vec!["::/0"]);
    map.insert("any", vec!["0.0.0.0/0", "::/0"]);
    map.insert("linklocal4", vec!["fe80::/10"]);
    map.insert("linklocal6", vec!["fe80::/10"]);
    map.insert("linklocal", vec!["169.254.0.0/16", "fe80::/10"]);
    map.insert(
        "local4",
        vec![
            "127.0.0.0/8",
            "10.0.0.0/8",
            "172.16.0.0/12",
            "192.168.0.0/16",
        ],
    );
    map.insert("local6", vec!["::1", "fe80::/7", "fc00::/7", "fec0::/7"]);
    map.insert(
        "local",
        vec![
            "127.0.0.0/8",
            "10.0.0.0/8",
            "172.16.0.0/12",
            "192.168.0.0/16",
            "::1/128",
            "fe80::/7",
            "fc00::/7",
            "fec0::/7",
        ],
    );
    map.insert("loopback4", vec!["127.0.0.0/8"]);
    map.insert("loopback6", vec!["::1/128"]);
    map.insert("loopback", vec!["127.0.0.0/8", "::1/128"]);

    map
});

fn strbool(s: &str) -> Result<bool, Errno> {
    match s.to_ascii_lowercase().as_str() {
        "1" | "on" | "t" | "tr" | "tru" | "true" | "✓" => Ok(true),
        "0" | "off" | "f" | "fa" | "fal" | "fals" | "false" | "✗" => Ok(false),
        "" => Err(Errno::ENOENT),
        _ => Err(Errno::EINVAL),
    }
}

bitflags! {
    /// Represents allowlisted netlink families.
    #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
    pub(crate) struct NetlinkFamily: u32 {
        const NETLINK_ROUTE = 1 << 0;     // Routing/device hook
        const NETLINK_UNUSED = 1 << 1;    // Unused number
        const NETLINK_USERSOCK = 1 << 2;  // Reserved for user mode socket protocols
        const NETLINK_FIREWALL = 1 << 3;  // Unused number, formerly ip_queue
        const NETLINK_SOCK_DIAG = 1 << 4; // socket monitoring
        const NETLINK_NFLOG = 1 << 5;     // netfilter/iptables ULOG
        const NETLINK_XFRM = 1 << 6;      // ipsec
        const NETLINK_SELINUX = 1 << 7;   // SELinux event notifications
        const NETLINK_ISCSI = 1 << 8;     // Open-iSCSI
        const NETLINK_AUDIT = 1 << 9;     // auditing
        const NETLINK_FIB_LOOKUP = 1 << 10;
        const NETLINK_CONNECTOR = 1 << 11;
        const NETLINK_NETFILTER = 1 << 12; // netfilter subsystem
        const NETLINK_IP6_FW = 1 << 13;
        const NETLINK_DNRTMSG = 1 << 14;        // DECnet routing messages (obsolete)
        const NETLINK_KOBJECT_UEVENT = 1 << 15; // Kernel messages to userspace
        const NETLINK_GENERIC = 1 << 16;
        // leave room for const NETLINK_DM (DM Events)
        const NETLINK_SCSITRANSPORT = 1 << 18; // SCSI Transports
        const NETLINK_ECRYPTFS = 1 << 19;
        const NETLINK_RDMA = 1 << 20;
        const NETLINK_CRYPTO = 1 << 21; // Crypto layer
        const NETLINK_SMC = 1 << 22;    // SMC monitoring
    }
}

impl FromStr for NetlinkFamily {
    type Err = Errno;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        let mut families = NetlinkFamily::empty();
        for family in value.split(',') {
            families |= match family.to_ascii_lowercase().as_str() {
                "all" => Self::all(),
                "route" => Self::NETLINK_ROUTE,
                "usersock" => Self::NETLINK_USERSOCK,
                "firewall" => Self::NETLINK_FIREWALL,
                "inet_diag" | "sock_diag" => Self::NETLINK_SOCK_DIAG,
                "nflog" => Self::NETLINK_NFLOG,
                "xfrm" => Self::NETLINK_XFRM,
                "selinux" => Self::NETLINK_SELINUX,
                "iscsi" => Self::NETLINK_ISCSI,
                "audit" => Self::NETLINK_AUDIT,
                "fib_lookup" => Self::NETLINK_FIB_LOOKUP,
                "connector" => Self::NETLINK_CONNECTOR,
                "netfilter" => Self::NETLINK_NETFILTER,
                "ip6_fw" => Self::NETLINK_IP6_FW,
                "dnrtmsg" => Self::NETLINK_DNRTMSG,
                "kobject_uevent" => Self::NETLINK_KOBJECT_UEVENT,
                "generic" => Self::NETLINK_GENERIC,
                "scsitransport" => Self::NETLINK_SCSITRANSPORT,
                "ecryptfs" => Self::NETLINK_ECRYPTFS,
                "rdma" => Self::NETLINK_RDMA,
                "crypto" => Self::NETLINK_CRYPTO,
                "smc" => Self::NETLINK_SMC,
                _ => return Err(Errno::EINVAL),
            };
        }

        if !families.is_empty() {
            Ok(families)
        } else {
            Err(Errno::ENOENT)
        }
    }
}

impl NetlinkFamily {
    pub(crate) fn max() -> libc::c_int {
        libc::NETLINK_CRYPTO + 1 // NETLINK_SMC
    }

    pub(crate) fn to_vec(self) -> Vec<libc::c_int> {
        let mut vec = Vec::new();

        if self.is_empty() {
            // Do nothing.
        } else {
            for netlink_family in self {
                vec.push(netlink_family.to_raw_int());
            }
        }

        vec
    }

    fn to_raw_int(self) -> libc::c_int {
        match self {
            Self::NETLINK_ROUTE => libc::NETLINK_ROUTE,
            Self::NETLINK_USERSOCK => libc::NETLINK_USERSOCK,
            Self::NETLINK_FIREWALL => libc::NETLINK_FIREWALL,
            Self::NETLINK_SOCK_DIAG => libc::NETLINK_SOCK_DIAG,
            Self::NETLINK_NFLOG => libc::NETLINK_NFLOG,
            Self::NETLINK_XFRM => libc::NETLINK_XFRM,
            Self::NETLINK_SELINUX => libc::NETLINK_SELINUX,
            Self::NETLINK_ISCSI => libc::NETLINK_ISCSI,
            Self::NETLINK_AUDIT => libc::NETLINK_AUDIT,
            Self::NETLINK_FIB_LOOKUP => libc::NETLINK_FIB_LOOKUP,
            Self::NETLINK_CONNECTOR => libc::NETLINK_CONNECTOR,
            Self::NETLINK_NETFILTER => libc::NETLINK_NETFILTER,
            Self::NETLINK_IP6_FW => libc::NETLINK_IP6_FW,
            Self::NETLINK_DNRTMSG => libc::NETLINK_DNRTMSG,
            Self::NETLINK_KOBJECT_UEVENT => libc::NETLINK_KOBJECT_UEVENT,
            Self::NETLINK_GENERIC => libc::NETLINK_GENERIC,
            Self::NETLINK_SCSITRANSPORT => libc::NETLINK_SCSITRANSPORT,
            Self::NETLINK_ECRYPTFS => libc::NETLINK_ECRYPTFS,
            Self::NETLINK_RDMA => libc::NETLINK_RDMA,
            Self::NETLINK_CRYPTO => libc::NETLINK_CRYPTO,
            Self::NETLINK_SMC => libc::NETLINK_CRYPTO + 1,
            _ => unreachable!(),
        }
    }
}

/// Represents an integrity error, used by Force Sandboxing.
#[derive(Debug)]
pub enum IntegrityError {
    /// System error, represented by an Errno.
    Sys(Errno),
    /// Hash mismatch.
    Hash {
        /// The action to take on mismatch.
        action: Action,
        /// Expected hash as hex-encoded string.
        expected: String,
        /// Found hash as hex-encoded string.
        found: String,
    },
}

impl From<Errno> for IntegrityError {
    fn from(errno: Errno) -> Self {
        Self::Sys(errno)
    }
}

impl From<std::io::Error> for IntegrityError {
    fn from(err: std::io::Error) -> Self {
        Self::Sys(err2no(&err))
    }
}

impl From<SydError> for IntegrityError {
    fn from(error: SydError) -> Self {
        Self::Sys(error.errno().unwrap_or(Errno::ENOSYS))
    }
}

/// Helper to report syd(2) sandbox API version.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Version {
    major: u8,
    minor: u8,
}

impl Version {
    /// Create a new version payload.
    pub const fn new(major: u8, minor: u8) -> Self {
        Self { major, minor }
    }

    /// The major version number.
    pub const fn major(&self) -> u8 {
        self.major
    }

    /// The minor version number.
    pub const fn minor(&self) -> u8 {
        self.minor
    }

    /// Converts the `Version` to a `dev_t` (device type) value.
    pub fn dev(&self) -> u64 {
        u64::from(self.major) << 8 | u64::from(self.minor)
    }
}

impl fmt::Display for Version {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}.{}", self.major, self.minor)
    }
}

impl Serialize for Version {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(3))?;

        map.serialize_entry("major", &self.major)?;
        map.serialize_entry("minor", &self.minor)?;
        map.serialize_entry("version", &self.to_string())?;

        map.end()
    }
}

/// Represents a recursive bind mount operation.
#[derive(Debug)]
pub struct BindMount {
    /// Source directory
    pub src: XPathBuf,
    /// Target directory, can be the same as source
    pub dst: XPathBuf,
    /// The options that are allowed are:
    /// ro, nosuid, nodev, noexec, nosymfollow, noatime, nodiratime, relatime, strictatime
    /// kernel is going to ignore other options.
    pub opt: MountAttrFlags,
    /// Optional filesystem specific data, useful for tmpfs.
    pub dat: Option<String>,
}

impl PartialEq for BindMount {
    // Flags are not used in equality check.
    fn eq(&self, other: &Self) -> bool {
        self.src == other.src && self.dst == other.dst
    }
}

impl Eq for BindMount {}

impl fmt::Display for BindMount {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let opts = SydMountAttrFlags(self.opt);
        let opts = if opts.0.is_empty() {
            "none".to_string()
        } else {
            opts.to_names().join(",")
        };
        write!(
            f,
            "{}->{}:{opts}:{}",
            self.src,
            self.dst,
            self.dat.as_deref().unwrap_or("none")
        )
    }
}

impl Serialize for BindMount {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(4))?; // We expect 4 fields.

        // Serialize src field
        map.serialize_entry("src", &self.src)?;

        // Serialize dst field
        map.serialize_entry("dst", &self.dst)?;

        // Serialize opt field using to_names from SydMountAttrFlags
        let syd_flags = SydMountAttrFlags(self.opt);
        let flags_names = syd_flags.to_names();
        map.serialize_entry("opt", &flags_names)?;

        // Serialize dat field
        match &self.dat {
            Some(dat) => map.serialize_entry("dat", &dat)?,
            None => map.serialize_entry("dat", &None::<String>)?,
        };

        map.end()
    }
}

bitflags! {
    /// Sandboxing capabilities
    //
    // Changing the order of the first 32-bits requires
    // an API version bump, see DESCRIPTION in syd(2).
    #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
    pub struct Capability: u64 {
        /// Landlock capability
        const CAP_LOCK = 1 << 0;
        /// Walk capability
        const CAP_WALK = 1 << 1;
        /// List capability
        const CAP_STAT = 1 << 2;
        /// Read capability
        const CAP_READ = 1 << 3;
        /// Write capability
        const CAP_WRITE = 1 << 4;
        /// Execute capability
        const CAP_EXEC = 1 << 5;
        /// Ioctl capability
        const CAP_IOCTL = 1 << 6;
        /// Create capability
        const CAP_CREATE = 1 << 7;
        /// Delete capability
        const CAP_DELETE = 1 << 8;
        /// Rename capability
        const CAP_RENAME = 1 << 9;
        /// Symlink capability
        const CAP_SYMLINK = 1 << 10;
        /// Truncate capability
        const CAP_TRUNCATE = 1 << 11;
        /// Chdir capability
        const CAP_CHDIR = 1 << 12;
        /// List-directory capability
        const CAP_READDIR = 1 << 13;
        /// Make-directory capability
        const CAP_MKDIR = 1 << 14;
        /// Remove-directory capability
        const CAP_RMDIR = 1 << 15;
        /// Change owner capability
        const CAP_CHOWN = 1 << 16;
        /// Change group capability
        const CAP_CHGRP = 1 << 17;
        /// Change mode capability
        const CAP_CHMOD = 1 << 18;
        /// Change attribute capability
        const CAP_CHATTR = 1 << 19;
        /// Chroot capability
        const CAP_CHROOT = 1 << 20;
        /// Change file last access and modification time capability
        const CAP_UTIME = 1 << 21;
        /// Create block device capability
        const CAP_MKBDEV = 1 << 22;
        /// Create character device capability
        const CAP_MKCDEV = 1 << 23;
        /// Create named pipe capability
        const CAP_MKFIFO = 1 << 24;
        /// Temporary file capability
        const CAP_MKTEMP = 1 << 25;
        /// Network bind capability
        const CAP_NET_BIND = 1 << 26;
        /// Network connect capability
        const CAP_NET_CONNECT = 1 << 27;
        /// Network sendfd capability
        const CAP_NET_SENDFD = 1 << 28;
        /// Filesystem capability
        const CAP_FS = 1 << 29;
        /// Proxy sandboxing
        const CAP_PROXY = 1 << 30;
        /// PTY sandboxing
        const CAP_PTY = 1 << 31;
        /// Force capability
        const CAP_FORCE = 1 << 32;
        /// Trusted Path Execution (TPE) capability
        const CAP_TPE = 1 << 33;
        /// Memory capability
        const CAP_MEM = 1 << 34;
        /// Pid capability
        const CAP_PID = 1 << 35;

        /// Pseudo capability for Append, only used for caching.
        const CAP_APPEND = 1 << 61;
        /// Pseudo capability for Crypt, only used for caching.
        const CAP_CRYPT = 1 << 62;
        /// Pseudo capability for Mask, only used for caching.
        const CAP_MASK = 1 << 63;

        /// All capabilities with path/glob rules
        /// Used by `all` alias.
        /// Includes network sandboxing.
        const CAP_GLOB =
            Self::CAP_WALK.bits() |
            Self::CAP_STAT.bits() |
            Self::CAP_READ.bits() |
            Self::CAP_WRITE.bits() |
            Self::CAP_EXEC.bits() |
            Self::CAP_CREATE.bits() |
            Self::CAP_DELETE.bits() |
            Self::CAP_RENAME.bits() |
            Self::CAP_SYMLINK.bits() |
            Self::CAP_TRUNCATE.bits() |
            Self::CAP_CHDIR.bits() |
            Self::CAP_READDIR.bits() |
            Self::CAP_MKDIR.bits() |
            Self::CAP_RMDIR.bits() |
            Self::CAP_CHOWN.bits() |
            Self::CAP_CHGRP.bits() |
            Self::CAP_CHMOD.bits() |
            Self::CAP_CHATTR.bits() |
            Self::CAP_CHROOT.bits() |
            Self::CAP_UTIME.bits() |
            Self::CAP_MKBDEV.bits() |
            Self::CAP_MKCDEV.bits() |
            Self::CAP_MKFIFO.bits() |
            Self::CAP_MKTEMP.bits() |
            Self::CAP_NET_BIND.bits() |
            Self::CAP_NET_CONNECT.bits() |
            Self::CAP_NET_SENDFD.bits();

        /// All capabilities with path/glob rules except `exec`.
        /// Used by `all-x` alias which is used by esandbox.
        /// Includes network sandboxing.
        const CAP_ALL_X =
            Self::CAP_WALK.bits() |
            Self::CAP_STAT.bits() |
            Self::CAP_READ.bits() |
            Self::CAP_WRITE.bits() |
            Self::CAP_CREATE.bits() |
            Self::CAP_DELETE.bits() |
            Self::CAP_RENAME.bits() |
            Self::CAP_SYMLINK.bits() |
            Self::CAP_TRUNCATE.bits() |
            Self::CAP_CHDIR.bits() |
            Self::CAP_READDIR.bits() |
            Self::CAP_MKDIR.bits() |
            Self::CAP_RMDIR.bits() |
            Self::CAP_CHOWN.bits() |
            Self::CAP_CHGRP.bits() |
            Self::CAP_CHMOD.bits() |
            Self::CAP_CHATTR.bits() |
            Self::CAP_CHROOT.bits() |
            Self::CAP_UTIME.bits() |
            Self::CAP_MKBDEV.bits() |
            Self::CAP_MKCDEV.bits() |
            Self::CAP_MKFIFO.bits() |
            Self::CAP_MKTEMP.bits() |
            Self::CAP_NET_BIND.bits() |
            Self::CAP_NET_CONNECT.bits() |
            Self::CAP_NET_SENDFD.bits();

        /// All capabilities with path check except `stat`,
        /// which is treated differently due to path hiding.
        /// Includes network sandboxing.
        const CAP_PATH =
            Self::CAP_WALK.bits() |
            Self::CAP_READ.bits() |
            Self::CAP_WRITE.bits() |
            Self::CAP_EXEC.bits() |
            Self::CAP_CREATE.bits() |
            Self::CAP_DELETE.bits() |
            Self::CAP_RENAME.bits() |
            Self::CAP_SYMLINK.bits() |
            Self::CAP_TRUNCATE.bits() |
            Self::CAP_CHDIR.bits() |
            Self::CAP_READDIR.bits() |
            Self::CAP_MKDIR.bits() |
            Self::CAP_RMDIR.bits() |
            Self::CAP_CHOWN.bits() |
            Self::CAP_CHGRP.bits() |
            Self::CAP_CHMOD.bits() |
            Self::CAP_CHATTR.bits() |
            Self::CAP_CHROOT.bits() |
            Self::CAP_UTIME.bits() |
            Self::CAP_MKBDEV.bits() |
            Self::CAP_MKCDEV.bits() |
            Self::CAP_MKFIFO.bits() |
            Self::CAP_MKTEMP.bits() |
            Self::CAP_NET_BIND.bits() |
            Self::CAP_NET_CONNECT.bits() |
            Self::CAP_NET_SENDFD.bits();

        /// All capabilities that may write.
        /// Used by append-only checker, see can_write().
        const CAP_WRALL =
            Self::CAP_WRITE.bits() |
            Self::CAP_CREATE.bits() |
            Self::CAP_DELETE.bits() |
            Self::CAP_RENAME.bits() |
            Self::CAP_TRUNCATE.bits();

        /// Lookup-like capabilities.
        /// Used by the `lpath` alias as of 3.39.0.
        const CAP_LPATH =
            Self::CAP_WALK.bits() |
            Self::CAP_STAT.bits() |
            Self::CAP_CHDIR.bits();

        /// Read-like capabilities.
        /// Used by the `rpath` alias as of 3.35.0.
        const CAP_RPATH =
            Self::CAP_READ.bits() |
            Self::CAP_READDIR.bits();

        /// Write-like capabilities.
        /// Used by the `wpath` alias as of 3.38.0.
        const CAP_WPATH =
            Self::CAP_WRITE.bits() |
            Self::CAP_TRUNCATE.bits();

        /// Create-like capabilities.
        /// Used by the `cpath` alias as of 3.38.0
        const CAP_CPATH =
            Self::CAP_CREATE.bits() |
            Self::CAP_DELETE.bits() |
            Self::CAP_RENAME.bits();

        /// Device creation capabilities.
        /// Used by the `dpath` alias as of 3.38.0.
        const CAP_DPATH =
            Self::CAP_MKBDEV.bits() |
            Self::CAP_MKCDEV.bits();

        /// Special file creation capabilities.
        /// Used by the `spath` alias as of 3.38.0.
        const CAP_SPATH =
            Self::CAP_MKFIFO.bits() |
            Self::CAP_SYMLINK.bits();

        /// Write-like directory capabilities.
        /// Used by the `tpath` alias as of 3.38.0.
        const CAP_TPATH =
            Self::CAP_MKDIR.bits() |
            Self::CAP_RMDIR.bits();

        /// File owner/group change capabilities.
        /// Used by the `fown` alias as of 3.38.0.
        const CAP_FOWN =
            Self::CAP_CHOWN.bits() |
            Self::CAP_CHGRP.bits();

        /// File metadata change capabilities.
        /// Used by the `fattr` alias as of 3.38.0.
        const CAP_FATTR =
            Self::CAP_CHMOD.bits() |
            Self::CAP_CHATTR.bits() |
            Self::CAP_UTIME.bits();

        /// All categories of network type.
        /// Used by the `net` alias as of 3.38.0.
        const CAP_NET =
            Self::CAP_NET_BIND.bits() |
            Self::CAP_NET_CONNECT.bits() |
            Self::CAP_NET_SENDFD.bits();

        /// All categories of IP network type.
        /// Used by the `inet` alias as of 3.38.0.
        const CAP_INET =
            Self::CAP_NET_BIND.bits() |
            Self::CAP_NET_CONNECT.bits();

        /// All categories checked by mmap(2) and mmap2(2).
        const CAP_MMAP =
            Self::CAP_MEM.bits() |
            Self::CAP_EXEC.bits() |
            Self::CAP_FORCE.bits() |
            Self::CAP_TPE.bits();
    }
}

impl Capability {
    /// Returns true if the Capability must be set at startup.
    pub fn is_startup(self) -> bool {
        // Note: CAP_MEM is not here because turning it off
        // at runtime is still possible, however turning it on is not...
        self.intersects(Self::CAP_CRYPT | Self::CAP_PROXY | Self::CAP_PTY | Self::CAP_LOCK)
    }

    /// Returns true if the Capability can write.
    pub fn can_write(self) -> bool {
        self.intersects(Self::CAP_WRALL)
    }

    /// Returns true if IP blocklist should be applied.
    ///
    /// Empty capabilities imply accept{,4}(2) here.
    pub fn is_block(self) -> bool {
        self.is_empty() || self.contains(Self::CAP_NET_CONNECT)
    }

    /// Returns true if Capability is supported by syd-oci.
    pub fn is_oci(self) -> bool {
        !self.intersects(Self::CAP_PROXY | Self::CAP_PTY)
    }

    /// Returns the lower 32 bits of the `Capability` bitmask as a `u32`.
    pub fn nlink(self) -> u32 {
        (self.bits() & 0xFFFFFFFF) as u32
    }
}

pub(crate) static SANDBOX_CAPS: LazyLock<SydIndexMap<&str, Capability>> = LazyLock::new(|| {
    // This is an SydIndexMap so that
    // the API serializes them as a sorted array,
    // see api.rs
    SydIndexMap::from_iter([
        // Capability sets
        ("all", Capability::CAP_GLOB),
        ("all-x", Capability::CAP_ALL_X),
        ("lpath", Capability::CAP_LPATH),
        ("rpath", Capability::CAP_RPATH),
        ("wpath", Capability::CAP_WPATH),
        ("cpath", Capability::CAP_CPATH),
        ("dpath", Capability::CAP_DPATH),
        ("spath", Capability::CAP_SPATH),
        ("tpath", Capability::CAP_TPATH),
        ("fown", Capability::CAP_FOWN),
        ("fattr", Capability::CAP_FATTR),
        ("net", Capability::CAP_NET),
        ("inet", Capability::CAP_INET),
        ("bnet", Capability::CAP_NET_BIND),
        ("cnet", Capability::CAP_NET_CONNECT),
        ("snet", Capability::CAP_NET_SENDFD),
        // Capabilities
        ("fs", Capability::CAP_FS),
        ("walk", Capability::CAP_WALK),
        ("stat", Capability::CAP_STAT),
        ("read", Capability::CAP_READ),
        ("write", Capability::CAP_WRITE),
        ("exec", Capability::CAP_EXEC),
        ("ioctl", Capability::CAP_IOCTL),
        ("create", Capability::CAP_CREATE),
        ("delete", Capability::CAP_DELETE),
        ("rename", Capability::CAP_RENAME),
        ("symlink", Capability::CAP_SYMLINK),
        ("truncate", Capability::CAP_TRUNCATE),
        ("chdir", Capability::CAP_CHDIR),
        ("readdir", Capability::CAP_READDIR),
        ("mkdir", Capability::CAP_MKDIR),
        ("rmdir", Capability::CAP_RMDIR),
        ("chown", Capability::CAP_CHOWN),
        ("chgrp", Capability::CAP_CHGRP),
        ("chmod", Capability::CAP_CHMOD),
        ("chattr", Capability::CAP_CHATTR),
        ("chroot", Capability::CAP_CHROOT),
        ("utime", Capability::CAP_UTIME),
        ("mkbdev", Capability::CAP_MKBDEV),
        ("mkcdev", Capability::CAP_MKCDEV),
        ("mkfifo", Capability::CAP_MKFIFO),
        ("mktemp", Capability::CAP_MKTEMP),
        ("net/bind", Capability::CAP_NET_BIND),
        ("net/connect", Capability::CAP_NET_CONNECT),
        ("net/sendfd", Capability::CAP_NET_SENDFD),
        // Special capabilities
        ("mem", Capability::CAP_MEM),
        ("pid", Capability::CAP_PID),
        ("pty", Capability::CAP_PTY),
        ("tpe", Capability::CAP_TPE),
        ("lock", Capability::CAP_LOCK),
        ("crypt", Capability::CAP_CRYPT),
        ("force", Capability::CAP_FORCE),
        ("fs", Capability::CAP_FS),
        ("proxy", Capability::CAP_PROXY),
    ])
});

impl FromStr for Capability {
    type Err = Errno;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        SANDBOX_CAPS.get(value).copied().ok_or(Errno::EINVAL)
    }
}

#[expect(clippy::cognitive_complexity)]
impl fmt::Display for Capability {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut capabilities: Vec<&str> = vec![];

        if self.contains(Self::CAP_FS) {
            capabilities.push("fs");
        }
        if self.contains(Self::CAP_WALK) {
            capabilities.push("walk");
        }
        if self.contains(Self::CAP_STAT) {
            capabilities.push("stat");
        }
        if self.contains(Self::CAP_READ) {
            capabilities.push("read");
        }
        if self.contains(Self::CAP_WRITE) {
            capabilities.push("write");
        }
        if self.contains(Self::CAP_EXEC) {
            capabilities.push("exec");
        }
        if self.contains(Self::CAP_IOCTL) {
            capabilities.push("ioctl");
        }
        if self.contains(Self::CAP_CREATE) {
            capabilities.push("create");
        }
        if self.contains(Self::CAP_DELETE) {
            capabilities.push("delete");
        }
        if self.contains(Self::CAP_RENAME) {
            capabilities.push("rename");
        }
        if self.contains(Self::CAP_SYMLINK) {
            capabilities.push("symlink");
        }
        if self.contains(Self::CAP_TRUNCATE) {
            capabilities.push("truncate");
        }
        if self.contains(Self::CAP_CHDIR) {
            capabilities.push("chdir");
        }
        if self.contains(Self::CAP_READDIR) {
            capabilities.push("readdir");
        }
        if self.contains(Self::CAP_MKDIR) {
            capabilities.push("mkdir");
        }
        if self.contains(Self::CAP_RMDIR) {
            capabilities.push("rmdir");
        }
        if self.contains(Self::CAP_CHOWN) {
            capabilities.push("chown");
        }
        if self.contains(Self::CAP_CHGRP) {
            capabilities.push("chgrp");
        }
        if self.contains(Self::CAP_CHMOD) {
            capabilities.push("chmod");
        }
        if self.contains(Self::CAP_CHATTR) {
            capabilities.push("chattr");
        }
        if self.contains(Self::CAP_CHROOT) {
            capabilities.push("chroot");
        }
        if self.contains(Self::CAP_UTIME) {
            capabilities.push("utime");
        }
        if self.contains(Self::CAP_MKBDEV) {
            capabilities.push("mkbdev");
        }
        if self.contains(Self::CAP_MKCDEV) {
            capabilities.push("mkcdev");
        }
        if self.contains(Self::CAP_MKFIFO) {
            capabilities.push("mkfifo");
        }
        if self.contains(Self::CAP_MKTEMP) {
            capabilities.push("mktemp");
        }
        if self.contains(Self::CAP_NET_BIND) {
            capabilities.push("net/bind");
        }
        if self.contains(Self::CAP_NET_CONNECT) {
            capabilities.push("net/connect");
        }
        if self.contains(Self::CAP_NET_SENDFD) {
            capabilities.push("net/sendfd");
        }
        if self.contains(Self::CAP_FORCE) {
            capabilities.push("force");
        }
        if self.contains(Self::CAP_TPE) {
            capabilities.push("tpe");
        }
        if self.contains(Self::CAP_PROXY) {
            capabilities.push("proxy");
        }
        if self.contains(Self::CAP_PTY) {
            capabilities.push("pty");
        }
        if self.contains(Self::CAP_MEM) {
            capabilities.push("mem");
        }
        if self.contains(Self::CAP_PID) {
            capabilities.push("pid");
        }
        if self.contains(Self::CAP_CRYPT) {
            capabilities.push("crypt");
        }
        if self.intersects(Self::CAP_LOCK) {
            capabilities.push("lock");
        }

        write!(f, "{}", capabilities.join(","))
    }
}

impl Serialize for Capability {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut seq = match self.iter().count() {
            0 => return serializer.serialize_none(),
            1 => return serializer.serialize_str(&self.to_string()),
            n => serializer.serialize_seq(Some(n))?,
        };

        for cap in self.iter() {
            seq.serialize_element(&cap.to_string())?;
        }

        seq.end()
    }
}

impl TryFrom<(ScmpNotifReq, &str)> for Capability {
    type Error = Errno;

    // Find out capabilities of the system call using the system call name and seccomp request.
    #[expect(clippy::cognitive_complexity)]
    fn try_from(value: (ScmpNotifReq, &str)) -> Result<Self, Errno> {
        let (req, syscall_name) = value;
        match syscall_name {
            name if Self::stat(name) => Ok(Self::CAP_STAT),
            name if Self::exec(name) => Ok(Self::CAP_EXEC),
            name if Self::chdir(name) => Ok(Self::CAP_CHDIR),
            name if Self::readdir(name) => Ok(Self::CAP_READDIR),
            name if Self::mkdir(name) => Ok(Self::CAP_MKDIR),
            // SAFETY: rmdir check must happen before delete,
            // as unlinkat(2) system call may either be rmdir
            // or delete depending on AT_REMOVEDIR.
            name if Self::rmdir(name, req) => Ok(Self::CAP_RMDIR),
            name if Self::delete(name) => Ok(Self::CAP_DELETE),
            name if Self::rename(name) => Ok(Self::CAP_RENAME),
            name if Self::symlink(name) => Ok(Self::CAP_SYMLINK),
            name if Self::truncate(name) => Ok(Self::CAP_TRUNCATE),
            name if Self::chmod(name) => Ok(Self::CAP_CHMOD),
            name if Self::chattr(name) => Ok(Self::CAP_CHATTR),
            name if Self::chroot(name) => Ok(Self::CAP_CHROOT),
            name if Self::connect(name) => Ok(Self::CAP_NET_CONNECT),
            "bind" => Ok(Self::CAP_NET_BIND),
            "creat" => Ok(Self::CAP_CREATE),
            "ioctl" => Ok(Self::CAP_IOCTL),
            "mknod" | "mknodat" => Self::mknod(syscall_name, req),
            name if memmem::find(name.as_bytes(), b"utime").is_some() => Ok(Self::CAP_UTIME),
            name if memmem::find(name.as_bytes(), b"chown").is_some() => {
                Ok(Self::chown(syscall_name, req))
            }
            "open" | "openat" | "openat2" => unreachable!(),
            _ => Ok(Self::CAP_WRITE),
        }
    }
}

impl Capability {
    fn chown(syscall_name: &str, req: ScmpNotifReq) -> Self {
        // {f,l,}chown or fchownat (there's no chgrp syscall).
        let (uid, gid) = if is_suffix(syscall_name.as_bytes(), b"at") {
            (2, 3)
        } else {
            (1, 2)
        };

        let mut caps = Capability::empty();
        if libc::uid_t::try_from(req.data.args[uid]).is_ok() {
            caps.insert(Capability::CAP_CHOWN);
        }
        if libc::gid_t::try_from(req.data.args[gid]).is_ok() {
            caps.insert(Capability::CAP_CHGRP);
        }

        // fchown(0,-1,-1) returns success,
        // hence we do want to hide the file.
        if caps.is_empty() {
            caps.insert(Capability::CAP_STAT);
        }

        caps
    }

    fn chmod(syscall_name: &str) -> bool {
        // chmod, fchmod, fchmodat or fchmodat2.
        memmem::find(syscall_name.as_bytes(), b"chmod").is_some()
    }

    fn chattr(syscall_name: &str) -> bool {
        // setxattr, setxattrat, fsetxattr, lsetxattr, removexattr,
        // removexattrat, fremovexattr, or lremovexattr.
        let name = syscall_name.as_bytes();
        memmem::find(name, b"setxattr").is_some() || memmem::find(name, b"removexattr").is_some()
    }

    fn chroot(syscall_name: &str) -> bool {
        is_equal(syscall_name.as_bytes(), b"chroot")
    }

    fn mknod(syscall_name: &str, req: ScmpNotifReq) -> Result<Self, Errno> {
        // mknod or mknodat.
        let idx = if is_suffix(syscall_name.as_bytes(), b"at") {
            2
        } else {
            1
        };
        #[expect(clippy::cast_possible_truncation)]
        let arg = req.data.args[idx] as libc::mode_t & SFlag::S_IFMT.bits();
        let arg = if arg == 0 {
            // Regular file.
            return Ok(Self::CAP_CREATE);
        } else {
            SFlag::from_bits_truncate(arg)
        };

        // Set and return capability.
        match arg {
            SFlag::S_IFBLK => {
                // Block device.
                Ok(Self::CAP_MKBDEV)
            }
            SFlag::S_IFCHR => {
                // Character device.
                Ok(Self::CAP_MKCDEV)
            }
            SFlag::S_IFSOCK => {
                // UNIX domain socket.
                Ok(Self::CAP_NET_BIND)
            }
            SFlag::S_IFIFO => {
                // FIFO (named pipe).
                Ok(Self::CAP_MKFIFO)
            }
            SFlag::S_IFREG => {
                // Regular-file.
                Ok(Self::CAP_CREATE)
            }
            _ => Err(Errno::EINVAL),
        }
    }

    fn exec(syscall_name: &str) -> bool {
        // execve or execveat.
        is_prefix(syscall_name.as_bytes(), b"execve")
    }

    fn stat(syscall_name: &str) -> bool {
        let name = syscall_name.as_bytes();
        STAT_SYSCALLS
            .binary_search_by(|probe| probe.as_bytes().cmp(name))
            .is_ok()
    }

    fn chdir(syscall_name: &str) -> bool {
        // chdir or fchdir.
        is_suffix(syscall_name.as_bytes(), b"chdir")
    }

    fn readdir(syscall_name: &str) -> bool {
        // getdents or getdents64.
        is_prefix(syscall_name.as_bytes(), b"getdents")
    }

    fn mkdir(syscall_name: &str) -> bool {
        // mkdir or mkdirat.
        is_prefix(syscall_name.as_bytes(), b"mkdir")
    }

    fn rmdir(syscall_name: &str, req: ScmpNotifReq) -> bool {
        let name_bytes = syscall_name.as_bytes();

        if is_equal(name_bytes, b"unlinkat") {
            req.data.args[2] & libc::AT_REMOVEDIR as u64 != 0
        } else {
            is_equal(name_bytes, b"rmdir")
        }
    }

    fn delete(syscall_name: &str) -> bool {
        // SAFETY: This check relies on the fact that
        // `rmdir` check is done first, see the respective
        // TryFrom implementation for more information.
        is_prefix(syscall_name.as_bytes(), b"unlink")
    }

    fn rename(syscall_name: &str) -> bool {
        let name = syscall_name.as_bytes();
        RENAME_SYSCALLS
            .binary_search_by(|probe| probe.as_bytes().cmp(name))
            .is_ok()
    }

    fn symlink(syscall_name: &str) -> bool {
        // symlink or symlinkat.
        is_prefix(syscall_name.as_bytes(), b"symlink")
    }

    fn truncate(syscall_name: &str) -> bool {
        let name = syscall_name.as_bytes();
        TRUNCATE_SYSCALLS
            .binary_search_by(|probe| probe.as_bytes().cmp(name))
            .is_ok()
    }

    fn connect(syscall_name: &str) -> bool {
        let name = syscall_name.as_bytes();
        CONNECT_SYSCALLS
            .binary_search_by(|probe| probe.as_bytes().cmp(name))
            .is_ok()
    }
}

bitflags! {
    /// Sandboxing options
    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
    pub struct Flags: u128 {
        /// Deny .. in path resolution for open(2) family calls.
        const FL_DENY_DOTDOT = 1 << 0;
        /// Apply CONTINUE on O_PATH file descriptors rather than
        /// turning them into O_RDONLY.
        const FL_ALLOW_UNSAFE_OPEN_PATH = 1 << 1;
        /// Allow unsafe block device stat(2)s.
        const FL_ALLOW_UNSAFE_STAT_BDEV = 1 << 2;
        /// Allow unsafe character device stat(2)s.
        const FL_ALLOW_UNSAFE_STAT_CDEV = 1 << 3;
        /// Allow unsafe block device notifications.
        const FL_ALLOW_UNSAFE_NOTIFY_BDEV = 1 << 4;
        /// Allow unsafe character device notifications.
        const FL_ALLOW_UNSAFE_NOTIFY_CDEV = 1 << 5;
        /// Allow unsafe file creation.
        /// This mitigation is inspired by CONFIG_GRKERNSEC_FIFO,
        /// and it's similar to protected_{fifos,regular} of proc_sys_fs(5).
        const FL_ALLOW_UNSAFE_CREATE = 1 << 6;
        /// Allow hardlinks to non-regular files and files we don't own.
        /// This mitigation is inspired from CONFIG_GRKERNSEC_LINK.
        const FL_ALLOW_UNSAFE_HARDLINKS = 1 << 7;
        /// Allow symbolic links which reside in sticky-bit-set,
        /// group-writable, or other-writable directories to be followed.
        /// This mitigation is inspired from CONFIG_GRKERNSEC_LINK.
        const FL_ALLOW_UNSAFE_SYMLINKS = 1 << 8;
        /// Allow /proc magic symbolic links to be followed even when
        /// per-process directory pid differs from the caller pid.
        const FL_ALLOW_UNSAFE_MAGICLINKS = 1 << 9;
        /// Disable generating _machine-id_(5) using `ENV_ID`.
        const FL_ALLOW_UNSAFE_MACHINE_ID = 1 << 10;
        /// Disable masking security-sensitive fields in proc_pid_status(5).
        const FL_ALLOW_UNSAFE_PROC_PID_STATUS = 1 << 11;
        /// Allow bind/connect to anyaddr (0.0.0.0/::).
        const FL_ALLOW_UNSAFE_ANY_ADDR = 1 << 12;
        /// Allow indirect execution with ld.so(8).
        const FL_ALLOW_UNSAFE_EXEC_LDSO = 1 << 13;
        /// Allow execution of non-PIE binaries.
        const FL_ALLOW_UNSAFE_EXEC_NOPIE = 1 << 14;
        /// Allow executable stack for ELF binaries.
        const FL_ALLOW_UNSAFE_EXEC_STACK = 1 << 15;
        /// Apply CONTINUE on AMD KFD character devices rather than
        /// opening them in the Syd emulator thread and sending the
        /// file descriptor. This is a workaround because this
        /// character device has per-process handling.
        ///
        /// This setting may be changed at runtime,
        /// and it is highly advised to turn it back off once the
        /// respective resources are open.
        const FL_ALLOW_UNSAFE_OPEN_KFD = 1 << 16;
        /// Deny execution of 32-bit ELF binaries.
        const FL_DENY_EXEC_ELF32 = 1 << 17;
        /// Deny execution of dynamically linked binaries.
        const FL_DENY_EXEC_ELF_DYNAMIC = 1 << 18;
        /// Deny execution of statically linked binaries.
        const FL_DENY_EXEC_ELF_STATIC = 1 << 19;
        /// Deny execution of scripts using an interpreter via #!<path>.
        const FL_DENY_EXEC_SCRIPT = 1 << 20;
        /// Deny access to vDSO.
        const FL_DENY_VDSO = 1 << 21;
        /// Force close-on-exec file descriptors.
        const FL_FORCE_CLOEXEC = 1 << 22;
        /// Force randomized file descriptors.
        const FL_FORCE_RAND_FD = 1 << 23;
        /// Force O_RDONLY open(2) calls.
        const FL_FORCE_RO_OPEN = 1 << 24;
        /// Force bind/connect to loopback.
        const FL_FORCE_LOCAL_NET = 1 << 25;
        /// Force RESOLVE_NO_SYMLINKS at open(2) boundary.
        const FL_FORCE_NO_SYMLINKS = 1 << 26;
        /// Force RESOLVE_NO_MAGICLINKS at open(2) boundary.
        const FL_FORCE_NO_MAGICLINKS = 1 << 27;
        /// Force RESOLVE_NO_XDEV at open(2) boundary.
        const FL_FORCE_NO_XDEV = 1 << 28;
        /// Allow dmesg(1) access to processes without access to the sandbox lock.
        ///
        /// Note this is not the host dmesg(1), it's Syd's syslog(2) emulation
        /// that gives information on access violations.
        const FL_ALLOW_SAFE_SYSLOG = 1 << 29;
        /// Allow access to the Linux kernel crypto API
        const FL_ALLOW_SAFE_KCAPI = 1 << 30;
        /// Allow socket families which are unsupported
        const FL_ALLOW_UNSUPP_SOCKET = 1 << 31;
        /// Allow filenames with control characters in them.
        const FL_ALLOW_UNSAFE_FILENAME = 1 << 32;
        /// Allow secret memfds and executable memfds.
        const FL_ALLOW_UNSAFE_MEMFD = 1 << 33;
        /// Remove xattr restrictions for user.syd.* and security.*.
        const FL_ALLOW_UNSAFE_XATTR = 1 << 34;
        /// Negate TPE GID logic.
        const FL_TPE_NEGATE = 1 << 35;
        /// Ensure TPE directory is root owned.
        const FL_TPE_ROOT_OWNED = 1 << 36;
        /// Ensure TPE directory is user or root owned.
        const FL_TPE_USER_OWNED = 1 << 37;
        /// Ensure TPE directory is on root filesystem.
        const FL_TPE_ROOT_MOUNT = 1 << 38;
        /// Wait for all processes before exiting.
        const FL_EXIT_WAIT_ALL = 1 << 39;

        /// If set at startup, sets synchronous mode for seccomp-notify.
        const FL_SYNC_SCMP = 1 << 52;
        /// If set at startup, all id system calls return 0 in the sandbox.
        const FL_FAKE_ROOT = 1 << 53;
        /// If set at startup, root is mapped to current user in the user namespace.
        const FL_MAP_ROOT = 1 << 54;
        /// Allow deprecated system calls inside the sandbox.
        const FL_ALLOW_UNSAFE_DEPRECATED = 1 << 55;
        /// Allow seccomp-bpf filters inside the sandbox.
        const FL_ALLOW_UNSAFE_CBPF = 1 << 56;
        /// Allow EBPF programs inside the sandbox.
        const FL_ALLOW_UNSAFE_EBPF = 1 << 57;
        /// Allow kernel pointers in syscall arguments.
        const FL_ALLOW_UNSAFE_KPTR = 1 << 58;
        /// Allow unsafe block device creation.
        const FL_ALLOW_UNSAFE_MKBDEV = 1 << 59;
        /// Allow unsafe character device creation.
        const FL_ALLOW_UNSAFE_MKCDEV = 1 << 60;
        /// Do NOT harden madvise(2) system call.
        const FL_ALLOW_UNSAFE_MADVISE = 1 << 61;
        /// Allow mbind(2) system call.
        const FL_ALLOW_UNSAFE_MBIND = 1 << 62;
        /// Disable enforcing system call argument cookies using seccomp(2).
        const FL_ALLOW_UNSAFE_NOCOOKIE = 1 << 63;
        /// Disable sealing sandbox policy as read-only using mseal(2).
        const FL_ALLOW_UNSAFE_NOMSEAL = 1 << 64;
        /// Disable XOM marking of Syd's executable mappings.
        const FL_ALLOW_UNSAFE_NOXOM = 1 << 65;
        /// Allow MSG_OOB flag for send{,to,msg,mmsg}(2).
        const FL_ALLOW_UNSAFE_OOB = 1 << 66;
        /// Allow perf calls inside the sandbox.
        const FL_ALLOW_UNSAFE_PERF = 1 << 67;
        /// Allow notification pipes inside the sandbox.
        const FL_ALLOW_UNSAFE_PIPE = 1 << 68;
        /// Allow unsafe setsockopt(2) operations inside the sandbox.
        const FL_ALLOW_UNSAFE_SETSOCKOPT = 1 << 69;
        /// Disable setting AT_SECURE at PTRACE_EVENT_EXEC boundary.
        const FL_ALLOW_UNSAFE_EXEC_LIBC = 1 << 70;
        /// Allow unsafe memory manipulation.
        const FL_ALLOW_UNSAFE_EXEC_MEMORY = 1 << 71;
        /// Allows unsafe exec calls with NULL as argv and envp arguments.
        const FL_ALLOW_UNSAFE_EXEC_NULL = 1 << 72;
        /// Disable setting SECBIT_EXEC_RESTRICT_FILE_LOCKED.
        /// No-op on Linux<6.14.
        const FL_ALLOW_UNSAFE_EXEC_SCRIPT = 1 << 73;
        /// Disable setting SECBIT_EXEC_DENY_INTERACTIVE.
        /// No-op on Linux<6.14.
        const FL_ALLOW_UNSAFE_EXEC_INTERACTIVE = 1 << 74;
        /// Do not force speculative execution mitigations
        const FL_ALLOW_UNSAFE_EXEC_SPECULATIVE = 1 << 75;
        /// Allows unsafe ptrace calls.
        /// Disables {chdir,exec}-TOCTOU mitigator.
        /// Keeps the capability CAP_SYS_PTRACE.
        const FL_ALLOW_UNSAFE_PTRACE = 1 << 76;
        /// Disable SROP mitigations for {rt_,}sigreturn
        const FL_ALLOW_UNSAFE_SIGRETURN = 1 << 77;
        /// Allow core dumps and ptracing for the Syd process.
        /// Together with FL_ALLOW_UNSAFE_PTRACE allows strace -f syd.
        const FL_ALLOW_UNSAFE_DUMPABLE = 1 << 78;
        /// Retain capability CAP_SETUID
        const FL_ALLOW_SAFE_SETUID = 1 << 79;
        /// Retain capability CAP_SETGID
        const FL_ALLOW_SAFE_SETGID = 1 << 80;
        /// Allow successful bind calls for subsequent connect calls
        const FL_ALLOW_SAFE_BIND = 1 << 81;
        /// Retain capability CAP_NET_BIND_SERVICE
        const FL_ALLOW_UNSAFE_BIND = 1 << 82;
        /// Retain capability CAP_CHOWN
        const FL_ALLOW_UNSAFE_CHOWN = 1 << 83;
        /// Make chroot(2) no-op.
        const FL_ALLOW_UNSAFE_CHROOT = 1 << 84;
        /// Make pivot_root(2) no-op.
        const FL_ALLOW_UNSAFE_PIVOT_ROOT = 1 << 85;
        /// Allow system calls for CPU emulation functionality
        const FL_ALLOW_UNSAFE_CPU = 1 << 86;
        /// Allow Kernel keyring access.
        const FL_ALLOW_UNSAFE_KEYRING = 1 << 87;
        /// Allow system calls used for memory protection keys.
        const FL_ALLOW_UNSAFE_PKEY = 1 << 88;
        /// Avoid mounting internal procfs(5) with subset=pid.
        const FL_ALLOW_UNSAFE_PROC_FILES = 1 << 89;
        /// Retain _all_ Linux capabilities.
        const FL_ALLOW_UNSAFE_CAPS = 1 << 90;
        /// Retain SECBIT_KEEP_CAPS and do NOT set SECBIT_NO_SETUID_FIXUP.
        const FL_ALLOW_UNSAFE_CAP_FIXUP = 1 << 91;
        /// Allow unsafe environment variables.
        const FL_ALLOW_UNSAFE_ENV = 1 << 92;
        /// Allow unsafe socket families (RAW and PACKET).
        const FL_ALLOW_UNSAFE_SOCKET = 1 << 93;
        /// Allow unsafe syslog calls (reading /proc/kmsg etc.)
        const FL_ALLOW_UNSAFE_SYSLOG = 1 << 94;
        /// Allow unsafe cachestat(2) and mincore(2) system calls.
        const FL_ALLOW_UNSAFE_PAGE_CACHE = 1 << 95;
        /// Allow unsafe nice(2) calls.
        const FL_ALLOW_UNSAFE_NICE = 1 << 96;
        /// Allow unsafe personality(2) personas.
        const FL_ALLOW_UNSAFE_PERSONALITY = 1 << 97;
        /// Allow unsafe prctl(2) calls
        const FL_ALLOW_UNSAFE_PRCTL = 1 << 98;
        /// Allow unsafe prlimit calls
        const FL_ALLOW_UNSAFE_PRLIMIT = 1 << 99;
        /// Allow unsafe adjtimex and clock_adjtime calls,
        /// and keep the CAP_SYS_TIME capability.
        const FL_ALLOW_UNSAFE_TIME = 1 << 100;
        /// Allow the unsafe io-uring interface
        const FL_ALLOW_UNSAFE_IOURING = 1 << 101;
        /// Allow unsafe mq_open(3) syscalls.
        const FL_ALLOW_UNSAFE_MSGQUEUE = 1 << 102;
        /// Allow unsafe shared memory syscalls.
        const FL_ALLOW_UNSAFE_SHM = 1 << 103;
        /// Allow unsafe permissions in mq_open(2) syscalls.
        const FL_ALLOW_UNSAFE_PERM_MSGQUEUE = 1 << 104;
        /// Allow unsafe permissions in shared memory syscalls.
        const FL_ALLOW_UNSAFE_PERM_SHM = 1 << 105;
        /// Allow unsafe rseq(2) syscall.
        const FL_ALLOW_UNSAFE_RSEQ = 1 << 106;
        /// Allow the unsafe sync(2) and syncfs(2) system calls.
        const FL_ALLOW_UNSAFE_SYNC = 1 << 107;
        /// Allow the unsafe sysinfo(2) system call.
        const FL_ALLOW_UNSAFE_SYSINFO = 1 << 108;
        /// Allow the unsafe uname(2) system call.
        const FL_ALLOW_UNSAFE_UNAME = 1 << 109;
        /// Allow the unsafe vmsplice(2) system call.
        const FL_ALLOW_UNSAFE_VMSPLICE = 1 << 110;
        /// Deny reading the timestamp counter
        const FL_DENY_TSC = 1 << 111;

        /// Allow mount namespace
        const FL_ALLOW_UNSAFE_UNSHARE_MOUNT = 1 << 112;
        /// Allow uts namespace
        const FL_ALLOW_UNSAFE_UNSHARE_UTS = 1 << 113;
        /// Allow ipc namespace
        const FL_ALLOW_UNSAFE_UNSHARE_IPC = 1 << 114;
        /// Allow user namespace
        const FL_ALLOW_UNSAFE_UNSHARE_USER = 1 << 115;
        /// Allow pid namespace
        const FL_ALLOW_UNSAFE_UNSHARE_PID = 1 << 116;
        /// Allow net namespace
        const FL_ALLOW_UNSAFE_UNSHARE_NET = 1 << 117;
        /// Allow cgroup namespace
        const FL_ALLOW_UNSAFE_UNSHARE_CGROUP = 1 << 118;
        /// Allow time namespace
        const FL_ALLOW_UNSAFE_UNSHARE_TIME = 1 << 119;

        /// Unshare mount namespace
        const FL_UNSHARE_MOUNT = 1 << 120;
        /// Unshare uts namespace
        const FL_UNSHARE_UTS = 1 << 121;
        /// Unshare ipc namespace
        const FL_UNSHARE_IPC = 1 << 122;
        /// Unshare user namespace
        const FL_UNSHARE_USER = 1 << 123;
        /// Unshare pid namespace
        const FL_UNSHARE_PID = 1 << 124;
        /// Unshare net namespace
        const FL_UNSHARE_NET = 1 << 125;
        /// Unshare cgroup namespace
        const FL_UNSHARE_CGROUP = 1 << 126;
        /// Unshare time namespace
        const FL_UNSHARE_TIME = 1 << 127;
    }
}

impl From<Flags> for CloneFlags {
    fn from(flags: Flags) -> Self {
        let mut cflags = CloneFlags::empty();

        if flags.contains(Flags::FL_UNSHARE_MOUNT) {
            cflags.insert(CloneFlags::CLONE_NEWNS);
        }

        if flags.contains(Flags::FL_UNSHARE_UTS) {
            cflags.insert(CloneFlags::CLONE_NEWUTS);
        }

        if flags.contains(Flags::FL_UNSHARE_IPC) {
            cflags.insert(CloneFlags::CLONE_NEWIPC);
        }

        if flags.contains(Flags::FL_UNSHARE_USER) {
            cflags.insert(CloneFlags::CLONE_NEWUSER);
        }

        if flags.contains(Flags::FL_UNSHARE_PID) {
            cflags.insert(CloneFlags::CLONE_NEWPID);
        }

        if flags.contains(Flags::FL_UNSHARE_NET) {
            cflags.insert(CloneFlags::CLONE_NEWNET);
        }

        if flags.contains(Flags::FL_UNSHARE_CGROUP) {
            cflags.insert(CloneFlags::CLONE_NEWCGROUP);
        }

        if flags.contains(Flags::FL_UNSHARE_TIME) {
            cflags.insert(CLONE_NEWTIME);
        }

        cflags
    }
}

impl fmt::Display for Flags {
    #[expect(clippy::cognitive_complexity)]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut flags: Vec<&str> = vec![];

        if self.contains(Flags::FL_UNSHARE_MOUNT) {
            flags.push("Unshare Mount");
        }
        if self.contains(Flags::FL_UNSHARE_UTS) {
            flags.push("Unshare UTS");
        }
        if self.contains(Flags::FL_UNSHARE_IPC) {
            flags.push("Unshare Ipc");
        }
        if self.contains(Flags::FL_UNSHARE_USER) {
            flags.push("Unshare User");
        }
        if self.contains(Flags::FL_UNSHARE_PID) {
            flags.push("Unshare Pid");
        }
        if self.contains(Flags::FL_UNSHARE_NET) {
            flags.push("Unshare Net");
        }
        if self.contains(Flags::FL_UNSHARE_CGROUP) {
            flags.push("Unshare CGroup");
        }
        if self.contains(Flags::FL_UNSHARE_TIME) {
            flags.push("Unshare Time");
        }
        if self.contains(Flags::FL_EXIT_WAIT_ALL) {
            flags.push("Exit Wait All");
        }
        if self.contains(Flags::FL_TPE_NEGATE) {
            flags.push("Negate TPE GID Logic");
        }
        if self.contains(Flags::FL_TPE_ROOT_OWNED) {
            flags.push("Ensure TPE directory is root-owned");
        }
        if self.contains(Flags::FL_TPE_USER_OWNED) {
            flags.push("Ensure TPE directory is user-owned");
        }
        if self.contains(Flags::FL_TPE_ROOT_MOUNT) {
            flags.push("Ensure TPE directory is on root-mount");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_BIND) {
            flags.push("Allow Unsafe Bind");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CHOWN) {
            flags.push("Allow Unsafe Chown");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CHROOT) {
            flags.push("Allow Unsafe Chroot");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PIVOT_ROOT) {
            flags.push("Allow Unsafe Pivot Root");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CPU) {
            flags.push("Allow Unsafe CPU Emulation");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_DUMPABLE) {
            flags.push("Allow Unsafe Dumpable");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_KEYRING) {
            flags.push("Allow Unsafe Kernel keyring");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PKEY) {
            flags.push("Allow Unsafe Memory Protection Keys");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PROC_FILES) {
            flags.push("Allow Unsafe Proc Files");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CAPS) {
            flags.push("Allow Unsafe Capabilities");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CAP_FIXUP) {
            flags.push("Allow Unsafe Capability Fixup");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_ENV) {
            flags.push("Allow Unsafe Environment");
        }
        if self.contains(Flags::FL_SYNC_SCMP) {
            flags.push("Seccomp Sync");
        }
        if self.contains(Flags::FL_FAKE_ROOT) {
            flags.push("Fake Root");
        }
        if self.contains(Flags::FL_MAP_ROOT) {
            flags.push("Map Root");
        }
        if self.contains(Flags::FL_ALLOW_SAFE_BIND) {
            flags.push("Allow Safe Bind");
        }
        if self.contains(Flags::FL_ALLOW_SAFE_KCAPI) {
            flags.push("Allow Safe Kernel Crypto API");
        }
        if self.contains(Flags::FL_ALLOW_SAFE_SETUID) {
            flags.push("Allow Safe SetUID");
        }
        if self.contains(Flags::FL_ALLOW_SAFE_SETGID) {
            flags.push("Allow Safe SetGID");
        }
        if self.contains(Flags::FL_ALLOW_SAFE_SYSLOG) {
            flags.push("Allow Safe Syslog");
        }
        if self.contains(Flags::FL_ALLOW_UNSUPP_SOCKET) {
            flags.push("Allow Unsupported Socket Families");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SOCKET) {
            flags.push("Allow Unsafe Socket Families");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SYSLOG) {
            flags.push("Allow Unsafe Syslog");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PAGE_CACHE) {
            flags.push("Allow Unsafe Page Cache");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NICE) {
            flags.push("Allow Unsafe Nice");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PERSONALITY) {
            flags.push("Allow Unsafe Personality");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PRCTL) {
            flags.push("Allow Unsafe Process Control");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PRLIMIT) {
            flags.push("Allow Unsafe PRlimit");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_TIME) {
            flags.push("Allow Unsafe Time");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_ANY_ADDR) {
            flags.push("Allow Unsafe Any Address");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_LDSO) {
            flags.push("Allow Unsafe ld.so(8) Indirect-Exec");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_LIBC) {
            flags.push("Allow Unsafe Libc execution-mode");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_MEMORY) {
            flags.push("Allow Unsafe W^X Memory");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_NOPIE) {
            flags.push("Allow Unsafe Non-PIE Exec");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_NULL) {
            flags.push("Allow Unsafe Exec with NULL argv/envp");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_STACK) {
            flags.push("Allow Unsafe Executable Stack");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_SCRIPT) {
            flags.push("Allow Unsafe Script Execution");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_INTERACTIVE) {
            flags.push("Allow Unsafe Interactive Execution");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC_SPECULATIVE) {
            flags.push("Allow Unsafe Speculative Execution");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SIGRETURN) {
            flags.push("Allow Unsafe Signal Return");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_OPEN_KFD) {
            flags.push("Allow Unsafe AMD KFD Character Device Open");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_OPEN_PATH) {
            flags.push("Allow Unsafe O_PATH Open");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MKBDEV) {
            flags.push("Allow Unsafe Block Device Create");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MKCDEV) {
            flags.push("Allow Unsafe Character Device Create");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_STAT_BDEV) {
            flags.push("Allow Unsafe Block Device Stats");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_STAT_CDEV) {
            flags.push("Allow Unsafe Character Device Stats");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOTIFY_BDEV) {
            flags.push("Allow Unsafe Block Device Notifications");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOTIFY_CDEV) {
            flags.push("Allow Unsafe Character Device Notifications");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_DEPRECATED) {
            flags.push("Allow Unsafe Deprecated Syscalls");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CBPF) {
            flags.push("Allow Unsafe cBPF");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EBPF) {
            flags.push("Allow Unsafe eBPF");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_KPTR) {
            flags.push("Allow Unsafe Kernel Pointers");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MADVISE) {
            flags.push("Allow Unsafe Madvise");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MBIND) {
            flags.push("Allow Unsafe Mbind");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOCOOKIE) {
            flags.push("Allow Unsafe No Cookie");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOMSEAL) {
            flags.push("Allow Unsafe No Memory Seal");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOXOM) {
            flags.push("Allow Unsafe No Execute-Only Memory");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_OOB) {
            flags.push("Allow Unsafe Out of Band Data");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PTRACE) {
            flags.push("Allow Unsafe Ptrace");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PERF) {
            flags.push("Allow Unsafe Perf");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PIPE) {
            flags.push("Allow Unsafe Pipe");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SETSOCKOPT) {
            flags.push("Allow Unsafe Setsockopt");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CREATE) {
            flags.push("Allow Unsafe Create");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_HARDLINKS) {
            flags.push("Allow Unsafe Hardlinks");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SYMLINKS) {
            flags.push("Allow Unsafe Symlinks");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MAGICLINKS) {
            flags.push("Allow Unsafe Magic Links");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MACHINE_ID) {
            flags.push("Allow Unfiltered machine-id(5) Access");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PROC_PID_STATUS) {
            flags.push("Allow Unfiltered proc_pid_status(5) Access");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_FILENAME) {
            flags.push("Allow Unsafe Filename");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_IOURING) {
            flags.push("Allow Unsafe IO_Uring");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MSGQUEUE) {
            flags.push("Allow Unsafe Message Queue");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SHM) {
            flags.push("Allow Unsafe Shared Memory");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PERM_MSGQUEUE) {
            flags.push("Allow Unsafe Permissions for Message Queue");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PERM_SHM) {
            flags.push("Allow Unsafe Permissions for Shared Memory");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_RSEQ) {
            flags.push("Allow Unsafe Restartable Sequences");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SYNC) {
            flags.push("Allow Unsafe Sync");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SYSINFO) {
            flags.push("Allow Unsafe SysInfo");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_UNAME) {
            flags.push("Allow Unsafe Uname");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_VMSPLICE) {
            flags.push("Allow Unsafe Vmsplice");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MEMFD) {
            flags.push("Allow Unsafe MemFD");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_XATTR) {
            flags.push("Allow Unsafe Extended Attributes");
        }
        if self.contains(Flags::FL_DENY_DOTDOT) {
            flags.push("Deny DotDot");
        }
        if self.contains(Flags::FL_DENY_EXEC_ELF32) {
            flags.push("Deny 32-bit ELF Execution");
        }
        if self.contains(Flags::FL_DENY_EXEC_ELF_DYNAMIC) {
            flags.push("Deny Dynamic-Linked ELF Execution");
        }
        if self.contains(Flags::FL_DENY_EXEC_ELF_STATIC) {
            flags.push("Deny Static-Linked ELF Execution");
        }
        if self.contains(Flags::FL_DENY_EXEC_SCRIPT) {
            flags.push("Deny Script Execution");
        }
        if self.contains(Flags::FL_DENY_TSC) {
            flags.push("Deny TSC");
        }
        if self.contains(Flags::FL_DENY_VDSO) {
            flags.push("Deny vDSO");
        }
        if self.contains(Flags::FL_FORCE_CLOEXEC) {
            flags.push("Force Close-on-Exec FDs");
        }
        if self.contains(Flags::FL_FORCE_RAND_FD) {
            flags.push("Force Randomized FDs");
        }
        if self.contains(Flags::FL_FORCE_RO_OPEN) {
            flags.push("Force Readonly Open");
        }
        if self.contains(Flags::FL_FORCE_LOCAL_NET) {
            flags.push("Force Local Network");
        }
        if self.contains(Flags::FL_FORCE_NO_SYMLINKS) {
            flags.push("Force No Symbolic Links");
        }
        if self.contains(Flags::FL_FORCE_NO_MAGICLINKS) {
            flags.push("Force No Magic Symbolic Links");
        }
        if self.contains(Flags::FL_FORCE_NO_XDEV) {
            flags.push("Force No Mountpoint Traversal");
        }

        flags.sort();
        write!(f, "{}", flags.join(", "))
    }
}

impl Serialize for Flags {
    #[expect(clippy::cognitive_complexity)]
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut flags: Vec<&str> = vec![];
        if self.is_empty() {
            return serializer.collect_seq(flags);
        }
        if self.contains(Self::FL_UNSHARE_MOUNT) {
            flags.push("unshare-mount");
        }
        if self.contains(Self::FL_UNSHARE_UTS) {
            flags.push("unshare-uts");
        }
        if self.contains(Self::FL_UNSHARE_IPC) {
            flags.push("unshare-ipc");
        }
        if self.contains(Self::FL_UNSHARE_USER) {
            flags.push("unshare-user");
        }
        if self.contains(Self::FL_UNSHARE_PID) {
            flags.push("unshare-pid");
        }
        if self.contains(Self::FL_UNSHARE_NET) {
            flags.push("unshare-net");
        }
        if self.contains(Self::FL_UNSHARE_TIME) {
            flags.push("unshare-time");
        }
        if self.contains(Self::FL_SYNC_SCMP) {
            flags.push("sync-scmp");
        }
        if self.contains(Self::FL_FAKE_ROOT) {
            flags.push("fake-root");
        }
        if self.contains(Self::FL_MAP_ROOT) {
            flags.push("map-root");
        }
        if self.contains(Self::FL_EXIT_WAIT_ALL) {
            flags.push("exit-wait-all");
        }
        if self.contains(Self::FL_TPE_NEGATE) {
            flags.push("tpe-negate");
        }
        if self.contains(Self::FL_TPE_ROOT_OWNED) {
            flags.push("tpe-root-owned");
        }
        if self.contains(Self::FL_TPE_USER_OWNED) {
            flags.push("tpe-user-owned");
        }
        if self.contains(Self::FL_TPE_ROOT_MOUNT) {
            flags.push("tpe-root-mount");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_BIND) {
            flags.push("allow-unsafe-bind");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_CHOWN) {
            flags.push("allow-unsafe-chown");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_CHROOT) {
            flags.push("allow-unsafe-chroot");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PIVOT_ROOT) {
            flags.push("allow-unsafe-pivot-root");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_CPU) {
            flags.push("allow-unsafe-cpu");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_DUMPABLE) {
            flags.push("allow-unsafe-dumpable");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_KEYRING) {
            flags.push("allow-unsafe-keyring");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PKEY) {
            flags.push("allow-unsafe-pkey");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PROC_FILES) {
            flags.push("allow-unsafe-proc-files");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_CAPS) {
            flags.push("allow-unsafe-caps");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_CAP_FIXUP) {
            flags.push("allow-unsafe-cap-fixup");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_ENV) {
            flags.push("allow-unsafe-env");
        }
        if self.contains(Self::FL_ALLOW_SAFE_BIND) {
            flags.push("allow-safe-bind");
        }
        if self.contains(Self::FL_ALLOW_SAFE_KCAPI) {
            flags.push("allow-safe-kcapi");
        }
        if self.contains(Self::FL_ALLOW_SAFE_SETUID) {
            flags.push("allow-safe-setuid");
        }
        if self.contains(Self::FL_ALLOW_SAFE_SETGID) {
            flags.push("allow-safe-setgid");
        }
        if self.contains(Self::FL_ALLOW_SAFE_SYSLOG) {
            flags.push("allow-safe-syslog");
        }
        if self.contains(Self::FL_ALLOW_UNSUPP_SOCKET) {
            flags.push("allow-unsupp-socket");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SOCKET) {
            flags.push("allow-unsafe-socket");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SYSLOG) {
            flags.push("allow-unsafe-syslog");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PAGE_CACHE) {
            flags.push("allow-unsafe-page-cache");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_NICE) {
            flags.push("allow-unsafe-nice");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PERSONALITY) {
            flags.push("allow-unsafe-personality");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PRCTL) {
            flags.push("allow-unsafe-prctl");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PRLIMIT) {
            flags.push("allow-unsafe-prlimit");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_ANY_ADDR) {
            flags.push("allow-unsafe-any-addr");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_LDSO) {
            flags.push("allow-unsafe-exec-ldso");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_LIBC) {
            flags.push("allow-unsafe-exec-libc");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_MEMORY) {
            flags.push("allow-unsafe-exec-memory");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_NOPIE) {
            flags.push("allow-unsafe-exec-nopie");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_NULL) {
            flags.push("allow-unsafe-exec-null");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_STACK) {
            flags.push("allow-unsafe-exec-stack");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_SCRIPT) {
            flags.push("allow-unsafe-exec-script");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_INTERACTIVE) {
            flags.push("allow-unsafe-exec-interactive");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EXEC_SPECULATIVE) {
            flags.push("allow-unsafe-exec-speculative");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SIGRETURN) {
            flags.push("allow-unsafe-sigreturn");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_OPEN_KFD) {
            flags.push("allow-unsafe-open-kfd");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_TIME) {
            flags.push("allow-unsafe-time");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_OPEN_PATH) {
            flags.push("allow-unsafe-open-path");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MKBDEV) {
            flags.push("allow-unsafe-mkbdev");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MKCDEV) {
            flags.push("allow-unsafe-mkcdev");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_STAT_BDEV) {
            flags.push("allow-unsafe-stat-bdev");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_STAT_CDEV) {
            flags.push("allow-unsafe-stat-cdev");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOTIFY_BDEV) {
            flags.push("allow-unsafe-notify-bdev");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOTIFY_CDEV) {
            flags.push("allow-unsafe-notify-cdev");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_DEPRECATED) {
            flags.push("allow-unsafe-deprecated");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_CBPF) {
            flags.push("allow-unsafe-cbpf");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_EBPF) {
            flags.push("allow-unsafe-ebpf");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_KPTR) {
            flags.push("allow-unsafe-kptr");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MADVISE) {
            flags.push("allow-unsafe-madvise");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MBIND) {
            flags.push("allow-unsafe-mbind");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_NOCOOKIE) {
            flags.push("allow-unsafe-nocookie");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_NOMSEAL) {
            flags.push("allow-unsafe-nomseal");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_NOXOM) {
            flags.push("allow-unsafe-noxom");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_OOB) {
            flags.push("allow-unsafe-oob");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PTRACE) {
            flags.push("allow-unsafe-ptrace");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PERF) {
            flags.push("allow-unsafe-perf");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PIPE) {
            flags.push("allow-unsafe-pipe");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SETSOCKOPT) {
            flags.push("allow-unsafe-setsockopt");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_CREATE) {
            flags.push("allow-unsafe-create");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_HARDLINKS) {
            flags.push("allow-unsafe-hardlinks");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SYMLINKS) {
            flags.push("allow-unsafe-symlinks");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MAGICLINKS) {
            flags.push("allow-unsafe-magiclinks");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MACHINE_ID) {
            flags.push("allow-unsafe-machine-id");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PROC_PID_STATUS) {
            flags.push("allow-unsafe-proc-pid-status");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_FILENAME) {
            flags.push("allow-unsafe-filename");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_IOURING) {
            flags.push("allow-unsafe-uring");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MSGQUEUE) {
            flags.push("allow-unsafe-msgqueue");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SHM) {
            flags.push("allow-unsafe-shm");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PERM_MSGQUEUE) {
            flags.push("allow-unsafe-perm-msgqueue");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_PERM_SHM) {
            flags.push("allow-unsafe-perm-shm");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_RSEQ) {
            flags.push("allow-unsafe-rseq");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SYNC) {
            flags.push("allow-unsafe-sync");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_SYSINFO) {
            flags.push("allow-unsafe-sysinfo");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNAME) {
            flags.push("allow-unsafe-uname");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_VMSPLICE) {
            flags.push("allow-unsafe-vmsplice");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_MEMFD) {
            flags.push("allow-unsafe-memfd");
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_XATTR) {
            flags.push("allow-unsafe-xattr");
        }
        if self.contains(Self::FL_DENY_DOTDOT) {
            flags.push("deny-dotdot");
        }
        if self.contains(Self::FL_DENY_EXEC_ELF32) {
            flags.push("deny-exec-elf32");
        }
        if self.contains(Self::FL_DENY_EXEC_ELF_DYNAMIC) {
            flags.push("deny-exec-elf-dynamic");
        }
        if self.contains(Self::FL_DENY_EXEC_ELF_STATIC) {
            flags.push("deny-exec-elf-static");
        }
        if self.contains(Self::FL_DENY_EXEC_SCRIPT) {
            flags.push("deny-exec-script");
        }
        if self.contains(Self::FL_DENY_TSC) {
            flags.push("deny-tsc");
        }
        if self.contains(Self::FL_DENY_VDSO) {
            flags.push("deny-vdso");
        }
        if self.contains(Self::FL_FORCE_CLOEXEC) {
            flags.push("force-cloexec");
        }
        if self.contains(Self::FL_FORCE_RAND_FD) {
            flags.push("force-rand-fd");
        }
        if self.contains(Self::FL_FORCE_RO_OPEN) {
            flags.push("force-ro-open");
        }
        if self.contains(Self::FL_FORCE_LOCAL_NET) {
            flags.push("force-local-net");
        }
        if self.contains(Self::FL_FORCE_NO_SYMLINKS) {
            flags.push("force-no-symlinks");
        }
        if self.contains(Self::FL_FORCE_NO_MAGICLINKS) {
            flags.push("force-no-magiclinks");
        }
        if self.contains(Self::FL_FORCE_NO_XDEV) {
            flags.push("force-no-xdev");
        }

        flags.sort();
        serializer.collect_seq(flags)
    }
}

impl Flags {
    // Returns true if the Flag must be set at startup.
    fn is_startup(self) -> bool {
        self.intersects(
            Self::FL_MAP_ROOT
                | Self::FL_FAKE_ROOT
                | Self::FL_SYNC_SCMP
                | Self::FL_EXIT_WAIT_ALL
                | Self::FL_ALLOW_SAFE_BIND
                | Self::FL_ALLOW_SAFE_SETGID
                | Self::FL_ALLOW_SAFE_SETUID
                | Self::FL_ALLOW_SAFE_SYSLOG
                | Self::FL_ALLOW_UNSAFE_BIND
                | Self::FL_ALLOW_UNSAFE_CAPS
                | Self::FL_ALLOW_UNSAFE_CAP_FIXUP
                | Self::FL_ALLOW_UNSAFE_CBPF
                | Self::FL_ALLOW_UNSAFE_CHOWN
                | Self::FL_ALLOW_UNSAFE_CHROOT
                | Self::FL_ALLOW_UNSAFE_CPU
                | Self::FL_ALLOW_UNSAFE_DEPRECATED
                | Self::FL_ALLOW_UNSAFE_DUMPABLE
                | Self::FL_ALLOW_UNSAFE_EBPF
                | Self::FL_ALLOW_UNSAFE_ENV
                | Self::FL_ALLOW_UNSAFE_EXEC_INTERACTIVE
                | Self::FL_ALLOW_UNSAFE_EXEC_LIBC
                | Self::FL_ALLOW_UNSAFE_EXEC_MEMORY
                | Self::FL_ALLOW_UNSAFE_EXEC_NULL
                | Self::FL_ALLOW_UNSAFE_EXEC_SCRIPT
                | Self::FL_ALLOW_UNSAFE_EXEC_SPECULATIVE
                | Self::FL_ALLOW_UNSAFE_IOURING
                | Self::FL_ALLOW_UNSAFE_KEYRING
                | Self::FL_ALLOW_UNSAFE_KPTR
                | Self::FL_ALLOW_UNSAFE_MADVISE
                | Self::FL_ALLOW_UNSAFE_MBIND
                | Self::FL_ALLOW_UNSAFE_MKBDEV
                | Self::FL_ALLOW_UNSAFE_MKCDEV
                | Self::FL_ALLOW_UNSAFE_MSGQUEUE
                | Self::FL_ALLOW_UNSAFE_NICE
                | Self::FL_ALLOW_UNSAFE_NOCOOKIE
                | Self::FL_ALLOW_UNSAFE_NOMSEAL
                | Self::FL_ALLOW_UNSAFE_NOXOM
                | Self::FL_ALLOW_UNSAFE_OOB
                | Self::FL_ALLOW_UNSAFE_PAGE_CACHE
                | Self::FL_ALLOW_UNSAFE_PERF
                | Self::FL_ALLOW_UNSAFE_PERM_MSGQUEUE
                | Self::FL_ALLOW_UNSAFE_PERM_SHM
                | Self::FL_ALLOW_UNSAFE_PERSONALITY
                | Self::FL_ALLOW_UNSAFE_PIPE
                | Self::FL_ALLOW_UNSAFE_PIVOT_ROOT
                | Self::FL_ALLOW_UNSAFE_PKEY
                | Self::FL_ALLOW_UNSAFE_PRCTL
                | Self::FL_ALLOW_UNSAFE_PRLIMIT
                | Self::FL_ALLOW_UNSAFE_PROC_FILES
                | Self::FL_ALLOW_UNSAFE_PTRACE
                | Self::FL_ALLOW_UNSAFE_RSEQ
                | Self::FL_ALLOW_UNSAFE_SETSOCKOPT
                | Self::FL_ALLOW_UNSAFE_SHM
                | Self::FL_ALLOW_UNSAFE_SIGRETURN
                | Self::FL_ALLOW_UNSAFE_SOCKET
                | Self::FL_ALLOW_UNSAFE_SYNC
                | Self::FL_ALLOW_UNSAFE_SYSINFO
                | Self::FL_ALLOW_UNSAFE_SYSLOG
                | Self::FL_ALLOW_UNSAFE_TIME
                | Self::FL_ALLOW_UNSAFE_UNAME
                | Self::FL_ALLOW_UNSAFE_VMSPLICE
                | Self::FL_DENY_TSC,
        )
    }

    fn ns_from_str(value: &str, unsafe_: bool) -> Result<Self, Errno> {
        let mut flags = Self::empty();
        for flag in value.split(',') {
            flags |= match flag.to_ascii_lowercase().as_str() {
                "mount" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_MOUNT,
                "uts" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_UTS,
                "ipc" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_IPC,
                "user" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_USER,
                "pid" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_PID,
                "net" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_NET,
                "cgroup" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_CGROUP,
                "time" if unsafe_ => Self::FL_ALLOW_UNSAFE_UNSHARE_TIME,
                "mount" => Self::FL_UNSHARE_MOUNT,
                "uts" => Self::FL_UNSHARE_UTS,
                "ipc" => Self::FL_UNSHARE_IPC,
                "user" => Self::FL_UNSHARE_USER,
                "pid" => Self::FL_UNSHARE_PID,
                "net" => Self::FL_UNSHARE_NET,
                "cgroup" => Self::FL_UNSHARE_CGROUP,
                "time" => Self::FL_UNSHARE_TIME,
                "all" if unsafe_ => {
                    Self::FL_ALLOW_UNSAFE_UNSHARE_MOUNT
                        | Self::FL_ALLOW_UNSAFE_UNSHARE_UTS
                        | Self::FL_ALLOW_UNSAFE_UNSHARE_IPC
                        | Self::FL_ALLOW_UNSAFE_UNSHARE_USER
                        | Self::FL_ALLOW_UNSAFE_UNSHARE_PID
                        | Self::FL_ALLOW_UNSAFE_UNSHARE_NET
                        | Self::FL_ALLOW_UNSAFE_UNSHARE_CGROUP
                        | Self::FL_ALLOW_UNSAFE_UNSHARE_TIME
                }
                "all" => {
                    Self::FL_UNSHARE_MOUNT
                        | Self::FL_UNSHARE_UTS
                        | Self::FL_UNSHARE_IPC
                        | Self::FL_UNSHARE_USER
                        | Self::FL_UNSHARE_PID
                        | Self::FL_UNSHARE_NET
                        | Self::FL_UNSHARE_CGROUP
                        | Self::FL_UNSHARE_TIME
                }
                _ => return Err(Errno::EINVAL),
            };
        }

        if !flags.is_empty() {
            Ok(flags)
        } else {
            Err(Errno::ENOENT)
        }
    }

    /// Get sync seccomp flag.
    pub fn sync_scmp(self) -> bool {
        self.contains(Self::FL_SYNC_SCMP)
    }

    /// Get map root flag.
    pub fn map_root(self) -> bool {
        self.contains(Self::FL_MAP_ROOT)
    }

    /// Get fake root flag.
    pub fn fake_root(self) -> bool {
        self.contains(Self::FL_FAKE_ROOT)
    }

    /// Return true if capabilities has to be inherited.
    ///
    /// Used by securebits setter to decide whether to set SECBIT_NOROOT.
    pub fn want_caps(self) -> bool {
        // Only capabilities that has to be inherited by the sandbox process
        // belong here, e.g. CAP_CHMOD, CAP_CHOWN, CAP_NET_BIND_SERVICE aren't
        // inherited by sandbox process so we don't test them here.
        self.intersects(
            Self::FL_ALLOW_SAFE_SETUID
                | Self::FL_ALLOW_SAFE_SETGID
                | Self::FL_ALLOW_UNSAFE_CAPS
                | Self::FL_ALLOW_UNSAFE_PTRACE
                | Self::FL_ALLOW_UNSAFE_SYSLOG
                | Self::FL_ALLOW_UNSAFE_TIME,
        )
    }

    /// Get the namespace settings of the Sandbox.
    pub fn namespaces(self) -> libc::c_int {
        let mut namespaces = 0;

        if self.contains(Self::FL_UNSHARE_MOUNT) {
            namespaces |= libc::CLONE_NEWNS;
        }
        if self.contains(Self::FL_UNSHARE_UTS) {
            namespaces |= libc::CLONE_NEWUTS;
        }
        if self.contains(Self::FL_UNSHARE_IPC) {
            namespaces |= libc::CLONE_NEWIPC;
        }
        if self.contains(Self::FL_UNSHARE_USER) {
            namespaces |= libc::CLONE_NEWUSER;
        }
        if self.contains(Self::FL_UNSHARE_PID) {
            namespaces |= libc::CLONE_NEWPID;
        }
        if self.contains(Self::FL_UNSHARE_NET) {
            namespaces |= libc::CLONE_NEWNET;
        }
        if self.contains(Self::FL_UNSHARE_CGROUP) {
            namespaces |= libc::CLONE_NEWCGROUP;
        }
        if self.contains(Self::FL_UNSHARE_TIME) {
            namespaces |= CLONE_NEWTIME.bits();
        }

        namespaces
    }

    /// Get the allowed namespaces of the Sandbox.
    pub(crate) fn allowed_namespaces(self) -> libc::c_int {
        let mut namespaces = 0;

        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_MOUNT) {
            namespaces |= libc::CLONE_NEWNS;
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_UTS) {
            namespaces |= libc::CLONE_NEWUTS;
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_IPC) {
            namespaces |= libc::CLONE_NEWIPC;
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_USER) {
            namespaces |= libc::CLONE_NEWUSER;
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_PID) {
            namespaces |= libc::CLONE_NEWPID;
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_NET) {
            namespaces |= libc::CLONE_NEWNET;
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_CGROUP) {
            namespaces |= libc::CLONE_NEWCGROUP;
        }
        if self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_TIME) {
            namespaces |= CLONE_NEWTIME.bits();
        }

        namespaces
    }

    /// Get the denied namespaces of the Sandbox.
    pub(crate) fn denied_namespaces(self) -> libc::c_int {
        let allowed = self.allowed_namespaces();
        NAMESPACE_FLAGS_ALL & !allowed
    }

    /// Get the value of the unshare-mount flag.
    pub fn unshare_mount(self) -> bool {
        self.contains(Self::FL_UNSHARE_MOUNT)
    }

    /// Get the value of the unshare-uts flag.
    pub fn unshare_uts(self) -> bool {
        self.contains(Self::FL_UNSHARE_UTS)
    }

    /// Get the value of the unshare-ipc flag.
    pub fn unshare_ipc(self) -> bool {
        self.contains(Self::FL_UNSHARE_IPC)
    }

    /// Get the value of the unshare-user flag.
    pub fn unshare_user(self) -> bool {
        self.contains(Self::FL_UNSHARE_USER)
    }

    /// Get the value of the unshare-pid flag.
    pub fn unshare_pid(self) -> bool {
        self.contains(Self::FL_UNSHARE_PID)
    }

    /// Get the value of the unshare-net flag.
    pub fn unshare_net(self) -> bool {
        self.contains(Self::FL_UNSHARE_NET)
    }

    /// Get the value of the unshare-cgroup flag.
    pub fn unshare_cgroup(self) -> bool {
        self.contains(Self::FL_UNSHARE_CGROUP)
    }

    /// Get the value of the unshare-time flag.
    pub fn unshare_time(self) -> bool {
        self.contains(Self::FL_UNSHARE_TIME)
    }

    /// Get the value of the allow-unsafe-mount flag.
    pub fn allow_unsafe_unshare_mount(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_MOUNT)
    }

    /// Get the value of the allow-unsafe-uts flag.
    pub fn allow_unsafe_unshare_uts(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_UTS)
    }

    /// Get the value of the allow-unsafe-ipc flag.
    pub fn allow_unsafe_unshare_ipc(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_IPC)
    }

    /// Get the value of the allow-unsafe-user flag.
    pub fn allow_unsafe_unshare_user(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_USER)
    }

    /// Get the value of the allow-unsafe-pid flag.
    pub fn allow_unsafe_unshare_pid(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_PID)
    }

    /// Get the value of the allow-unsafe-net flag.
    pub fn allow_unsafe_unshare_net(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_NET)
    }

    /// Get the value of the allow-unsafe-cgroup flag.
    pub fn allow_unsafe_unshare_cgroup(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_CGROUP)
    }

    /// Get the value of the allow-unsafe-time flag.
    pub fn allow_unsafe_unshare_time(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNSHARE_TIME)
    }

    /// Returns true if exit wait flag is set.
    pub fn exit_wait_all(self) -> bool {
        self.contains(Self::FL_EXIT_WAIT_ALL)
    }

    /// Returns true if tpe negate flag is set.
    pub fn tpe_negate(self) -> bool {
        self.contains(Self::FL_TPE_NEGATE)
    }

    /// Returns true if tpe root owned flag is set.
    pub fn tpe_root_owned(self) -> bool {
        self.contains(Self::FL_TPE_ROOT_OWNED)
    }

    /// Returns true if tpe user owned flag is set.
    pub fn tpe_user_owned(self) -> bool {
        self.contains(Self::FL_TPE_USER_OWNED)
    }

    /// Returns true if tpe root mount flag is set.
    pub fn tpe_root_mount(self) -> bool {
        self.contains(Self::FL_TPE_ROOT_MOUNT)
    }

    /// Returns true if deny dotdot flag is set.
    pub fn deny_dotdot(self) -> bool {
        self.contains(Self::FL_DENY_DOTDOT)
    }

    /// Returns true if deny exec elf32 flag is set.
    pub fn deny_exec_elf32(self) -> bool {
        self.contains(Self::FL_DENY_EXEC_ELF32)
    }

    /// Returns true if deny exec elf-dynamic flag is set.
    pub fn deny_exec_elf_dynamic(self) -> bool {
        self.contains(Self::FL_DENY_EXEC_ELF_DYNAMIC)
    }

    /// Returns true if deny exec elf-static flag is set.
    pub fn deny_exec_elf_static(self) -> bool {
        self.contains(Self::FL_DENY_EXEC_ELF_STATIC)
    }

    /// Returns true if deny exec script flag is set.
    pub fn deny_exec_script(self) -> bool {
        self.contains(Self::FL_DENY_EXEC_SCRIPT)
    }

    /// Returns true if reading the timestamp counter is denied.
    pub fn deny_tsc(self) -> bool {
        self.contains(Self::FL_DENY_TSC)
    }

    /// Returns true if access to vDSO should be denied.
    pub fn deny_vdso(self) -> bool {
        self.contains(Self::FL_DENY_VDSO)
    }

    /// Returns true if force-cloexec flag is set.
    pub fn force_cloexec(self) -> bool {
        self.contains(Self::FL_FORCE_CLOEXEC)
    }

    /// Returns true if force-rand-fd flag is set.
    pub fn force_rand_fd(self) -> bool {
        self.contains(Self::FL_FORCE_RAND_FD)
    }

    /// Returns true if force-ro-open flag is set.
    pub fn force_ro_open(self) -> bool {
        self.contains(Self::FL_FORCE_RO_OPEN)
    }

    /// Returns true if force-local-net flag is set.
    pub fn force_local_net(self) -> bool {
        self.contains(Self::FL_FORCE_LOCAL_NET)
    }

    /// Returns true if RESOLVE_NO_SYMLINKS should be forced at open(2) boundary.
    pub fn force_no_symlinks(self) -> bool {
        self.contains(Self::FL_FORCE_NO_SYMLINKS)
    }

    /// Returns true if RESOLVE_NO_MAGICLINKS should be forced at open(2) boundary.
    pub fn force_no_magiclinks(self) -> bool {
        self.contains(Self::FL_FORCE_NO_MAGICLINKS)
    }

    /// Returns true if RESOLVE_NO_XDEV should be forced at open(2) boundary.
    pub fn force_no_xdev(self) -> bool {
        self.contains(Self::FL_FORCE_NO_XDEV)
    }

    /// Returns true if CAP_NET_BIND_SERVICE capability is retained.
    pub fn allow_unsafe_bind(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_BIND)
    }

    /// Returns true if CAP_CHOWN capability is retained.
    pub fn allow_unsafe_chown(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_CHOWN)
    }

    /// Returns true if chroot(2) is no-op.
    pub fn allow_unsafe_chroot(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_CHROOT)
    }

    /// Returns true if pivot_root(2) is no-op.
    pub fn allow_unsafe_pivot_root(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PIVOT_ROOT)
    }

    /// Allow system calls for CPU emulation functionality.
    pub fn allow_unsafe_cpu(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_CPU)
    }

    /// Returns true if core dumps are allowed for the Syd process.
    pub fn allow_unsafe_dumpable(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_DUMPABLE)
    }

    /// Returns true if any address should not be rewritten for bind/connect.
    pub fn allow_unsafe_any_addr(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_ANY_ADDR)
    }

    /// Returns true if ld.so(8) indirect-execution is allowed.
    pub fn allow_unsafe_exec_ldso(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_LDSO)
    }

    /// Returns true if setting AT_SECURE at PTRACE_EVENT_EXEC boundary is disabled.
    pub fn allow_unsafe_exec_libc(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_LIBC)
    }

    /// Returns true if unsafe exec memory flag is set.
    pub fn allow_unsafe_exec_memory(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_MEMORY)
    }

    /// Returns true if execution of non-PIE binaries is allowed.
    pub fn allow_unsafe_exec_nopie(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_NOPIE)
    }

    /// Returns true if execve NULL arguments mitigation is disabled.
    pub fn allow_unsafe_exec_null(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_NULL)
    }

    /// Returns true if execution of ELF binaries with executable stack is allowed.
    pub fn allow_unsafe_exec_stack(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_STACK)
    }

    /// Returns true if setting SECBIT_EXEC_RESTRICT_FILE_LOCKED should be disabled.
    ///
    /// No-op on Linux<6.14.
    pub fn allow_unsafe_exec_script(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_SCRIPT)
    }

    /// Returns true if setting SECBIT_EXEC_DENY_INTERACTIVE_LOCKED should be disabled.
    ///
    /// No-op on Linux<6.14.
    pub fn allow_unsafe_exec_interactive(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_INTERACTIVE)
    }

    /// Returns true if unsafe speculative execution is allowed.
    pub fn allow_unsafe_exec_speculative(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EXEC_SPECULATIVE)
    }

    /// Returns true if access to the Kernel keyring is allowed.
    pub fn allow_unsafe_keyring(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_KEYRING)
    }

    /// Returns true if system calls used for memory protection keys are allowed.
    pub fn allow_unsafe_pkey(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PKEY)
    }

    /// Returns true if internal procfs(5) should NOT be mounted with subset=pid.
    pub fn allow_unsafe_proc_files(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PROC_FILES)
    }

    /// Returns true if unsafe capabilities flag is set.
    pub fn allow_unsafe_caps(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_CAPS)
    }

    /// Returns true if SECBIT_KEEP_CAPS should be retained,
    /// and SECBIT_NO_SETUID_FIXUP should NOT be set.
    pub fn allow_unsafe_cap_fixup(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_CAP_FIXUP)
    }

    /// Returns true if unsafe environment flag is set.
    pub fn allow_unsafe_env(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_ENV)
    }

    /// Returns true if successful bind addresses should be allowed for subsequent connect calls.
    pub fn allow_safe_bind(self) -> bool {
        self.contains(Self::FL_ALLOW_SAFE_BIND)
    }

    /// Returns true if access to the Linux kernel crypto API is allowed.
    pub fn allow_safe_kcapi(self) -> bool {
        self.contains(Self::FL_ALLOW_SAFE_KCAPI)
    }

    /// Returns true if CAP_SETUID capability is retained.
    pub fn allow_safe_setuid(self) -> bool {
        self.contains(Self::FL_ALLOW_SAFE_SETUID)
    }

    /// Returns true if CAP_SETGID capability is retained.
    pub fn allow_safe_setgid(self) -> bool {
        self.contains(Self::FL_ALLOW_SAFE_SETGID)
    }

    /// Returns true whether sandbox lock is not enforced for syslog(2) emulation.
    pub fn allow_safe_syslog(self) -> bool {
        self.contains(Self::FL_ALLOW_SAFE_SYSLOG)
    }

    /// Returns true if SROP mitigations for {rt_}sigreturn should be disabled.
    pub fn allow_unsafe_sigreturn(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SIGRETURN)
    }

    /// Returns true if unsupported socket families should be allowed.
    pub fn allow_unsupp_socket(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSUPP_SOCKET)
    }

    /// Returns true if raw sockets should be allowed.
    pub fn allow_unsafe_socket(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SOCKET)
    }

    /// Returns true if unsafe syslog should be allowed.
    pub fn allow_unsafe_syslog(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SYSLOG)
    }

    /// Returns true if unsafe cachestat and mincore calls are allowed.
    pub fn allow_unsafe_page_cache(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PAGE_CACHE)
    }

    /// Returns true if unsafe nice calls are allowed.
    pub fn allow_unsafe_nice(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_NICE)
    }

    /// Returns true if unsafe prctl calls are allowed.
    pub fn allow_unsafe_prctl(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PRCTL)
    }

    /// Returns true if unsafe prlimit calls are allowed.
    pub fn allow_unsafe_prlimit(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PRLIMIT)
    }

    /// Returns true if unsafe deprecated syscalls are allowed.
    pub fn allow_unsafe_deprecated(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_DEPRECATED)
    }

    /// Returns true if unsafe seccomp-bpf filters are allowed.
    pub fn allow_unsafe_cbpf(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_CBPF)
    }

    /// Returns true if unsafe EBPF programs are allowed.
    pub fn allow_unsafe_ebpf(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_EBPF)
    }

    /// Returns true if kernel pointers in syscall arguments are allowed.
    pub fn allow_unsafe_kptr(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_KPTR)
    }

    /// Returns true if madvise(2) system call should NOT be hardened.
    pub fn allow_unsafe_madvise(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MADVISE)
    }

    /// Returns true if mbind(2) system call is allowed.
    pub fn allow_unsafe_mbind(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MBIND)
    }

    /// Returns true if enforcing syscall argument cookies should be disabled.
    pub fn allow_unsafe_nocookie(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_NOCOOKIE)
    }

    /// Returns true if memory sealing of sandbox policy should be disabled.
    pub fn allow_unsafe_nomseal(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_NOMSEAL)
    }

    /// Returns true if XOM mapping of Syd's executable regions should be disabled.
    pub fn allow_unsafe_noxom(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_NOXOM)
    }

    /// Returns true if unsafe MSG_OOB flag is allowed.
    pub fn allow_unsafe_oob(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_OOB)
    }

    /// Returns true if unsafe perf calls are allowed.
    pub fn allow_unsafe_perf(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PERF)
    }

    /// Returns true if unsafe pipe2() calls with O_NOTIFICATION_PIPE are allowed.
    pub fn allow_unsafe_pipe(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PIPE)
    }

    /// Returns true if unsafe setsockopt(2) calls are allowed.
    pub fn allow_unsafe_setsockopt(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SETSOCKOPT)
    }

    /// Returns true if unsafe ptrace calls are allowed.
    pub fn allow_unsafe_ptrace(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PTRACE)
    }

    /// Returns true if unsafe adjtime calls are allowed.
    /// This also results in keeping the CAP_SYS_TIME capability.
    pub fn allow_unsafe_time(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_TIME)
    }

    /// Returns true if CONTINUE should be applied on O_PATH file
    /// descriptors rather than turning them into O_RDONLY.
    pub fn allow_unsafe_open_path(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_OPEN_PATH)
    }

    /// Returns true if CONTINUE should be applied on AMD KFD chardevs.
    pub fn allow_unsafe_open_kfd(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_OPEN_KFD)
    }

    /// Returns true if block device creation is allowed.
    pub fn allow_unsafe_mkbdev(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MKBDEV)
    }

    /// Returns true if character device creation is allowed.
    pub fn allow_unsafe_mkcdev(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MKCDEV)
    }

    /// Returns true if block device stat(2)s are allowed.
    pub fn allow_unsafe_stat_bdev(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_STAT_BDEV)
    }

    /// Returns true if character device stat(2)s are allowed.
    pub fn allow_unsafe_stat_cdev(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_STAT_CDEV)
    }

    /// Returns true if block device notifications are allowed.
    pub fn allow_unsafe_notify_bdev(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_NOTIFY_BDEV)
    }

    /// Returns true if character device notifications are allowed.
    pub fn allow_unsafe_notify_cdev(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_NOTIFY_CDEV)
    }

    /// Returns true if unsafe file creation should be allowed.
    /// This mitigation is inspired by CONFIG_GRKERNSEC_FIFO,
    /// and it's similar to protected_{fifos,regular} of proc_sys_fs(5).
    pub fn allow_unsafe_create(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_CREATE)
    }

    /// Returns true if unsafe hardlinks should be allowed.
    /// This mitigation is inspired from CONFIG_GRKERNSEC_LINK.
    pub fn allow_unsafe_hardlinks(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_HARDLINKS)
    }

    /// Returns true to allow symbolic links which reside in sticky-bit-set,
    /// group-writable, or other-writable directories to be followed.
    /// This mitigation is inspired from CONFIG_GRKERNSEC_LINK.
    pub fn allow_unsafe_symlinks(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SYMLINKS)
    }

    /// Returns true if proc magic symbolic links should be followed
    /// even when per-process directory pid differs from caller pid.
    pub fn allow_unsafe_magiclinks(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MAGICLINKS)
    }

    /// Returns true if machine-id(5) should not be autogenerated per-Syd instance.
    pub fn allow_unsafe_machine_id(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MACHINE_ID)
    }

    /// Returns true if proc_pid_status(5) should not be filtered.
    pub fn allow_unsafe_proc_pid_status(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PROC_PID_STATUS)
    }

    /// Returns true if filenames with control characters are allowed.
    pub fn allow_unsafe_filename(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_FILENAME)
    }

    /// Returns true if unsafe io_uring calls are allowed.
    pub fn allow_unsafe_iouring(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_IOURING)
    }

    /// Returns true if mq_open(3) syscalls are allowed.
    pub fn allow_unsafe_msgqueue(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MSGQUEUE)
    }

    /// Returns true if shared memory syscalls are allowed.
    pub fn allow_unsafe_shm(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SHM)
    }

    /// Returns true if unsafe permissions in mq_open(3) syscalls are allowed.
    pub fn allow_unsafe_perm_msgqueue(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PERM_MSGQUEUE)
    }

    /// Returns true if unsafe permissions in shared memory syscalls are allowed.
    pub fn allow_unsafe_perm_shm(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PERM_SHM)
    }

    /// Returns true if unsafe rseq(2) syscall is allowed.
    pub fn allow_unsafe_rseq(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_RSEQ)
    }

    /// Returns true if unsafe sync(2) and syncfs(2) calls are allowed.
    pub fn allow_unsafe_sync(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SYNC)
    }

    /// Returns true if unsafe sysinfo(2) is allowed.
    pub fn allow_unsafe_sysinfo(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_SYSINFO)
    }

    /// Returns true if unsafe uname(2) is allowed.
    pub fn allow_unsafe_uname(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_UNAME)
    }

    /// Returns true if unsafe vmsplice(2) is allowed.
    pub fn allow_unsafe_vmsplice(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_VMSPLICE)
    }

    /// Returns true if secret memfds and executable memfds are allowed.
    pub fn allow_unsafe_memfd(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_MEMFD)
    }

    /// Returns true if xattr restrictions for user.syd.* and security.* should be lifted.
    pub fn allow_unsafe_xattr(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_XATTR)
    }

    /// Returns true if personality(2) system call is unrestricted.
    pub fn allow_unsafe_personality(self) -> bool {
        self.contains(Self::FL_ALLOW_UNSAFE_PERSONALITY)
    }
}

#[derive(Debug)]
enum AddrParseError {
    Addr(std::net::AddrParseError),
    Cidr(ipnet::AddrParseError),
    Plen(ipnet::PrefixLenError),
}

impl std::error::Error for AddrParseError {}

impl fmt::Display for AddrParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Self::Addr(ref e) => write!(f, "AddrParseError: {e}"),
            Self::Cidr(ref e) => write!(f, "CidrParseError: {e}"),
            Self::Plen(ref e) => write!(f, "PrefixLenError: {e}"),
        }
    }
}

impl From<std::net::AddrParseError> for AddrParseError {
    fn from(err: std::net::AddrParseError) -> Self {
        Self::Addr(err)
    }
}

impl From<ipnet::AddrParseError> for AddrParseError {
    fn from(err: ipnet::AddrParseError) -> Self {
        Self::Cidr(err)
    }
}

impl From<ipnet::PrefixLenError> for AddrParseError {
    fn from(err: ipnet::PrefixLenError) -> Self {
        Self::Plen(err)
    }
}

fn parse_ipnet(ip: &str) -> Result<IpNet, AddrParseError> {
    if memchr::memchr(b'/', ip.as_bytes()).is_some() {
        Ok(ip.parse::<IpNet>()?)
    } else if memchr::memchr(b':', ip.as_bytes()).is_some() {
        Ok(IpNet::from(Ipv6Net::new(ip.parse::<Ipv6Addr>()?, 128)?))
    } else {
        Ok(IpNet::from(Ipv4Net::new(ip.parse::<Ipv4Addr>()?, 32)?))
    }
}

/// Represents a network address pattern
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct AddressPattern {
    pub(crate) addr: IpNet,
    pub(crate) port: Option<PortRange>,
}

impl fmt::Display for AddressPattern {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self.port {
            None => write!(f, "{}", self.addr),
            Some(ports) if ports.start() == ports.end() => {
                write!(f, "{}!{}", self.addr, ports.start())
            }
            Some(ports) => write!(f, "{}!{}-{}", self.addr, ports.start(), ports.end()),
        }
    }
}

impl Serialize for AddressPattern {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(2))?;
        map.serialize_entry("addr", &format!("{}", self.addr))?;
        match &self.port {
            None => {}
            Some(ports) if ports.start() == ports.end() => {
                map.serialize_entry("port", &ports.start())?
            }
            Some(ports) => map.serialize_entry("port", &[ports.start(), ports.end()])?,
        };
        map.end()
    }
}

impl FromStr for AddressPattern {
    type Err = Errno;

    fn from_str(pat: &str) -> Result<Self, Self::Err> {
        let mut split = pat.splitn(2, ['!', '@']);
        if let (Some(addr), Some(port)) = (split.next(), split.next()) {
            let mut split = port.splitn(2, '-');
            if let Some(port0) = split.next() {
                if let Ok(port0) = port0.parse::<u16>() {
                    let port1 = if let Some(port1) = split.next() {
                        port1.parse::<u16>()
                    } else {
                        Ok(port0)
                    };
                    if let Ok(port1) = port1 {
                        if let Ok(addr) = parse_ipnet(addr) {
                            let port = if port0 == PORT_MIN && port1 == PORT_MAX {
                                None
                            } else {
                                Some(port0..=port1)
                            };
                            return Ok(Self { addr, port });
                        }
                    }
                }
            }
        }

        Err(Errno::EINVAL)
    }
}

/// Represents a rule action.
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum Action {
    /// Allow system call.
    Allow,
    /// Allow system call and warn.
    Warn,
    /// Deny system call silently.
    Filter,
    /// Deny system call and warn, this is the default.
    #[default]
    Deny,
    /// Deny system call, warn and panic the current Syd thread.
    Panic,
    /// Deny system call, warn and stop offending process.
    Stop,
    /// Deny system call, warn and abort offending process.
    Abort,
    /// Deny system call, warn and kill offending process.
    Kill,
    /// Warn, and exit Syd immediately with deny errno as exit value.
    Exit,
}

// List of valid actions.
//
// This array must be sorted because it's binary searched.
// XPath is used for efficient string lookups with `memchr`.
pub(crate) const ACTION_STR: &[&XPath] = &[
    XPath::from_bytes(b"abort"),
    XPath::from_bytes(b"allow"),
    XPath::from_bytes(b"deny"),
    XPath::from_bytes(b"exit"),
    XPath::from_bytes(b"filter"),
    XPath::from_bytes(b"kill"),
    XPath::from_bytes(b"panic"),
    XPath::from_bytes(b"stop"),
    XPath::from_bytes(b"warn"),
];

pub(crate) const ACTION_VAL: &[Action] = &[
    Action::Abort,
    Action::Allow,
    Action::Deny,
    Action::Exit,
    Action::Filter,
    Action::Kill,
    Action::Panic,
    Action::Stop,
    Action::Warn,
];

impl FromStr for Action {
    type Err = Errno;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        if let Ok(idx) = ACTION_STR.binary_search(&XPath::from_bytes(value.as_bytes())) {
            Ok(ACTION_VAL[idx])
        } else {
            Err(Errno::EINVAL)
        }
    }
}

impl fmt::Display for Action {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Self::Allow => write!(f, "allow"),
            Self::Warn => write!(f, "warn"),
            Self::Filter => write!(f, "filter"),
            Self::Deny => write!(f, "deny"),
            Self::Panic => write!(f, "panic"),
            Self::Stop => write!(f, "stop"),
            Self::Abort => write!(f, "abort"),
            Self::Kill => write!(f, "kill"),
            Self::Exit => write!(f, "exit"),
        }
    }
}

impl Serialize for Action {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string())
    }
}

impl Action {
    /// Return true if Action is allowing.
    pub fn is_allowing(self) -> bool {
        matches!(self, Self::Allow | Self::Warn)
    }

    /// Return true if Action is denying.
    pub fn is_denying(self) -> bool {
        !self.is_allowing()
    }

    /// Return true if Action is signaling.
    pub fn is_signaling(self) -> bool {
        matches!(self, Self::Stop | Self::Abort | Self::Kill)
    }

    /// Return signal related to the action if any.
    pub fn signal(self) -> Option<Signal> {
        match self {
            Self::Stop => Some(Signal::SIGSTOP),
            Self::Abort => Some(Signal::SIGABRT),
            Self::Kill => Some(Signal::SIGKILL),
            _ => None,
        }
    }
}

/// Represents a network address sandboxing rule.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct CidrRule {
    pub(crate) act: Action,
    pub(crate) cap: Capability,
    pub(crate) pat: AddressPattern,
}

/// Represents a glob sandboxing rule.
#[derive(Debug)]
pub struct GlobRule {
    act: Action,
    cap: Capability,
    pat: XPathBuf,
}

/// Represents a simple sandboxing rule.
#[derive(Debug)]
pub struct Rule(String);

impl CidrRule {
    /// Create a network address sandboxing rule.
    pub fn new(act: Action, cap: Capability, addr: IpNet, port: PortRange) -> Self {
        let port = if *port.start() == PORT_MIN && *port.end() == PORT_MAX {
            None
        } else {
            Some(port)
        };
        Self {
            act,
            cap,
            pat: AddressPattern { addr, port },
        }
    }
}

impl fmt::Display for CidrRule {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Action: {}, Capability: {}, Pattern: {}",
            self.act, self.cap, self.pat
        )
    }
}

impl fmt::Display for GlobRule {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Action: {}, Capability: {}, Pattern: `{}'",
            self.act, self.cap, self.pat
        )
    }
}

impl fmt::Display for Rule {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Pattern: {}", self.0)
    }
}

impl Serialize for CidrRule {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("cidr", 3)?;
        state.serialize_field("act", &self.act)?;
        state.serialize_field("cap", &self.cap)?;
        state.serialize_field("pat", &self.pat)?;
        state.end()
    }
}

impl Serialize for GlobRule {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("glob", 3)?;
        state.serialize_field("act", &self.act)?;
        state.serialize_field("cap", &self.cap)?;
        state.serialize_field("pat", &self.pat)?;
        state.end()
    }
}

impl Serialize for Rule {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state = serializer.serialize_struct("rule", 1)?;
        state.serialize_field("pat", &self.0)?;
        state.end()
    }
}

// Once the sandbox is locked, there is no going back,
// to efficiently check for that without having to lock
// the sandbox, we use this global Once.
// Lock state is LockState::Set when it is set.
// Otherwise it is one of Exec or Off.
static LOCKED: Once = Once::new();

/// Represents the state of the magic command lock.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LockState {
    /// Lock is off, sandbox commands are allowed.
    Off,
    /// Sandbox commands are only allowed to the syd execve child.
    Exec,
    /// Sandbox commands are only allowed via the IPC socket.
    Ipc,
    /// Sandbox commands are only allowed for read-only access.
    Read,
    /// Lock is set, sandbox commands are not allowed.
    Set,
}

impl LockState {
    fn is_locked(self) -> bool {
        matches!(self, Self::Read | Self::Set)
    }
}

impl fmt::Display for LockState {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Self::Ipc => "Ipc",
                Self::Exec => "Exec",
                Self::Read => "Read",
                Self::Set => "Set",
                Self::Off => "Off",
            }
        )
    }
}

impl Serialize for LockState {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_str(&self.to_string().to_ascii_lowercase())
    }
}

type AclRule = (XPathBuf, MatchMethod, Action);
type ArrRule = (XPathBuf, MatchMethod);
type Acl = SealableVecDeque<AclRule>;
type Arr = SealableVecDeque<ArrRule>;

type FsAclRule = (FsType, Action);
type FsArrRule = FsType;
type FsAcl = SealableVecDeque<FsAclRule>;
type FsArr = SealableVecDeque<FsArrRule>;

pub(crate) type RawIoctlMap = SydHashMap<ScmpArch, Vec<u64>>;

/// Mask rule, see "mask" command in _syd_(2).
#[derive(Debug, Clone)]
pub struct Mask {
    /// Mask regardless of file type: Defaults to /dev/null.
    pub mask_all: Option<XPathBuf>,

    /// Mask override for directories.
    pub mask_dir: Option<XPathBuf>,
}
#[derive(Debug, Clone)]
struct MaskRule {
    // Match method (literal, glob etc.)
    meth: MatchMethod,
    // Mask is (maybe_mask_file, maybe_mask_directory)
    // Defaults to /dev/null. mask_dir defaults to mask_file.
    mask: Mask,
}
type MaskArr = SealableVecDeque<(XPathBuf, MaskRule)>;

/// Sandbox
pub struct Sandbox {
    /// Sandbox options represented using a set of `Flag` flags.
    pub flags: Sealable<Flags>,

    /// Sandbox state represented using a set of `Capability` flags.
    pub state: Sealable<Capability>,

    /// State of the magic lock.
    /// SAFETY: If None, set to LockState::Set the moment cpid is set.
    pub(crate) lock: Option<LockState>,

    /// Log seccomp request information with the access violation.
    pub verbose: u8,

    // This is true if we're running as `syd-oci' and not `syd'.
    // This is used in argument validation.
    oci: bool,

    /// Path to the IPC socket, prefix with `@' for abstract socket.
    pub(crate) ipc: Option<XPathBuf>,

    /// Uid for IPC authentication.
    pub(crate) ipc_uid: Option<Uid>,

    /// Gid for IPC authentication.
    pub(crate) ipc_gid: Option<Gid>,

    /// State of chroot.
    chroot: bool,

    /// Process ID of the syd execve child.
    /// SAFETY: This is 0 before the sandbox process has been executed.
    cpid: libc::pid_t,

    /// PID file descriptor of the syd execve child.
    pub(crate) fpid: RawFd,

    /// Change root to this directory on startup.
    ///
    /// Must be an absolute path.
    /// Special keyword `tmp` is supported to create a temporary new-root dir.
    pub root: Option<XPathBuf>,

    /// Hostname in UTS namespace.
    pub hostname: Option<CString>,

    /// Domainname in UTS namespace.
    pub domainname: Option<CString>,

    /// Version in uname(2) boundary.
    pub version: Option<CString>,

    /// Timestamp offset in seconds for BOOTTIME clock in Time namespace.
    pub boottime: Option<i64>,
    /// Timestamp offset in seconds for MONOTONIC clock in Time namespace.
    pub monotime: Option<i64>,

    /// Per-process memory limit in bytes for memory sandboxing.
    pub mem_max: u64,

    /// Per-process virtual memory limit in bytes for memory sandboxing.
    pub mem_vm_max: u64,

    /// Pid limit for PID sandboxing.
    pub pid_max: u64,

    /// Resource limit RLIMIT_AS in bytes
    pub rlimit_as: Option<rlim_t>,

    /// Resource limit RLIMIT_CORE in bytes
    pub rlimit_core: Option<rlim_t>,

    /// Resource limit RLIMIT_CPU in seconds
    pub rlimit_cpu: Option<rlim_t>,

    /// Resource limit RLIMIT_DATA in bytes
    pub rlimit_data: Option<rlim_t>,

    /// Resource limit RLIMIT_FSIZE in bytes
    pub rlimit_fsize: Option<rlim_t>,

    /// Resource limit RLIMIT_MEMLOCK in bytes
    pub rlimit_memlock: Option<rlim_t>,

    /// Resource limit RLIMIT_MSGQUEUE in bytes
    pub rlimit_msgqueue: Option<rlim_t>,

    /// Resource limit RLIMIT_NICE in range -20..=20
    ///
    /// The useful range for this limit is from 0 (corresponding to a
    /// nice value of 20) to 40 (corresponding to a nice value of -20).
    /// Syd enforces the range [-20..=20] and handles the translation.
    pub rlimit_nice: Option<rlim_t>,

    /// Resource limit RLIMIT_NOFILE
    pub rlimit_nofile: Option<rlim_t>,

    /// Resource limit RLIMIT_NPROC
    pub rlimit_nproc: Option<rlim_t>,

    /// Resource limit RLIMIT_RTPRIO
    pub rlimit_rtprio: Option<rlim_t>,

    /// Resource limit RLIMIT_RTTIME in microseconds
    pub rlimit_rttime: Option<rlim_t>,

    /// Resource limit RLIMIT_SIGPENDING
    pub rlimit_sigpending: Option<rlim_t>,

    /// Resource limit RLIMIT_STACK in bytes
    pub rlimit_stack: Option<rlim_t>,

    /// Umask mode to force, None to disable.
    pub umask: Option<Mode>,

    /// Sandbox timeout, None to disable.
    pub tmout: Option<Duration>,

    /// Set of environment variables to pass-through.
    pub pass_env: Option<SydHashSet<OsString>>,

    /// Proxy internal port (defaults to 9050).
    pub proxy_port: u16,

    /// Proxy internal address (defaults to 127.0.0.1).
    pub proxy_addr: IpAddr,

    /// Proxy external port (defaults to 9050).
    pub proxy_ext_port: u16,

    /// Proxy external address (defaults to 127.0.0.1).
    pub proxy_ext_addr: IpAddr,

    /// Proxy external UNIX socket (has precedence over proxy_ext_addr).
    pub proxy_ext_unix: Option<XPathBuf>,

    /// Default actions for sandboxing.
    /// We keep this in a vector for ease of sealing.
    default_act: SealableVec<Action>,

    /// Ip blocklists for Ipv4 and Ipv6.
    net_block_lst: (IpRange<Ipv4Net>, IpRange<Ipv6Net>),

    // Set of allowlisted or denylisted ioctl(2) requests.
    // Key is a pair of request number and architecture code.
    // true: deny, false: allow.
    ioctl_set: SealableSydHashMap<(u64, u32), bool>,

    // TPE GID
    tpe_gid: Option<Gid>,

    // Vector of safe {U,G}ID transitions.
    // source_{u,g}id->target_{u,g}id
    pub(crate) transit_uids: Vec<(Uid, Uid)>,
    pub(crate) transit_gids: Vec<(Gid, Gid)>,

    // PTY row size.
    pty_ws_x: Option<libc::c_ushort>,
    // PTY column size.
    pty_ws_y: Option<libc::c_ushort>,

    // SegvGuard entry expiry timeout.
    segvguard_expiry: Duration,

    // SegvGuard entry suspension timeout.
    segvguard_suspension: Duration,

    // SegvGuard max number of crashes before suspension.
    pub(crate) segvguard_maxcrashes: u8,

    // SegvGuard Lists: map is used for expiry, set is used for suspension.
    segvguard_map_expiry: ExpiringMap<XPathBuf, u8>,
    segvguard_map_suspension: ExpiringMap<XPathBuf, ()>,

    // Crypt Sandboxing.
    pub(crate) crypt_id: Option<Secret>,
    pub(crate) crypt_tmp: Option<RawFd>,

    // Integrity force check map.
    force_map: SealableSydHashMap<XPathBuf, (Action, Vec<u8>)>,

    // List of bind mounts.
    bind_mounts: Option<Vec<BindMount>>,

    // List of allowlisted Netlink families.
    // TODO: Part of access policy, must be sealed on lock.
    pub(crate) netlink_families: NetlinkFamily,

    // Timeout for config expansion.
    // Setting to `Duration::ZERO` switches
    // from wordexp(3) to shellexpand (default).
    config_expand_timeout: Duration,

    // List of network address sandboxing rules.
    //
    // When trace/allow_safe_bind is set, we access
    // this VecDeque directly to be efficient at
    // syscall boundary by avoiding parsing.
    pub(crate) cidr_rules: SealableVecDeque<CidrRule>,

    // Landlock rules to be applied if Lock sandboxing is on.
    lock_rules: Option<LandlockPolicy>,

    // Access control lists and filters:
    fs_acl: FsAcl,
    fs_arr: FsArr,

    walk_acl: Acl,
    walk_arr: Arr,

    stat_acl: Acl,
    stat_arr: Arr,

    read_acl: Acl,
    read_arr: Arr,

    write_acl: Acl,
    write_arr: Arr,

    exec_acl: Acl,
    exec_arr: Arr,

    create_acl: Acl,
    create_arr: Arr,

    delete_acl: Acl,
    delete_arr: Arr,

    rename_acl: Acl,
    rename_arr: Arr,

    symlink_acl: Acl,
    symlink_arr: Arr,

    truncate_acl: Acl,
    truncate_arr: Arr,

    chdir_acl: Acl,
    chdir_arr: Arr,

    readdir_acl: Acl,
    readdir_arr: Arr,

    mkdir_acl: Acl,
    mkdir_arr: Arr,

    rmdir_acl: Acl,
    rmdir_arr: Arr,

    chown_acl: Acl,
    chown_arr: Arr,

    chgrp_acl: Acl,
    chgrp_arr: Arr,

    chmod_acl: Acl,
    chmod_arr: Arr,

    chattr_acl: Acl,
    chattr_arr: Arr,

    chroot_acl: Acl,
    chroot_arr: Arr,

    utime_acl: Acl,
    utime_arr: Arr,

    mkbdev_acl: Acl,
    mkbdev_arr: Arr,

    mkcdev_acl: Acl,
    mkcdev_arr: Arr,

    mkfifo_acl: Acl,
    mkfifo_arr: Arr,

    mktemp_acl: Acl,
    mktemp_arr: Arr,

    net_bind_acl: Acl,
    net_bind_arr: Arr,

    net_conn_acl: Acl,
    net_conn_arr: Arr,

    net_sendfd_acl: Acl,
    net_sendfd_arr: Arr,

    // ACL for Append-only.
    append_acl: Arr,

    // ACL for Crypt sandboxing.
    crypt_acl: Arr,

    // ACL for Path masking.
    mask_acl: MaskArr,
}

/// Sandbox Lock types.
#[derive(Debug)]
pub enum SandboxLock {
    /// Read Lock
    Read,
    /// Write lock
    Write,
}

/// Sandbox guard to use it practically under a read/write lock.
#[derive(Debug)]
pub enum SandboxGuard<'a> {
    /// Sandbox locked for read
    Read(RwLockReadGuard<'a, Sandbox>),
    /// Sandbox locked for write
    Write(RwLockWriteGuard<'a, Sandbox>),
}

impl Default for Flags {
    fn default() -> Self {
        let is_mips = cfg!(any(
            target_arch = "mips",
            target_arch = "mips32r6",
            target_arch = "mips64",
            target_arch = "mips64r6",
        ));
        let is_ppc = cfg!(any(target_arch = "powerpc", target_arch = "powerpc64",));
        let is_riscv = cfg!(target_arch = "riscv64");
        let is_loong = cfg!(target_arch = "loongarch64");

        let mut flags = Self::empty();

        // MIPS requires executable stack.
        if is_mips {
            flags.insert(Self::FL_ALLOW_UNSAFE_EXEC_MEMORY | Self::FL_ALLOW_UNSAFE_EXEC_STACK);
        }

        // MIPS, PPC, RISCV, and LOONG don't support XOM.
        if is_mips || is_ppc || is_riscv || is_loong {
            flags.insert(Self::FL_ALLOW_UNSAFE_NOXOM);
        }

        // As of version 3.37.6, we enable trace/sync_seccomp
        // by default because it helps with performance in
        // the new architecture where all emulator threads
        // block on SECCOMP_NOTIFY_RECV simultaneously rather
        // than using multithreaded epoll.
        flags.insert(Self::FL_SYNC_SCMP);

        // Convenience environment variables:
        // 1. SYD_FORCE_NO_SYMLINKS    trace/force_no_symlinks:1
        // 2. SYD_FORCE_NO_MAGICLINKS  trace/force_no_magiclinks:1
        // 3. SYD_FORCE_NO_XDEV        trace/force_no_xdev:1
        // 4. SYD_FORCE_CLOEXEC        trace/force_cloexec:1
        // 5. SYD_FORCE_RAND_FD        trace/force_rand_fd:1
        // 6. SYD_FORCE_RO_OPEN        trace/force_ro_open:1
        // 7. SYD_FORCE_LOCAL_NET      trace/force_local_net:1
        const ENV2FLAG: &[(&str, Flags)] = &[
            (ENV_FORCE_NO_SYMLINKS, Flags::FL_FORCE_NO_SYMLINKS),
            (ENV_FORCE_NO_MAGICLINKS, Flags::FL_FORCE_NO_MAGICLINKS),
            (ENV_FORCE_NO_XDEV, Flags::FL_FORCE_NO_XDEV),
            (ENV_FORCE_CLOEXEC, Flags::FL_FORCE_CLOEXEC),
            (ENV_FORCE_RAND_FD, Flags::FL_FORCE_RAND_FD),
            (ENV_FORCE_RO_OPEN, Flags::FL_FORCE_RO_OPEN),
            (ENV_FORCE_LOCAL_NET, Flags::FL_FORCE_LOCAL_NET),
        ];
        for (var, flag) in ENV2FLAG {
            if env::var_os(var).is_some() {
                flags.insert(*flag);
            }
        }

        flags
    }
}

impl Default for Capability {
    fn default() -> Self {
        // Note:
        // 1. GLOB includes network sandboxing.
        // 2. PTY has no effect unless stdandard input is a TTY.
        // 3. PTY has no effect with _syd-oci_(1).
        // 4. CHDIR/STAT/WALK have noticeable overhead so they're off by default.
        // 5. IOCTL is request-only, therefore not in GLOB.
        let mut caps =
            Self::CAP_GLOB | Self::CAP_FS | Self::CAP_IOCTL | Self::CAP_PTY | Self::CAP_TPE;
        caps.remove(Self::CAP_CHDIR | Self::CAP_STAT | Self::CAP_WALK);
        caps
    }
}

impl FromStr for LockState {
    type Err = Errno;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "0" | "off" => Ok(Self::Off),
            "1" | "on" => Ok(Self::Set),
            "x" | "exec" => Ok(Self::Exec),
            "r" | "ro" | "read" | "readonly" | "read-only" => Ok(Self::Read),
            "i" | "ipc" => Ok(Self::Ipc),
            _ => Err(Errno::EINVAL),
        }
    }
}

impl Deref for SandboxGuard<'_> {
    type Target = Sandbox;
    fn deref(&self) -> &Self::Target {
        match self {
            SandboxGuard::Read(guard) => guard,
            SandboxGuard::Write(guard) => guard,
        }
    }
}

impl DerefMut for SandboxGuard<'_> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        match self {
            SandboxGuard::Write(guard) => guard,
            _ => panic!("Cannot mutate a read-locked Sandbox!"),
        }
    }
}

impl Default for Sandbox {
    fn default() -> Self {
        // SAFETY: Determine Linux kernel version string
        // randomly to prevent information leaks.
        let version = rand_version()
            .ok()
            .and_then(|version| CString::new(version).ok())
            .unwrap_or_else(|| CString::from(c""));

        let ppm_force = env::var_os(ENV_NO_CROSS_MEMORY_ATTACH).is_some();
        let ppm_fback = env::var_os(ENV_PROC_PID_MEM_FALLBACK).is_some();
        PROC_PID_MEM_FORCE.store(ppm_force, std::sync::atomic::Ordering::Relaxed);
        PROC_PID_MEM_FBACK.store(ppm_fback, std::sync::atomic::Ordering::Relaxed);

        let mut sbox = Sandbox {
            oci: false, // syd-oci sets this.
            flags: Sealable::new(Flags::default()),
            state: Sealable::new(Capability::default()),
            lock: None,
            pty_ws_x: None,
            pty_ws_y: None,
            ipc: None,
            ipc_uid: Some(Uid::current()),
            ipc_gid: Some(Gid::current()),
            chroot: false,
            verbose: 1,
            cpid: 0,
            fpid: libc::AT_FDCWD,
            config_expand_timeout: std::time::Duration::ZERO.into(),
            root: None,
            hostname: Some(CString::from(c"localhost")),
            domainname: Some(CString::from(c"(none)")),
            version: Some(version),
            boottime: None,
            monotime: None,
            mem_max: 0,
            mem_vm_max: 0,
            pid_max: 0,
            rlimit_as: None,
            rlimit_core: Some(0),
            rlimit_cpu: None,
            rlimit_data: None,
            rlimit_fsize: None,
            rlimit_memlock: Some(0),
            rlimit_msgqueue: Some(0),
            rlimit_nice: Some(0),
            rlimit_nofile: None,
            rlimit_nproc: None,
            rlimit_rtprio: Some(0),
            rlimit_rttime: Some(0),
            rlimit_sigpending: None,
            rlimit_stack: None,
            net_block_lst: (IpRange::new(), IpRange::new()),
            umask: None,
            tmout: None,
            pass_env: None,
            default_act: SealableVec::new(DEF_ACT.to_vec()),
            ioctl_set: SealableSydHashMap::default(),
            proxy_port: 9050,
            proxy_addr: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
            proxy_ext_port: 9050,
            proxy_ext_addr: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
            proxy_ext_unix: None,
            tpe_gid: None,
            transit_uids: Vec::new(),
            transit_gids: Vec::new(),
            segvguard_expiry: SEGVGUARD_EXPIRY,
            segvguard_suspension: SEGVGUARD_SUSPENSION,
            segvguard_maxcrashes: SEGVGUARD_MAXCRASHES,
            segvguard_map_expiry: ExpiringMap::new(),
            segvguard_map_suspension: ExpiringMap::new(),
            crypt_id: None,
            crypt_tmp: None,
            force_map: SealableSydHashMap::default(),
            bind_mounts: None,
            netlink_families: NetlinkFamily::empty(),
            cidr_rules: SealableVecDeque::default(),
            lock_rules: None,
            fs_acl: FsAcl::default(),
            fs_arr: FsArr::default(),
            walk_acl: Acl::default(),
            walk_arr: Arr::default(),
            stat_acl: Acl::default(),
            stat_arr: Arr::default(),
            read_acl: Acl::default(),
            read_arr: Arr::default(),
            write_acl: Acl::default(),
            write_arr: Arr::default(),
            exec_acl: Acl::default(),
            exec_arr: Arr::default(),
            create_acl: Acl::default(),
            create_arr: Arr::default(),
            delete_acl: Acl::default(),
            delete_arr: Arr::default(),
            rename_acl: Acl::default(),
            rename_arr: Arr::default(),
            symlink_acl: Acl::default(),
            symlink_arr: Arr::default(),
            truncate_acl: Acl::default(),
            truncate_arr: Arr::default(),
            chdir_acl: Acl::default(),
            chdir_arr: Arr::default(),
            readdir_acl: Acl::default(),
            readdir_arr: Arr::default(),
            mkdir_acl: Acl::default(),
            mkdir_arr: Arr::default(),
            rmdir_acl: Acl::default(),
            rmdir_arr: Arr::default(),
            chown_acl: Acl::default(),
            chown_arr: Arr::default(),
            chgrp_acl: Acl::default(),
            chgrp_arr: Arr::default(),
            chmod_acl: Acl::default(),
            chmod_arr: Arr::default(),
            chattr_acl: Acl::default(),
            chattr_arr: Arr::default(),
            chroot_acl: Acl::default(),
            chroot_arr: Arr::default(),
            utime_acl: Acl::default(),
            utime_arr: Arr::default(),
            mkbdev_acl: Acl::default(),
            mkbdev_arr: Arr::default(),
            mkcdev_acl: Acl::default(),
            mkcdev_arr: Arr::default(),
            mkfifo_acl: Acl::default(),
            mkfifo_arr: Arr::default(),
            mktemp_acl: Acl::default(),
            mktemp_arr: Arr::default(),
            net_bind_acl: Acl::default(),
            net_bind_arr: Arr::default(),
            net_conn_acl: Acl::default(),
            net_conn_arr: Arr::default(),
            net_sendfd_acl: Acl::default(),
            net_sendfd_arr: Arr::default(),
            append_acl: Arr::default(),
            crypt_acl: Arr::default(),
            mask_acl: MaskArr::default(),
        };

        // Populate ioctl(2) allow and denylists.
        #[expect(clippy::disallowed_methods)]
        for (request, deny) in DEFAULT_IOCTL {
            if *deny {
                sbox.add_ioctl_deny(request).expect("deny/ioctl");
            } else {
                sbox.add_ioctl_allow(request).expect("allow/ioctl");
            }
        }

        // Convenience environment variables:
        // - SYD_RLIMIT_AS            rlimit/as
        // - SYD_RLIMIT_CORE          rlimit/core
        // - SYD_RLIMIT_DATA          rlimit/data
        // - SYD_RLIMIT_FSIZE         rlimit/fsize
        // - SYD_RLIMIT_MEMLOCK       rlimit/memlock
        // - SYD_RLIMIT_NICE          rlimit/nice
        // - SYD_RLIMIT_NOFILE        rlimit/nofile
        // - SYD_RLIMIT_NPROC         rlimit/nproc
        // - SYD_RLIMIT_RTPRIO        rlimit/rtprio
        // - SYD_RLIMIT_RTTIME        rlimit/rttime
        // - SYD_RLIMIT_SIGPENDING    rlimit/sigpending
        // - SYD_RLIMIT_STACK         rlimit/stack
        // - SYD_TMOUT                timeout
        const ENV2CMD: &[(&str, &str)] = &[
            (ENV_RLIMIT_AS, "rlimit/as"),
            (ENV_RLIMIT_CORE, "rlimit/core"),
            (ENV_RLIMIT_DATA, "rlimit/data"),
            (ENV_RLIMIT_FSIZE, "rlimit/fsize"),
            (ENV_RLIMIT_MEMLOCK, "rlimit/memlock"),
            (ENV_RLIMIT_NICE, "rlimit/nice"),
            (ENV_RLIMIT_NOFILE, "rlimit/nofile"),
            (ENV_RLIMIT_NPROC, "rlimit/nproc"),
            (ENV_RLIMIT_RTPRIO, "rlimit/rtprio"),
            (ENV_RLIMIT_RTTIME, "rlimit/rttime"),
            (ENV_RLIMIT_SIGPENDING, "rlimit/sigpending"),
            (ENV_RLIMIT_STACK, "rlimit/stack"),
            (ENV_TMOUT, "timeout"),
        ];
        for (var, cmd) in ENV2CMD {
            let val = if let Some(val) = env::var_os(var) {
                val
            } else {
                continue;
            };
            let cmd = format!("{cmd}:{}", String::from_utf8_lossy(val.as_bytes()));

            // This is init code, panicking is OK.
            #[expect(clippy::disallowed_methods)]
            sbox.config_unchecked(&cmd).expect(var);
        }

        sbox
    }
}

impl fmt::Display for Sandbox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "Syd:")?;

        writeln!(
            f,
            "  Sandbox ID: {}",
            env::var_os(ENV_ID)
                .map(XPathBuf::from)
                .unwrap_or_else(|| XPathBuf::from("?")),
        )?;
        writeln!(f, "  Sandbox Process ID: {}", self.cpid)?;

        writeln!(
            f,
            "  Lock: {}",
            self.lock
                .map(|l| l.to_string())
                .unwrap_or_else(|| "off".to_string())
        )?;

        writeln!(f, "  Options: {}", *self.flags)?;
        writeln!(f, "  Capabilities: {}", *self.state)?;
        writeln!(f, "  Verbosity: {}", self.verbose)?;

        #[expect(clippy::cast_possible_truncation)]
        let mem_max = human_size(self.mem_max as usize);
        #[expect(clippy::cast_possible_truncation)]
        let mem_vm_max = human_size(self.mem_vm_max as usize);
        writeln!(f, "  Memory Max: {mem_max}")?;
        writeln!(f, "  Virtual Memory Max: {mem_vm_max}")?;

        writeln!(f, "  Pid Max: {}", self.pid_max)?;
        writeln!(f, "  SegvGuard Max Crashes: {}", self.segvguard_maxcrashes)?;
        writeln!(
            f,
            "  SegvGuard Expiry: {} seconds",
            self.segvguard_expiry.as_secs()
        )?;
        writeln!(
            f,
            "  SegvGuard Suspension: {} seconds",
            self.segvguard_suspension.as_secs()
        )?;

        writeln!(f, "  Default Action:")?;
        for cap in self.state.iter() {
            let action = self.default_action(cap);
            writeln!(f, "    {cap}:\t\t{action}")?;
        }

        writeln!(
            f,
            "  Allowed UID Transitions: (total: {}, source -> target)",
            self.transit_uids.len()
        )?;
        for (source_uid, target_uid) in &self.transit_uids {
            writeln!(f, "    - {source_uid} -> {target_uid}")?;
        }
        writeln!(
            f,
            "  Allowed GID Transitions: (total: {}, source -> target)",
            self.transit_gids.len()
        )?;
        for (source_gid, target_gid) in &self.transit_gids {
            writeln!(f, "    - {source_gid} -> {target_gid}")?;
        }

        let len4 = self.net_block_lst.0.iter().count();
        let len6 = self.net_block_lst.1.iter().count();
        let lall = len4.saturating_add(len6);
        writeln!(f, "  IP Blocklist: {len4} IPv4, {len6} IPv6, {lall} total")?;

        let fs_rules = self.fs_rules();
        let size = fs_rules.capacity().saturating_mul(size_of::<FsAclRule>());
        writeln!(
            f,
            "  Filesystem Rules: ({}, total {}, highest precedence first)",
            human_size(size),
            fs_rules.len()
        )?;
        for (idx, &(fs_type, act)) in fs_rules.iter().enumerate() {
            let idx = idx.saturating_add(1);
            let fs_magic: fs_type_t = fs_type.into();
            writeln!(
                f,
                "    {idx}. Action: {act}, FsType: {fs_type}, FsMagic: {fs_magic:#x}"
            )?;
        }

        let size = self
            .cidr_rules
            .capacity()
            .saturating_mul(size_of::<CidrRule>());
        writeln!(
            f,
            "  Cidr Rules: ({}, total {}, highest precedence first)",
            human_size(size),
            self.cidr_rules.len()
        )?;
        for (idx, rule) in self.cidr_rules.iter().enumerate() {
            // rev() because last matching rule wins.
            let idx = idx.saturating_add(1);
            writeln!(f, "    {idx}. {rule}")?;
        }

        let glob_rules = self.glob_rules();
        let size = glob_rules.capacity().saturating_mul(size_of::<GlobRule>());
        writeln!(
            f,
            "  Glob Rules: ({}, total {}, highest precedence first)",
            human_size(size),
            glob_rules.len()
        )?;
        for (idx, rule) in glob_rules.iter().enumerate() {
            let idx = idx.saturating_add(1);
            writeln!(f, "    {idx}. {rule}")?;
        }

        let size = self
            .append_acl
            .capacity()
            .saturating_mul(size_of::<AclRule>());
        writeln!(
            f,
            "  Append-only Rules: ({}, total {})",
            human_size(size),
            self.append_acl.len()
        )?;
        for (idx, (rule, _)) in self.append_acl.iter().enumerate() {
            let idx = idx.saturating_add(1);
            writeln!(f, "    {idx}. {rule}")?;
        }

        let size = self
            .crypt_acl
            .capacity()
            .saturating_mul(size_of::<AclRule>());
        writeln!(
            f,
            "  Crypt Rules: ({}, total {})",
            human_size(size),
            self.crypt_acl.len()
        )?;
        for (idx, (rule, _)) in self.crypt_acl.iter().enumerate() {
            let idx = idx.saturating_add(1);
            writeln!(f, "    {idx}. {rule}")?;
        }

        let size = self
            .mask_acl
            .capacity()
            .saturating_mul(size_of::<MaskRule>());
        writeln!(
            f,
            "  Mask Rules: ({}, total {})",
            human_size(size),
            self.mask_acl.len()
        )?;
        for (idx, (pattern, rule)) in self.mask_acl.into_iter().enumerate() {
            let idx = idx.saturating_add(1);
            write!(f, "    {idx}. Pattern: {pattern}, ")?;

            let mask_all = rule
                .mask
                .mask_all
                .as_ref()
                .map(|path| path.as_xpath())
                .unwrap_or_else(|| XPath::from_bytes(b"/dev/null"));
            if let Some(mask_dir) = &rule.mask.mask_dir {
                writeln!(f, ", AllMask: {mask_all}, DirMask: {mask_dir}")?;
            } else {
                writeln!(f, "Mask: {mask_all}")?;
            }
        }

        let mut force_rules: Vec<_> = self.force_rules();
        force_rules.sort_by_key(|&(k, _)| k); // Sort by path keys for consistent ordering.
        writeln!(
            f,
            "  Force Rules: (total {}, default action: {})",
            force_rules.len(),
            self.default_action(Capability::CAP_FORCE),
        )?;
        for (idx, (path, v)) in force_rules.iter().enumerate() {
            let (force, bytes) = v;
            let idx = idx.saturating_add(1);
            let hash = HEXLOWER.encode(bytes);
            writeln!(
                f,
                "    {idx}. Action: {force}, Checksum: {hash}, Path: {path}"
            )?;
        }

        if let Some(rules) = self.lock_rules.as_ref() {
            write!(f, "{rules}")?;
        }

        Ok(())
    }
}

impl fmt::Debug for Sandbox {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Sandbox")
            .field("flags", &self.flags)
            .field("state", &self.state)
            .field("lock", &self.lock)
            .field("cpid", &self.cpid)
            .field("fpid", &self.fpid)
            .field("root", &self.root)
            .field("default_fs", &self.default_action(Capability::CAP_FS))
            .field("default_walk", &self.default_action(Capability::CAP_WALK))
            .field("default_stat", &self.default_action(Capability::CAP_STAT))
            .field("default_read", &self.default_action(Capability::CAP_READ))
            .field("default_write", &self.default_action(Capability::CAP_WRITE))
            .field("default_exec", &self.default_action(Capability::CAP_EXEC))
            .field("default_ioctl", &self.default_action(Capability::CAP_IOCTL))
            .field("default_create", &self.default_action(Capability::CAP_CREATE))
            .field("default_delete", &self.default_action(Capability::CAP_DELETE))
            .field("default_rename", &self.default_action(Capability::CAP_RENAME))
            .field("default_symlink", &self.default_action(Capability::CAP_SYMLINK))
            .field("default_truncate", &self.default_action(Capability::CAP_TRUNCATE))
            .field("default_chdir", &self.default_action(Capability::CAP_CHDIR))
            .field("default_readdir", &self.default_action(Capability::CAP_READDIR))
            .field("default_mkdir", &self.default_action(Capability::CAP_MKDIR))
            .field("default_rmdir", &self.default_action(Capability::CAP_RMDIR))
            .field("default_chown", &self.default_action(Capability::CAP_CHOWN))
            .field("default_chgrp", &self.default_action(Capability::CAP_CHGRP))
            .field("default_chmod", &self.default_action(Capability::CAP_CHMOD))
            .field("default_chattr", &self.default_action(Capability::CAP_CHATTR))
            .field("default_chroot", &self.default_action(Capability::CAP_CHROOT))
            .field("default_utime", &self.default_action(Capability::CAP_UTIME))
            .field("default_mkbdev", &self.default_action(Capability::CAP_MKBDEV))
            .field("default_mkcdev", &self.default_action(Capability::CAP_MKCDEV))
            .field("default_mkfifo", &self.default_action(Capability::CAP_MKFIFO))
            .field("default_mktemp", &self.default_action(Capability::CAP_MKTEMP))
            .field("default_net_bind", &self.default_action(Capability::CAP_NET_BIND))
            .field("default_net_connect", &self.default_action(Capability::CAP_NET_CONNECT))
            .field("default_net_sendfd", &self.default_action(Capability::CAP_NET_SENDFD))
            .field("default_block", &self.net_block_act())
            .field("default_mem", &self.default_action(Capability::CAP_MEM))
            .field("default_pid", &self.default_action(Capability::CAP_PID))
            .field("default_force", &self.default_action(Capability::CAP_FORCE))
            .field("default_segvguard", &self.segvguard_act())
            .field("default_tpe", &self.default_action(Capability::CAP_TPE))
            .field("default_lock", &self.default_action(Capability::CAP_LOCK))
            .field("hostname", &self.hostname)
            .field("domainname", &self.domainname)
            .field("mem_max", &self.mem_max)
            .field("mem_vm_max", &self.mem_vm_max)
            .field("pid_max", &self.pid_max)
            .field("rlimit_as", &self.rlimit_as)
            .field("rlimit_core", &self.rlimit_core)
            .field("rlimit_cpu", &self.rlimit_cpu)
            .field("rlimit_data", &self.rlimit_data)
            .field("rlimit_fsize", &self.rlimit_fsize)
            .field("rlimit_memlock", &self.rlimit_memlock)
            .field("rlimit_msgqueue", &self.rlimit_msgqueue)
            .field("rlimit_nice", &self.rlimit_nice)
            .field("rlimit_nofile", &self.rlimit_nofile)
            .field("rlimit_nproc", &self.rlimit_nproc)
            .field("rlimit_rtprio", &self.rlimit_rtprio)
            .field("rlimit_rttime", &self.rlimit_rttime)
            .field("rlimit_sigpending", &self.rlimit_sigpending)
            .field("rlimit_stack", &self.rlimit_stack)
            .field("umask", &self.umask)
            .field("tmout", &self.tmout)
            .field("transit_uids", &self.transit_uids)
            .field("transit_gids", &self.transit_gids)
            .field("segvguard_expiry", &self.segvguard_expiry.as_secs())
            .field("segvguard_suspension", &self.segvguard_suspension.as_secs())
            .field("segvguard_maxcrashes", &self.segvguard_maxcrashes)
            //.field("segvguard_map_expiry", &self.segvguard_map_expiry) // skipped
            //.field("segvguard_map_suspension", &self.segvguard_map_suspension) // skipped
            .field("force_map", &self.force_map)
            .field("bind_mounts", &self.bind_mounts)
            .field("cidr_rules", &self.cidr_rules)
            .field("glob_rules", &self.glob_rules())
            .field("lock_rules", &self.lock_rules)
            .finish()
    }
}

impl Serialize for Sandbox {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(None)?;

        #[expect(clippy::disallowed_methods)]
        map.serialize_entry(
            "id",
            &env::var(ENV_ID).expect("BUG: SYD_ID environment variable isn't set!"),
        )?;
        map.serialize_entry("name", &self.hostname)?;
        map.serialize_entry("domain", &self.domainname)?;
        map.serialize_entry("flags", &*self.flags)?;
        map.serialize_entry("state", &*self.state)?;
        map.serialize_entry("lock", &self.lock)?;
        map.serialize_entry("cpid", &self.cpid)?;
        map.serialize_entry("fpid", &self.fpid)?;
        map.serialize_entry("chroot", &self.chroot)?;
        map.serialize_entry("boottime", &self.boottime)?;
        map.serialize_entry("monotime", &self.monotime)?;
        map.serialize_entry("umask", &self.umask.map(|m| m.bits()))?;
        map.serialize_entry("tmout", &self.tmout.map(|d| d.as_secs()))?;
        map.serialize_entry("verbose", &self.verbose)?;

        // This is used in tests to verify RUST_BACKTRACE=0 override.
        let backtrace = env::var_os("RUST_BACKTRACE")
            .map(XPathBuf::from)
            .unwrap_or_else(|| XPathBuf::from("?"));
        map.serialize_entry("backtrace", &backtrace)?;

        map.serialize_entry("proxy_addr", &self.proxy_addr)?;
        map.serialize_entry("proxy_port", &self.proxy_port)?;
        map.serialize_entry("proxy_ext_addr", &self.proxy_ext_addr)?;
        map.serialize_entry("proxy_ext_port", &self.proxy_ext_port)?;
        map.serialize_entry("proxy_ext_unix", &self.proxy_ext_unix)?;

        map.serialize_entry("default_fs", &self.default_action(Capability::CAP_FS))?;
        map.serialize_entry("default_walk", &self.default_action(Capability::CAP_WALK))?;
        map.serialize_entry("default_stat", &self.default_action(Capability::CAP_STAT))?;
        map.serialize_entry("default_read", &self.default_action(Capability::CAP_READ))?;
        map.serialize_entry("default_write", &self.default_action(Capability::CAP_WRITE))?;
        map.serialize_entry("default_exec", &self.default_action(Capability::CAP_EXEC))?;
        map.serialize_entry("default_ioctl", &self.default_action(Capability::CAP_IOCTL))?;
        map.serialize_entry(
            "default_create",
            &self.default_action(Capability::CAP_CREATE),
        )?;
        map.serialize_entry(
            "default_delete",
            &self.default_action(Capability::CAP_DELETE),
        )?;
        map.serialize_entry(
            "default_rename",
            &self.default_action(Capability::CAP_RENAME),
        )?;
        map.serialize_entry(
            "default_symlink",
            &self.default_action(Capability::CAP_SYMLINK),
        )?;
        map.serialize_entry(
            "default_truncate",
            &self.default_action(Capability::CAP_TRUNCATE),
        )?;
        map.serialize_entry("default_chdir", &self.default_action(Capability::CAP_CHDIR))?;
        map.serialize_entry(
            "default_readdir",
            &self.default_action(Capability::CAP_READDIR),
        )?;
        map.serialize_entry("default_mkdir", &self.default_action(Capability::CAP_MKDIR))?;
        map.serialize_entry("default_rmdir", &self.default_action(Capability::CAP_RMDIR))?;
        map.serialize_entry("default_chown", &self.default_action(Capability::CAP_CHOWN))?;
        map.serialize_entry("default_chgrp", &self.default_action(Capability::CAP_CHGRP))?;
        map.serialize_entry("default_chmod", &self.default_action(Capability::CAP_CHMOD))?;
        map.serialize_entry(
            "default_chattr",
            &self.default_action(Capability::CAP_CHATTR),
        )?;
        map.serialize_entry(
            "default_chroot",
            &self.default_action(Capability::CAP_CHROOT),
        )?;
        map.serialize_entry("default_utime", &self.default_action(Capability::CAP_UTIME))?;
        map.serialize_entry(
            "default_mkbdev",
            &self.default_action(Capability::CAP_MKBDEV),
        )?;
        map.serialize_entry(
            "default_mkcdev",
            &self.default_action(Capability::CAP_MKCDEV),
        )?;
        map.serialize_entry(
            "default_mkfifo",
            &self.default_action(Capability::CAP_MKFIFO),
        )?;
        map.serialize_entry(
            "default_mktemp",
            &self.default_action(Capability::CAP_MKTEMP),
        )?;
        map.serialize_entry(
            "default_net_bind",
            &self.default_action(Capability::CAP_NET_BIND),
        )?;
        map.serialize_entry(
            "default_net_connect",
            &self.default_action(Capability::CAP_NET_CONNECT),
        )?;
        map.serialize_entry(
            "default_net_sendfd",
            &self.default_action(Capability::CAP_NET_SENDFD),
        )?;
        map.serialize_entry("default_block", &self.net_block_act())?;
        map.serialize_entry("default_lock", &self.default_action(Capability::CAP_LOCK))?;
        map.serialize_entry("default_mem", &self.default_action(Capability::CAP_MEM))?;
        map.serialize_entry("default_pid", &self.default_action(Capability::CAP_PID))?;
        map.serialize_entry("default_force", &self.default_action(Capability::CAP_FORCE))?;
        map.serialize_entry("default_segvguard", &self.segvguard_act())?;
        map.serialize_entry("default_tpe", &self.default_action(Capability::CAP_TPE))?;

        map.serialize_entry("mem_max", &self.mem_max)?;
        map.serialize_entry("mem_vm_max", &self.mem_vm_max)?;
        map.serialize_entry("pid_max", &self.pid_max)?;
        map.serialize_entry("rlimit_as", &self.rlimit_as)?;
        map.serialize_entry("rlimit_core", &self.rlimit_core)?;
        map.serialize_entry("rlimit_cpu", &self.rlimit_cpu)?;
        map.serialize_entry("rlimit_data", &self.rlimit_data)?;
        map.serialize_entry("rlimit_fsize", &self.rlimit_fsize)?;
        map.serialize_entry("rlimit_memlock", &self.rlimit_memlock)?;
        map.serialize_entry("rlimit_msgqueue", &self.rlimit_msgqueue)?;
        map.serialize_entry("rlimit_nice", &self.rlimit_nice)?;
        map.serialize_entry("rlimit_nofile", &self.rlimit_nofile)?;
        map.serialize_entry("rlimit_nproc", &self.rlimit_nproc)?;
        map.serialize_entry("rlimit_rtprio", &self.rlimit_rtprio)?;
        map.serialize_entry("rlimit_rttime", &self.rlimit_rttime)?;
        map.serialize_entry("rlimit_sigpending", &self.rlimit_sigpending)?;
        map.serialize_entry("rlimit_stack", &self.rlimit_stack)?;
        map.serialize_entry("segvguard_expiry", &self.segvguard_expiry.as_secs())?;
        map.serialize_entry("segvguard_suspension", &self.segvguard_suspension.as_secs())?;
        map.serialize_entry("segvguard_maxcrashes", &self.segvguard_maxcrashes)?;
        map.serialize_entry(
            "transit_uids",
            &self
                .transit_uids
                .iter()
                .map(|(src, dst)| (src.as_raw(), dst.as_raw()))
                .collect::<Vec<(libc::uid_t, libc::uid_t)>>(),
        )?;
        map.serialize_entry(
            "transit_gids",
            &self
                .transit_gids
                .iter()
                .map(|(src, dst)| (src.as_raw(), dst.as_raw()))
                .collect::<Vec<(libc::gid_t, libc::gid_t)>>(),
        )?;
        map.serialize_entry("fs_rules", &self.fs_rules())?;
        map.serialize_entry("cidr_rules", &self.cidr_rules())?;
        map.serialize_entry("glob_rules", &self.glob_rules())?;
        map.serialize_entry("lock_rules", &self.lock_rules)?;
        map.serialize_entry(
            "append_rules",
            &self
                .append_acl
                .iter()
                .map(|(p, _)| p)
                .collect::<Vec<&XPathBuf>>(),
        )?;
        map.serialize_entry(
            "crypt_rules",
            &self
                .crypt_acl
                .iter()
                .map(|(p, _)| p)
                .collect::<Vec<&XPathBuf>>(),
        )?;
        map.serialize_entry(
            "mask_rules",
            &self
                .mask_acl
                .into_iter()
                .map(|(pat, rule)| {
                    (
                        pat,
                        rule.mask.mask_all.as_ref(),
                        rule.mask.mask_dir.as_ref(),
                    )
                })
                .collect::<Vec<(&XPathBuf, Option<&XPathBuf>, Option<&XPathBuf>)>>(),
        )?;

        // Serialize the `force_map` as "force_rules"
        let mut force_rules: Vec<_> = self.force_rules();
        force_rules.sort_by_key(|&(k, _)| k); // Sort by path keys for consistent ordering
                                              // FIXME: json! calls unwrap().
        #[expect(clippy::disallowed_methods)]
        let force_rules: Vec<_> = force_rules
            .iter()
            .map(|(k, v)| {
                let (force, bytes) = v;
                serde_json::json!({
                    "pat": k,
                    "sha": HEXLOWER.encode(bytes),
                    "act": force
                })
            })
            .collect();
        map.serialize_entry("force_rules", &force_rules)?;

        // Export API spec.
        map.serialize_entry("api", &*crate::api::API_SPEC)?;

        map.end()
    }
}

#[cfg(feature = "oci")]
impl TryFrom<&Spec> for Sandbox {
    type Error = crate::err::SydError;

    /// Create a sandbox using saved config /.oci.syd-3.
    /// If the file does not exist, parse the oci profile.
    #[expect(clippy::cognitive_complexity)]
    fn try_from(_spec: &Spec) -> Result<Self, Self::Error> {
        // Generate unique sandbox id from AT_RANDOM bytes.
        // Allow the user to override by setting SYD_ID.
        // Panic if SYD_ID is incorrectly formatted.
        use std::os::unix::ffi::OsStrExt;

        let cookie = crate::hash::get_at_random_hex(false);
        env::set_var(ENV_RAND, &cookie);

        #[expect(clippy::disallowed_methods)]
        if let Some(sandbox_id) = env::var_os(ENV_ID) {
            assert_eq!(
                sandbox_id.len(),
                128,
                "PANIC: Sandbox ID in SYD_ID environment variable isn't in correct format!"
            );
            assert!(
                sandbox_id
                    .as_bytes()
                    .iter()
                    .all(|b| b.is_ascii_hexdigit() && !b.is_ascii_uppercase()),
                "PANIC: Sandbox ID in SYD_ID environment variable isn't in correct format!"
            );
            let machine_id = &sandbox_id.as_bytes()[..32];
            assert!(
                machine_id.iter().any(|&b| b != b'0'),
                "PANIC: Sandbox ID in SYD_ID environment variable isn't in correct format!"
            );
        } else {
            let sandbox_id = HEXLOWER
                .encode(&crate::hash::hash(cookie.as_bytes(), HashAlgorithm::Sha512).unwrap());
            env::set_var(ENV_ID, &sandbox_id);
            info!("ctx": "set_sandbox_id",
                "id": &sandbox_id, "cookie": &cookie, "hash": "sha3-512",
                "msg": format!("generated syd id:{sandbox_id} from cookie:{cookie} using SHA3-512"));
        }

        // Initialize sandbox to default state.
        let mut sandbox = Self {
            // Inform sandbox that we're `syd-oci'.
            // This is used in argument validation.
            oci: true,
            ..Default::default()
        };

        // Parse the user specified configuration file.
        // Parse the hardcoded OCI profile if no user config was specified.
        let path = XPath::from_bytes(b"/.oci.syd-3");
        if path.exists(true) {
            sandbox.parse_config_file(path)?;
            info!("ctx": "configure_oci", "imp": true,
                "msg": "profile loaded from /.oci.syd-3");
        } else {
            sandbox.parse_profile("oci")?;
            info!("ctx": "configure_oci", "imp": false,
                "msg": "oci profile loaded as default");
        }

        // Remove unsupported options for `syd-oci'.
        //
        // Namespace creation is delegated to Youki.
        sandbox.flags.remove(
            Flags::FL_UNSHARE_MOUNT
                | Flags::FL_UNSHARE_UTS
                | Flags::FL_UNSHARE_IPC
                | Flags::FL_UNSHARE_USER
                | Flags::FL_UNSHARE_PID
                | Flags::FL_UNSHARE_NET
                | Flags::FL_UNSHARE_CGROUP
                | Flags::FL_UNSHARE_TIME
                | Flags::FL_MAP_ROOT,
        );
        //
        // Settings that expect namespace creation:
        sandbox.state.remove(Capability::CAP_PROXY);
        sandbox.bind_mounts = None;
        sandbox.root = None;
        sandbox.boottime = None;
        sandbox.monotime = None;
        // Settings that are unsafe with `syd-oci':
        sandbox.ipc = None;
        // PTY creation is delegated to Youki.
        sandbox.state.remove(Capability::CAP_PTY);

        Ok(sandbox)
    }
}

impl Sandbox {
    /// Parses a configuration from a given file-like object and applies its configuration to the sandbox.
    ///
    /// This function reads from the given file-like object line by line. It skips lines that are either
    /// empty or start with a '#' (treated as comments). For each valid line, it applies its
    /// configuration to the provided sandbox.
    ///
    /// # Arguments
    ///
    /// * `file` - A file-like object to read the configuration from. This can be any type that
    ///   implements the `Read` and `BufRead` traits.
    /// * `path` - Path name of the file, must be an absolute path and have the file extension ".syd-3".
    /// * `imap` - A HashSet of file information to keep track of included files to prevent loops.
    ///
    /// # Returns
    ///
    /// * A Result indicating the success or failure of the operation.
    ///
    /// # Errors
    ///
    /// This function will return an error if:
    /// * There's an error reading a line from the file.
    /// * There's an issue in parsing and applying a configuration line to the sandbox.
    pub fn parse_config<F: Read + BufRead>(
        &mut self,
        mut file: F,
        path: &XPath,
        imap: &mut SydHashSet<FileInfo>,
    ) -> SydResult<()> {
        let running = self.is_running();

        if running && path.is_relative() {
            // SAFETY: relative paths are only permitted at startup.
            return Err(Errno::EINVAL.into());
        }

        let load = running && is_equal(path.as_bytes(), b"/dev/syd/load");
        if !load {
            let fext = format!(".syd-{API_MAJOR_VERSION}");
            if !path.ends_with(fext.as_bytes()) {
                return Err(Errno::EOPNOTSUPP.into());
            }
        }
        let mut line = vec![0; LINE_MAX];
        let mut temp = Vec::new();
        let mut line_count = 1usize;

        loop {
            let bytes_read = file.read(&mut line[..])?;
            if bytes_read == 0 {
                break; // End of file reached.
            }

            if !line.iter().take(bytes_read).any(|&b| b == b'\n') {
                // If no newline is found in the current chunk and we're
                // reading from a file like /dev/zero, return an error
                // indicating the line count at which this was detected.
                return Err(Errno::ENAMETOOLONG.into());
            }
            temp.extend_from_slice(&line[..bytes_read]);

            while let Some(pos) = temp.iter().position(|&b| b == b'\n') {
                let line = &temp[..pos]; // excludes the \n character.
                let line = std::str::from_utf8(line)?;

                if line.trim_start().starts_with('#') {
                    /* Comment: do nothing */
                } else if line.trim().is_empty() {
                    /* Blank line: do nothing */
                } else if self.locked() {
                    // SAFETY: To be consistent with the way we handle
                    // consequent -m CLI arguments, we check for sandbox
                    // lock before each sandbox.config() call.
                    return Err(Errno::EBUSY.into());
                } else if let Some(inc) = line.strip_prefix("include_profile ") {
                    // Handle include_profile directive.
                    self.parse_profile(inc)?;
                } else if let Some(inc) = line.strip_prefix("include ") {
                    // Handle include directive.

                    // SAFETY: We do not parse include directives when loading from file descriptors.
                    if load {
                        return Err(Errno::EBUSY.into());
                    }

                    // 1. Shell expand the include path.
                    // 2. Handle relative files according to the directory of the current file.
                    let mut inc = self.expand_env(inc).map(XPathBuf::from)?;
                    if inc.is_relative() {
                        inc = path.parent().join(inc.as_bytes());
                    }

                    // Query file metadata.
                    let stx = statx(AT_FDCWD, &inc, 0, FileInfo::mask() | STATX_MODE)?;
                    let info = FileInfo::from_statx(stx);

                    // Check for include loops and secure file permissions.
                    let permissions = Mode::from_bits_truncate(stx.stx_mode.into());
                    if !imap.insert(info) {
                        return Err(Errno::ELOOP.into());
                    }
                    if permissions.contains(Mode::S_IWGRP | Mode::S_IWOTH) {
                        return Err(Errno::EACCES.into());
                    }

                    // Check for file extension.
                    // Currently we have three supported extensions:
                    // 1. .syd-3
                    // 2. .ipset, .netset
                    // ipset and netset files are list of IP addresses
                    // where lines starting with the '#' character are
                    // ignored.
                    let inc_ext = inc.extension().ok_or(Errno::EOPNOTSUPP)?;
                    let syd_ext = XPathBuf::from(format!("syd-{API_MAJOR_VERSION}"));
                    let ips_ext = XPath::from_bytes(b"ipset");
                    let net_ext = XPath::from_bytes(b"netset");
                    if *inc_ext == *syd_ext {
                        // Parse as Syd configuration file.
                        #[expect(clippy::disallowed_methods)]
                        let file = File::open(inc.as_path())?;
                        self.parse_config(BufReader::new(file), &inc, imap)?;
                    } else if inc_ext == ips_ext || inc_ext == net_ext {
                        // Parse as IPSet.
                        #[expect(clippy::disallowed_methods)]
                        let file = File::open(inc.as_path())?;
                        self.parse_netset(BufReader::new(file))?;
                    } else {
                        return Err(Errno::EOPNOTSUPP.into());
                    }
                } else {
                    self.config(line)?;
                }
                // Remove the processed line from temp storage.
                temp.drain(..=pos);
                line_count = line_count.saturating_add(1); // Increment line count after processing each line.
            }
        }

        Ok(())
    }

    /// Parses a configuration file and applies its configuration to the sandbox.
    ///
    /// This function reads the given configuration file line by line. It skips lines that are either
    /// empty or start with a '#' (treated as comments). For each valid line, it applies its
    /// configuration to the provided sandbox.
    ///
    /// # Arguments
    ///
    /// * `path` - A reference to the path of the configuration file. This can be any type that
    ///   implements the `AsRef<Path>` trait.
    ///
    /// # Returns
    ///
    /// * A Result indicating the success or failure of the operation.
    ///
    /// # Errors
    ///
    /// This function will return an error if:
    /// * There's an issue in opening the configuration file.
    /// * There's an error reading a line from the file.
    /// * There's an issue in parsing and applying a configuration line to the sandbox.
    #[expect(clippy::disallowed_methods)]
    pub fn parse_config_file(&mut self, path: &XPath) -> SydResult<()> {
        // SAFETY: Prevent path traversals.
        if path.has_parent_dot() {
            return Err(Errno::EPERM.into());
        }

        // SAFETY:
        // 1. Do not resolve symbolic links!
        // 2. Bail out if file is not a regular file.
        let how = OpenHow::new()
            .flags(OFlag::O_PATH | OFlag::O_CLOEXEC | OFlag::O_NOFOLLOW)
            .resolve(ResolveFlag::RESOLVE_NO_MAGICLINKS | ResolveFlag::RESOLVE_NO_SYMLINKS);
        let fd = retry_on_eintr(|| openat2(AT_FDCWD, path, how))?;
        if !file_type(&fd, None, false)?.is_file() {
            return Err(Errno::EPERM.into());
        }

        let how = OpenHow::new().flags(OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_NOCTTY);
        let mut pfd = XPathBuf::from("/proc/thread-self/fd");
        pfd.push_fd(fd.as_raw_fd());

        let file = retry_on_eintr(|| openat2(AT_BADFD, &pfd, how))
            .map(File::from)
            .map(BufReader::new)?;

        let mut imap = SydHashSet::default();

        self.parse_config(file, path, &mut imap)
    }

    /// Parses the given profile and applies its configuration to the sandbox.
    ///
    /// This function supports multiple predefined profiles such as "paludis", "noipv4", "noipv6", and "user".
    /// Each profile corresponds to a set of configuration lines which are applied to the sandbox.
    /// The "user" profile includes both static configurations and dynamic ones that depend on the
    /// environment and the existence of a user-specific configuration file.
    ///
    /// # Arguments
    ///
    /// * `name` - A string slice that holds the name of the profile to be parsed.
    /// * `sandbox` - A mutable reference to the sandbox where the profile configurations will be applied.
    ///
    /// # Returns
    ///
    /// * A Result indicating the success or failure of the operation.
    ///
    /// # Errors
    ///
    /// This function will return an error if:
    /// * The profile name is invalid.
    /// * There's an issue in parsing the configuration lines.
    /// * There's an issue in reading or parsing the user-specific configuration file for the "user" profile.
    pub fn parse_profile(&mut self, name: &str) -> SydResult<()> {
        // Inner function to handle repetitive logic of applying configurations
        fn apply_config(sandbox: &mut Sandbox, profile: &[&str]) -> SydResult<()> {
            for line in profile {
                sandbox.config(line)?;
            }
            Ok(())
        }

        match name {
            "container" => apply_config(self, PROFILE_CONTAINER),
            "immutable" => apply_config(self, PROFILE_IMMUTABLE),
            "landlock" => apply_config(self, PROFILE_LANDLOCK),
            "linux" => apply_config(self, PROFILE_LINUX),
            "ltp" => apply_config(self, PROFILE_LTP),
            "kvm" => apply_config(self, PROFILE_KVM),
            "kvm_native" => apply_config(self, PROFILE_KVM_NATIVE),
            "nix" => apply_config(self, PROFILE_NIX),
            "pwd" | "cwd" => apply_config(self, PROFILE_CWD),
            "paludis" => apply_config(self, PROFILE_PALUDIS),
            "local" => apply_config(self, PROFILE_LOCAL),
            "noipv4" => apply_config(self, PROFILE_NOIPV4),
            "noipv6" => apply_config(self, PROFILE_NOIPV6),
            "privileged" => apply_config(self, PROFILE_PRIVILEGED),
            "core" => apply_config(self, PROFILE_CORE),
            "debug" => apply_config(self, PROFILE_DEBUG),
            "enforce" => apply_config(self, PROFILE_ENFORCE),
            "nomem" => apply_config(self, PROFILE_NOMEM),
            "nopie" => apply_config(self, PROFILE_NOPIE),
            "quiet" | "silent" => apply_config(self, PROFILE_QUIET),
            "hide" => apply_config(self, PROFILE_HIDE),
            "rand" => apply_config(self, PROFILE_RAND),
            "ro" | "readonly" => apply_config(self, PROFILE_READONLY),
            "ff" | "firefox" => apply_config(self, PROFILE_FIREFOX),
            "fs" => apply_config(self, PROFILE_FS),
            "gui" => apply_config(self, PROFILE_GUI),
            "off" => apply_config(self, PROFILE_OFF),
            "lib" => apply_config(self, PROFILE_LIB),
            "oci" => apply_config(self, PROFILE_OCI),
            "trace" => apply_config(self, PROFILE_TRACE),
            "tty" => apply_config(self, PROFILE_TTY),
            "tty_native" => apply_config(self, PROFILE_TTY_NATIVE),
            "nixstore" => apply_config(self, PROFILE_NIX_STORE),
            "user" => {
                // Apply the static `user` profile.
                apply_config(self, PROFILE_USER)?;

                // Parse the system & user configuration file if it exists.
                let home = env::var_os("HOME")
                    .map(XPathBuf::from)
                    .unwrap_or(XPathBuf::from("/proc/self/fdinfo"));
                let rc = [
                    XPath::from_bytes(PATH_ETC)
                        .join(format!("user.syd-{API_MAJOR_VERSION}").as_bytes()),
                    home.join(format!(".user.syd-{API_MAJOR_VERSION}").as_bytes()),
                ];

                for path in &rc {
                    if !path.exists(true) {
                        continue;
                    } else if self.locked() {
                        error!("ctx": "configure_user",
                            "path": path,
                            "msg": format!("profile load from `{path}' prevented by the sandbox lock"),
                            "tip": format!("set lock:exec or lock:off at the end of `{}'", rc[0]));
                        continue;
                    }

                    self.parse_config_file(path)?;
                }

                Ok(())
            }
            name => {
                // Parse one character at a time.
                let mut ok = false;
                for c in name.chars() {
                    self.parse_profile(match c {
                        '4' => "noipv6",
                        '6' => "noipv4",
                        'C' => "core",
                        'D' => "debug",
                        'E' => "enforce",
                        'M' => "nomem",
                        'P' => "nopie",
                        'X' => "noexe",
                        'c' => "container",
                        'd' => "cwd",
                        'f' => "fs",
                        'g' => "gui",
                        'h' => "hide",
                        'i' => "immutable",
                        'l' => "landlock",
                        'L' => "linux",
                        'p' => "privileged",
                        'q' => "quiet",
                        'r' => "rand",
                        't' => "tty",
                        'u' => "user",
                        '@' => "local",
                        _ => return Err(Errno::EINVAL.into()),
                    })?;
                    ok = true;
                }

                if ok {
                    Ok(())
                } else {
                    Err(Errno::EINVAL.into())
                }
            }
        }
    }

    /// Parses an ip set file with extensions: .ipset & .netset.
    pub fn parse_netset<F: Read + BufRead>(&mut self, mut file: F) -> SydResult<()> {
        let mut line = vec![0; LINE_MAX];
        let mut temp = Vec::new();
        let mut line_count = 1usize;

        // SAFETY: Check for sandbox lock.
        if self.locked() {
            return Err(Errno::EBUSY.into());
        }

        loop {
            let bytes_read = file.read(&mut line[..])?;
            if bytes_read == 0 {
                break; // End of file reached.
            }

            if !line.iter().take(bytes_read).any(|&b| b == b'\n') {
                // If no newline is found in the current chunk and we're
                // reading from a file like /dev/zero, return an error
                // indicating the line count at which this was detected.
                return Err(Errno::ENAMETOOLONG.into());
            }
            temp.extend_from_slice(&line[..bytes_read]);

            while let Some(pos) = temp.iter().position(|&b| b == b'\n') {
                let line = &temp[..pos]; // excludes the \n character.
                let line = std::str::from_utf8(line)?;
                let line = line.trim();
                if line.is_empty() || line.starts_with('#') {
                    /* Blank line or comment: do nothing. */
                } else {
                    match parse_ipnet(line) {
                        Ok(IpNet::V4(addr)) => {
                            self.net_block_lst.0.add(addr);
                        }
                        Ok(IpNet::V6(addr)) => {
                            self.net_block_lst.1.add(addr);
                        }
                        Err(err) => panic!("Invalid IP network `{line}': {err}"),
                    };
                }
                // Remove the processed line from temp storage.
                temp.drain(..=pos);
                line_count = line_count.saturating_add(1); // Increment line count after processing each line.
            }
        }

        Ok(())
    }

    /// Configures the sandbox using a specified command.
    ///
    /// This method provides a central point for configuring the sandbox. It interprets and
    /// processes a variety of commands to adjust the sandbox's state, manage its tracing,
    /// handle regex-based configurations, and more.
    ///
    /// # Arguments
    ///
    /// * `command` - A string slice that represents the command to be executed.
    ///
    /// # Returns
    ///
    /// * A `Result` that indicates the success or failure of the operation. In the event of a
    ///   failure, it returns an appropriate error from the `Errno` enum.
    ///
    /// # Commands
    ///
    /// - If the command is empty or matches the API version, it simply returns `Ok(())`.
    /// - If the command starts with "lock", it attempts to set the sandbox's lock state.
    /// - If the command matches one of the supported commands, it applies the command to the sandbox.
    ///   See the ["Configuration" section in the README.md file](https://crates.io/crates/syd#configuration)
    ///   for a list of supported commands.
    /// - If none of the above conditions are met, it returns an error indicating invalid input.
    ///
    /// # Examples
    ///
    /// ```
    /// use syd::sandbox::Sandbox;
    ///
    /// let mut sandbox = Sandbox::new();
    /// sandbox
    ///     .config("lock:on")
    ///     .expect("Failed to lock the sandbox");
    /// ```
    #[expect(clippy::cognitive_complexity)]
    pub fn config(&mut self, cmd: &str) -> Result<(), Errno> {
        // Init environment unless we're running.
        if !self.is_running() {
            Self::init_env();
        }

        // Apply given sandbox command.
        match self.config_unchecked(cmd) {
            Ok(()) => {
                if log_enabled!(LogLevel::Debug) && !cmd.starts_with("crypt/") {
                    let cmd = XPathBuf::from(cmd);
                    let sbq = cmd.ends_with(b"?");
                    debug!("ctx": if sbq { "query_sandbox" } else { "configure_sandbox" },
                        "msg": format!("{} sandbox with command {cmd}",
                            if sbq { "queried" } else { "configured" }),
                        "cfg": cmd);
                }
                Ok(())
            }
            Err(Errno::ENOENT) => {
                if log_enabled!(LogLevel::Debug) {
                    let cmd = XPathBuf::from(cmd);
                    debug!("ctx": "query_sandbox",
                        "msg": "sandbox query returned false",
                        "err": Errno::ENOENT as i32,
                        "cfg": cmd);
                }
                Err(Errno::ENOENT)
            }
            Err(errno) => {
                let cmd = XPathBuf::from(cmd);
                error!("ctx": "configure_sandbox",
                    "msg": format!("sandbox configure error for `{cmd}': {errno}"),
                    "err": errno as i32,
                    "cfg": cmd);
                Err(errno)
            }
        }
    }

    #[expect(clippy::cognitive_complexity)]
    fn init_env() {
        if env::var_os("SYD_UID").is_none() {
            // Set per-user environment variables:
            // SYD_UID, SYD_GID,
            // USER, HOME.
            let uid = Uid::current();
            let gid = Gid::current();
            let name = crate::get_user_name(uid);
            let home = crate::get_user_home(&name);

            env::set_var("SYD_UID", uid.to_string());
            info!("ctx": "init_env",
                "msg": format!("set SYD_UID environment variable to {uid}"));

            env::set_var("SYD_GID", gid.to_string());
            info!("ctx": "init_env",
                "msg": format!("set SYD_GID environment variable to {gid}"));

            env::set_var("SYD_USER", &name);
            info!("ctx": "init_env",
                "msg": format!("set SYD_USER environment variable to {name}"));

            env::set_var("SYD_HOME", &home);
            info!("ctx": "init_env",
                "msg": format!("set SYD_HOME environment variable to {home}"));

            if env::var_os("USER").is_none() {
                env::set_var("USER", &name);
            }
            if env::var_os("HOME").is_none() {
                env::set_var("HOME", &home);
            }

            // Save the user from some annoying warnings.
            if env::var_os("GIT_CEILING_DIRECTORIES").is_none() {
                env::set_var("GIT_CEILING_DIRECTORIES", &home);
            }
        }

        if env::var_os("SYD_PWD").is_none() {
            // Set SYD_PWD to canonicalized current working directory.
            // On errors fallback to /proc/self/fdinfo.
            if let Some(cwd) = getcwd()
                .ok()
                .and_then(|cwd| std::fs::canonicalize(cwd).ok())
                .map(XPathBuf::from)
            {
                env::set_var("PWD", &cwd);
                env::set_var("SYD_PWD", &cwd);
                info!("ctx": "init_env",
                    "msg": format!("set SYD_PWD environment variable to {cwd}"));
            } else {
                env::set_var("PWD", "/proc/self/fdinfo");
                env::set_var("SYD_PWD", "/proc/self/fdinfo");
                info!("ctx": "init_env",
                    "msg": "set SYD_PWD environment variable to /proc/self/fdinfo");
            }
        }

        if env::var_os("SYD_TTY").is_none() {
            // Set per-session environment variable TTY.
            if let Ok(name) = ttyname(std::io::stdin()).map(XPathBuf::from) {
                env::set_var("SYD_TTY", &name);
                info!("ctx": "init_env",
                    "msg": format!("set SYD_TTY environment variable to {name}"));
            } else {
                env::set_var("SYD_TTY", "/dev/null");
                info!("ctx": "init_env",
                    "msg": "set SYD_TTY environment variable to /dev/null");
            }
        }
    }

    #[expect(clippy::cognitive_complexity)]
    pub(crate) fn config_unchecked(&mut self, command: &str) -> Result<(), Errno> {
        if command.is_empty() || command == API_MAJOR_VERSION {
            Ok(())
        } else if matches!(command, "l" | "lock") {
            // Shorthands for lock:on.
            self.lock(LockState::Set)
        } else if command == "reset" {
            self.reset()
        } else if command == "dump" {
            // Lock stderr to prevent concurrent access.
            let mut stderr = std::io::stderr().lock();
            rwrite!(
                stderr,
                "{}",
                serde_json::to_string_pretty(&self)
                    .as_ref()
                    .map_or("", |v| v)
            )
        } else if command == "stat" {
            // Lock stderr to prevent concurrent access.
            let mut stderr = std::io::stderr().lock();
            rwrite!(stderr, "{self}")
        } else if let Some(name) = command.strip_prefix("include_profile ") {
            // Handle include_profile directive here as well for convenience.
            // This way, we can include profile from within other profiles.
            self.parse_profile(name).or(Err(Errno::ENOENT))
        } else if let Some(varval) = command.strip_prefix("setenv!") {
            self.handle_setenv(varval)
        } else if let Some(var) = command.strip_prefix("unsetenv!") {
            self.handle_unsetenv(var)
        } else if command == "clearenv!" {
            self.handle_clearenv()
        } else if let Some(command) = command.strip_prefix("passenv") {
            self.handle_passenv(command)
        } else if let Some(state) = command.strip_prefix("lock:") {
            self.lock(LockState::from_str(&self.expand_env(state)?)?)
        } else if let Some(command) = command.strip_prefix("timeout:") {
            self.handle_timeout_command(command)
        } else if let Some(command) = command.strip_prefix("time") {
            self.handle_time_command(command)
        } else if let Some(command) = command.strip_prefix("cmd/") {
            self.handle_sandbox_command(command)
        } else if let Some(command) = command.strip_prefix("config/") {
            self.handle_config_command(command)
        } else if let Some(command) = command.strip_prefix("sandbox/") {
            self.handle_sandbox_config(command)
        } else if let Some(command) = command.strip_prefix("default/") {
            self.handle_default_config(command)
        } else if let Some(command) = command.strip_prefix("log/") {
            self.handle_log_config(command)
        } else if let Some(command) = command.strip_prefix("allow/ioctl") {
            self.handle_ioctl_config(command, false)
        } else if let Some(command) = command.strip_prefix("deny/ioctl") {
            self.handle_ioctl_config(command, true)
        } else if let Some(addr) = command.strip_prefix("ipc:") {
            self.handle_ipc_address(addr)
        } else if let Some(command) = command.strip_prefix("ipc/") {
            self.handle_ipc_config(command)
        } else if let Some(command) = command.strip_prefix("mem/") {
            self.handle_mem_config(command)
        } else if let Some(command) = command.strip_prefix("pid/") {
            self.handle_pid_config(command)
        } else if let Some(command) = command.strip_prefix("proxy/") {
            self.handle_proxy_config(command)
        } else if let Some(command) = command.strip_prefix("pty/") {
            self.handle_pty_config(command)
        } else if let Some(command) = command.strip_prefix("rlimit/") {
            self.handle_rlimit_config(command)
        } else if let Some(command) = command.strip_prefix("tpe/") {
            self.handle_tpe_config(command)
        } else if let Some(command) = command.strip_prefix("trace/") {
            self.handle_trace_config(command)
        } else if let Some(command) = command.strip_prefix("unshare/") {
            self.handle_unshare_config(command)
        } else if let Some(command) = command.strip_prefix("uts/") {
            self.handle_uts_config(command)
        } else if let Some(command) = command.strip_prefix("append") {
            self.handle_append_rules(command)
        } else if let Some(command) = command.strip_prefix("block") {
            self.handle_block_rules(command)
        } else if let Some(command) = command.strip_prefix("mask") {
            self.handle_mask_rules(command)
        } else if let Some(command) = command.strip_prefix("root") {
            self.handle_root_config(command)
        } else if let Ok(command) = parse_bind_cmd(command) {
            self.handle_bind_config(command)
        } else if let Some(command) = command.strip_prefix("crypt/") {
            self.handle_crypt_config(command)
        } else if let Some(command) = command.strip_prefix("crypt") {
            self.handle_crypt_rules(command)
        } else if let Some(command) = command.strip_prefix("segvguard/") {
            self.handle_segvguard_config(command)
        } else if let Ok(command) = parse_force_cmd(command) {
            self.handle_force_rule_config(command)
        } else if let Ok(command) = parse_setid_cmd(command) {
            self.handle_setid_rule_config(command)
        } else if let Ok(command) = parse_netlink_cmd(command) {
            self.handle_netlink_config(command)
        } else if let Ok(command) = parse_landlock_cmd(command) {
            self.handle_lock_rule_config(command)
        } else if let Ok(command) = parse_fs_cmd(command) {
            self.handle_fs_rule_config(command)
        } else if let Ok(command) = parse_scmp_cmd(command) {
            self.handle_scmp_rule_config(command)
        } else {
            Err(Errno::EINVAL)
        }
    }

    fn handle_setenv(&self, varval: &str) -> Result<(), Errno> {
        let mut split = varval.splitn(2, '=');
        let var = split.next().ok_or(Errno::EINVAL)?;
        let val = split.next().ok_or(Errno::EINVAL)?;

        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        // Do not allow blank variables.
        if var.trim().is_empty() {
            return Err(Errno::EINVAL);
        }

        // Do not allow oversized variables.
        if var.len() > PATH_MAX {
            return Err(Errno::ENAMETOOLONG);
        }

        // Do not allow setting internal environment vars.
        if is_prefix(var.as_bytes(), b"SYD_") {
            return Err(Errno::EPERM);
        }

        // Expand environment variables in value.
        let val = self.expand_env(val)?;
        let val = OsStr::from_bytes(val.as_bytes());

        env::set_var(var, val);

        Ok(())
    }

    fn handle_unsetenv(&self, var: &str) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        // Do not allow blank variables.
        if var.trim().is_empty() {
            return Err(Errno::EINVAL);
        }

        // Do not allow oversized variables.
        if var.len() > PATH_MAX {
            return Err(Errno::ENAMETOOLONG);
        }

        // Do not allow unsetting internal environment vars.
        if is_prefix(var.as_bytes(), b"SYD_") {
            return Err(Errno::EPERM);
        }

        env::remove_var(var);

        Ok(())
    }

    fn handle_clearenv(&self) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        for (name, _) in env::vars_os() {
            // Do not clear internal environment vars.
            if is_prefix(name.as_bytes(), b"SYD_") {
                continue;
            }
            env::remove_var(name);
        }

        Ok(())
    }

    fn handle_passenv(&mut self, command: &str) -> Result<(), Errno> {
        // Check the first character (^ = - for maps).
        match command.chars().nth(0) {
            Some('+') => self.env_add_pass(&command[1..]),
            Some('-') => self.env_del_pass(&command[1..]),
            Some('^') => self.env_del_pass(&command[1..]),
            _ => Err(Errno::EINVAL),
        }
    }

    /// Add pass-through environment variables.
    pub fn env_add_pass(&mut self, var: &str) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        for var in var.split(',') {
            // Do not allow blank variables.
            if var.trim().is_empty() {
                return Err(Errno::EINVAL);
            }

            // Do not allow oversized variables.
            if var.len() > PATH_MAX {
                return Err(Errno::ENAMETOOLONG);
            }

            // Do not allow passing-through internal environment vars.
            if is_prefix(var.as_bytes(), b"SYD_") {
                return Err(Errno::EPERM);
            }

            if let Some(set) = self.pass_env.as_mut() {
                set.insert(var.to_string().into());
            } else {
                let mut set = SydHashSet::default();
                set.insert(var.to_string().into());
                self.pass_env = Some(set);
            }
        }

        Ok(())
    }

    /// Delete pass-through environment variables.
    pub fn env_del_pass(&mut self, var: &str) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        for var in var.split(',') {
            // Do not allow blank variables.
            if var.trim().is_empty() {
                return Err(Errno::EINVAL);
            }

            // Do not allow passing-through internal environment vars.
            if is_prefix(var.as_bytes(), b"SYD_") {
                return Err(Errno::EPERM);
            }

            if let Some(set) = self.pass_env.as_mut() {
                set.remove(OsStr::new(var));
                if set.is_empty() {
                    self.pass_env = None;
                }
            }
        }

        Ok(())
    }

    fn handle_netalias_config(&mut self, command: &ScmpCmd, alias: &str) -> Result<(), Errno> {
        let mut split = alias.splitn(2, ['!', '@']);
        let host = split
            .next()
            .ok_or(Errno::EINVAL)?
            .trim()
            .to_ascii_lowercase();
        let port = split.next().ok_or(Errno::EINVAL)?;
        if let Some(addr_vec) = MAP_NETALIAS.get(host.as_str()) {
            for addr in addr_vec {
                let mut command = command.clone();
                command.pat = ScmpPattern::Addr(format!("{addr}!{port}"));
                self.handle_scmp_rule_config(command)?;
            }
            Ok(())
        } else {
            // This should never happen,
            // but let's handle it safely anyway.
            Err(Errno::EAFNOSUPPORT)
        }
    }

    fn handle_uts_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("host:") {
            self.set_uts_host(value)?;
        } else if let Some(value) = command.strip_prefix("domain:") {
            self.set_uts_domain(value)?;
        } else if let Some(value) = command.strip_prefix("version:") {
            self.set_uts_version(value)?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_append_rules(&mut self, command: &str) -> Result<(), Errno> {
        // Check command length is at least 2 parameters.
        if command.len() < 2 {
            return Err(Errno::EINVAL);
        }
        // Check the first character
        match command.chars().nth(0) {
            Some('+') => self.rule_add_append(&command[1..]),
            Some('-') => self.rule_del_append(&command[1..]),
            Some('^') => self.rule_rem_append(&command[1..]),
            _ => Err(Errno::EINVAL),
        }
    }

    fn handle_block_rules(&mut self, command: &str) -> Result<(), Errno> {
        // Check the first character.
        match command.chars().nth(0) {
            Some('+') => self.rule_add_block(&command[1..]),
            Some('-') => self.rule_del_block(&command[1..]),
            Some('^') => self.rule_rem_block(&command[1..]),
            Some('!') => self.rule_agg_block(&command[1..]),
            _ => Err(Errno::EINVAL),
        }
    }

    fn handle_crypt_rules(&mut self, command: &str) -> Result<(), Errno> {
        // Check command length is at least 2 parameters.
        if command.len() < 2 {
            return Err(Errno::EINVAL);
        }
        // Check the first character
        match command.chars().nth(0) {
            Some('+') => self.rule_add_crypt(&command[1..]),
            Some('-') => self.rule_del_crypt(&command[1..]),
            Some('^') => self.rule_rem_crypt(&command[1..]),
            _ => Err(Errno::EINVAL),
        }
    }

    fn handle_mask_rules(&mut self, command: &str) -> Result<(), Errno> {
        // Check the first character which is the mask operator.
        match command.chars().nth(0) {
            Some('+') if !command[1..].is_empty() => {
                let mut split = command[1..].splitn(3, ':');
                let pattern = split.next().ok_or(Errno::EINVAL)?;
                let mask_all = split.next(); // optional, defaults to /dev/null.
                let mask_dir = split.next(); // ditto.
                self.rule_add_mask(pattern, mask_all, mask_dir)
            }
            Some('-') if !command[1..].is_empty() => self.rule_del_mask(&command[1..]),
            Some('^') if command[1..].is_empty() => self.rule_rem_mask(),
            _ => Err(Errno::EINVAL),
        }
    }

    fn handle_root_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(root) = command.strip_prefix(':') {
            let root = self.decode_hex(&self.expand_env(root)?);
            let is_ramfs = root.is_equal(b"r") || root.is_equal(b"ram") || root.is_equal(b"ramfs");
            let is_tmpfs = root.is_equal(b"t") || root.is_equal(b"tmp") || root.is_equal(b"tmpfs");
            let is_unset = root.is_equal(b"none") || root.is_equal(b"off");
            if !is_ramfs && !is_tmpfs && !is_unset && (root.is_relative() || root.has_parent_dot())
            {
                // SAFETY:
                // 1. Do not allow relative paths.
                // 2. Do not allow paths with `..' component.
                return Err(Errno::EINVAL);
            }
            if self.oci {
                return Err(Errno::EOPNOTSUPP);
            }
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            if is_unset {
                self.root = None;
            } else if is_ramfs {
                self.root = Some("ramfs".into());
            } else if is_tmpfs {
                self.root = Some("tmpfs".into());
            } else {
                self.root = Some(root);
            }
        } else if let Some(value) = command.strip_prefix("/map:") {
            if self.oci {
                return Err(Errno::EOPNOTSUPP);
            }
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            self.set_flag(Flags::FL_MAP_ROOT, value)?;
        } else if let Some(value) = command.strip_prefix("/fake:") {
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            self.set_flag(Flags::FL_FAKE_ROOT, value)?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_config_command(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("expand:") {
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            let value = self.expand_env(value)?;
            let value = str2secs(&value)?;
            if cfg!(target_os = "android") && !value.is_zero() {
                // bionic libc does not support wordexp(3).
                return Err(Errno::EOPNOTSUPP);
            }
            self.config_expand_timeout = value;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_sandbox_config(&mut self, command: &str) -> Result<(), Errno> {
        let mut caps = Capability::empty();

        #[expect(clippy::arithmetic_side_effects)]
        let state = match command.chars().last() {
            Some('?') => {
                for cap in command[..command.len() - 1].split(',') {
                    caps.insert(Capability::from_str(cap)?);
                }

                None
            }
            _ => {
                let mut split = command.splitn(2, ':');
                for cap in split.next().ok_or(Errno::EINVAL)?.split(',') {
                    caps.insert(Capability::from_str(cap)?);
                }

                Some(strbool(
                    &self.expand_env(split.next().ok_or(Errno::EINVAL)?)?,
                )?)
            }
        };

        if let Some(state) = state {
            // Setting Capability with :{on,off}.
            if self.oci && !caps.is_oci() {
                return Err(Errno::EOPNOTSUPP);
            }
            if self.is_running() && caps.is_startup() {
                return Err(Errno::EBUSY);
            }
            if state {
                self.state.insert(caps);
            } else {
                self.state.remove(caps);
            }
        } else if !self.state.contains(caps) {
            // Querying for Capability with ?.
            return Err(Errno::ENOENT);
        }

        Ok(()) // set|query successful.
    }

    #[expect(clippy::cognitive_complexity)]
    fn handle_sandbox_command(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(command) = command.strip_prefix("exec!") {
            // SAFETY: Do not accept commands at startup.
            if !self.is_running() {
                return Err(Errno::ECANCELED);
            }

            // Splitting the command using the Unit Separator character
            let parts: Vec<&str> = command.split('\x1F').collect();

            // Paranoid checks:
            // Ensure the command and its arguments are not empty.
            if parts.is_empty() || parts[0].is_empty() {
                error!("ctx": "check_sandbox_program",
                    "msg": "Invalid cmd/exec program");
                return Err(Errno::EINVAL);
            }

            let program = parts[0];
            let args = &parts[1..];

            // SAFETY: We're spawning a child outside the sandbox here.
            // We should take some precautions so that the process to be
            // executed has a sane environment. That's why we change the
            // current directory to /, close the standard input, and
            // execute the process in a new process group as a daemon.
            let mut command = Command::new(program);
            command
                .args(args)
                .current_dir("/")
                .stdin(Stdio::null())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit());

            // SAFETY:
            // 1. Create a new session.
            // 2. Set umask(2) to a sane value.
            // 3. Ensure no file descriptors are leaked
            //    from the Syd process into the new process.
            unsafe {
                command.pre_exec(|| {
                    setsid()?;
                    umask(Mode::from_bits_truncate(0o077));
                    closefrom((libc::STDERR_FILENO + 1) as libc::c_uint)?;
                    Ok(())
                })
            };

            match command.spawn() {
                Ok(_) => Ok(()),
                Err(error) => {
                    let errno = err2no(&error);
                    error!("ctx": "spawn_sandbox_program",
                        "cmd": program, "args": args,
                        "msg": format!("cmd/exec program spawn error: {errno}"),
                        "err": errno as i32);
                    Err(errno)
                }
            }
        } else {
            Err(Errno::ENOENT)
        }
    }

    fn handle_default_config(&mut self, command: &str) -> Result<(), Errno> {
        // Split the command into two parts: items and action.
        let mut split = command.splitn(2, ':');
        let items = split.next().ok_or(Errno::EINVAL)?;

        // Validate action and expand environment variables.
        let action = split.next().ok_or(Errno::EINVAL)?;
        let action = self.expand_env(action)?;
        let action = Action::from_str(&action)?;

        let mut caps = Capability::empty();
        let mut cset = false;
        for item in items.split(',') {
            // Handle special cases:
            // default/block, default/lock, and default/segvguard.
            match item {
                "block" => {
                    if action == Action::Allow {
                        return Err(Errno::EINVAL);
                    }
                    self.set_net_block_act(action);
                    cset = true;
                    continue;
                }
                "lock" => {
                    if !matches!(action, Action::Kill | Action::Deny | Action::Warn) {
                        return Err(Errno::EINVAL);
                    }
                    if self.is_running() {
                        return Err(Errno::EBUSY);
                    }
                    self.set_landlock_act(action);
                    cset = true;
                    continue;
                }
                "segvguard" => {
                    if action == Action::Allow {
                        return Err(Errno::EINVAL);
                    }
                    self.set_segvguard_act(action);
                    cset = true;
                    continue;
                }
                _ => {}
            }

            let cap = Capability::from_str(item)?;
            caps.insert(cap);
        }

        // Reject empty capabilities.
        if caps.is_empty() {
            return if cset { Ok(()) } else { Err(Errno::EINVAL) };
        }

        for cap in caps {
            // Reject invalid actions based on capability.
            match (cap, action) {
                (
                    Capability::CAP_MEM | Capability::CAP_FORCE | Capability::CAP_TPE,
                    Action::Allow,
                ) => return Err(Errno::EINVAL),
                (Capability::CAP_PID, Action::Allow | Action::Deny | Action::Panic) => {
                    return Err(Errno::EINVAL)
                }
                _ => {}
            };

            self.set_default_action(cap, action);
        }

        Ok(())
    }

    fn handle_log_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("level:") {
            let level = self.expand_env(value)?;
            let level = level.as_bytes();
            let level = if let Ok(level) = btoi::<u8>(level) {
                if level < LogLevel::Emergent.as_u8() || level > LogLevel::Debug.as_u8() {
                    return Err(Errno::EINVAL);
                }
                level.into()
            } else if is_equal(level, b"emerg") {
                LogLevel::Emergent
            } else if is_equal(level, b"alert") {
                LogLevel::Alert
            } else if is_equal(level, b"crit") {
                LogLevel::Crit
            } else if is_equal(level, b"error") {
                LogLevel::Err
            } else if is_equal(level, b"warn") {
                LogLevel::Warn
            } else if is_equal(level, b"notice") {
                LogLevel::Notice
            } else if is_equal(level, b"info") {
                LogLevel::Info
            } else if is_equal(level, b"debug") {
                LogLevel::Debug
            } else {
                return Err(Errno::EINVAL);
            };
            env::set_var(ENV_LOG, level.as_u8().to_string());
            #[cfg(feature = "log")]
            if let Some(sys) = crate::syslog::global_syslog() {
                sys.set_loglevel(level.as_u8());
            }
        } else if let Some(value) = command.strip_prefix("lock/") {
            self.handle_log_lock_config(value)?;
        } else if let Some(value) = command.strip_prefix("verbose:") {
            let value = self.expand_env(value)?;
            let value = value
                .parse::<u8>()
                .or(Err(Errno::EINVAL))?
                .min(Self::LOG_MAX);
            self.verbose = value;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_log_lock_config(&mut self, command: &str) -> Result<(), Errno> {
        // Multiple options may be specified at once as a comma-delimited list.
        let mut split = command.splitn(2, ':');

        let flags = split.next().ok_or(Errno::EINVAL)?;
        let flags = LandlockPolicy::parse_restrict_self_flags(flags.as_bytes(), false)?;

        let value = split.next().ok_or(Errno::EINVAL)?;
        let value = strbool(&self.expand_env(value)?)?;

        // landlock(7) rules must only be passed at startup.
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        // Ensure landlock(7) rules are initialized.
        self.lock_rules
            .get_or_insert_with(Sandbox::default_lock_rules);
        let rules = self.lock_rules.as_mut().ok_or(Errno::EFAULT)?;

        if value {
            rules.restrict_self_flags.insert(flags);
        } else {
            rules.restrict_self_flags.remove(flags);
        }

        Ok(())
    }

    fn handle_ioctl_config(&mut self, cmd: &str, deny: bool) -> Result<(), Errno> {
        let (val, add) = if let Some(val) = cmd.strip_prefix("+") {
            (val, true)
        } else if let Some(val) = cmd.strip_prefix("-") {
            (val, false)
        } else if let Some(val) = cmd.strip_prefix("^") {
            (val, false)
        } else {
            return Err(Errno::EINVAL);
        };

        let mut reqs = vec![];
        for val in val.split(',') {
            let (val, missing_ok) = if let Some(val) = val.strip_suffix('!') {
                (val, true)
            } else {
                (val, false)
            };
            match self.expand_ioctl(val) {
                Ok(req) if req.is_empty() => {
                    unreachable!("BUG: expand_ioctl returned an empty vector, report a bug!")
                }
                Ok(req) => {
                    for (req, arch) in req {
                        reqs.push((req, arch));
                    }
                }
                Err(Errno::EINVAL) if missing_ok => {}
                Err(errno) => return Err(errno),
            }
        }

        if reqs.is_empty() {
            return Ok(());
        }

        if add {
            for (req, arch) in reqs {
                self.ioctl_set.insert((req, arch), deny)?;
            }
        } else {
            for (req, arch) in reqs {
                self.ioctl_set.remove(&(req, arch));
            }
        }

        Ok(())
    }

    fn handle_ipc_address(&mut self, addr: &str) -> Result<(), Errno> {
        // IPC socket is startup-only.
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        // 1. Expand environment variables.
        // 2. Decode hex.
        let addr = self.decode_hex(&self.expand_env(addr)?);

        // Use ipc:none or ipc:off to disable IPC.
        if addr.is_empty() {
            return Err(Errno::EINVAL);
        } else if addr.is_equal(b"none") || addr.is_equal(b"off") {
            self.ipc = None;
        } else if self.oci {
            return Err(Errno::EOPNOTSUPP);
        } else {
            // Note, we do not require an absolute pathname here,
            // because it is easy to hit UNIX_PATH_MAX which is
            // merely 108 bytes unlike PATH_MAX which is 4096 bytes.
            self.ipc = Some(addr);
        }

        Ok(())
    }

    fn handle_ipc_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("uid:") {
            let uid = self.expand_env(value)?;
            self.ipc_uid = if !matches!(uid.as_ref(), "none" | "off") {
                Some(parse_user(&uid)?)
            } else {
                None
            };
        } else if let Some(value) = command.strip_prefix("gid:") {
            let gid = self.expand_env(value)?;
            self.ipc_gid = if !matches!(gid.as_ref(), "none" | "off") {
                Some(parse_group(&gid)?)
            } else {
                None
            };
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_mem_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("max:") {
            self.mem_max = parse_size::Config::new()
                .with_binary()
                .parse_size(&*self.expand_env(value)?)
                .or(Err(Errno::EINVAL))?;
        } else if let Some(value) = command.strip_prefix("vm_max:") {
            self.mem_vm_max = parse_size::Config::new()
                .with_binary()
                .parse_size(&*self.expand_env(value)?)
                .or(Err(Errno::EINVAL))?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_pid_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("max:") {
            self.pid_max = self
                .expand_env(value)?
                .parse::<u64>()
                .or(Err(Errno::EINVAL))?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_proxy_config(&mut self, command: &str) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        } else if let Some(value) = command.strip_prefix("port:") {
            self.proxy_port = self
                .expand_env(value)?
                .parse::<u16>()
                .or(Err(Errno::EINVAL))?;
        } else if let Some(value) = command.strip_prefix("ext/port:") {
            self.proxy_ext_port = self
                .expand_env(value)?
                .parse::<u16>()
                .or(Err(Errno::EINVAL))?;
        } else if let Some(value) = command.strip_prefix("addr:") {
            self.proxy_addr = self
                .expand_env(value)?
                .parse::<IpAddr>()
                .or(Err(Errno::EINVAL))?;
        } else if let Some(value) = command.strip_prefix("ext/host:") {
            // Resolve DNS using system resolver if parsing as IP fails.
            self.proxy_ext_addr = match self.expand_env(value)?.parse::<IpAddr>() {
                Ok(addr) => addr,
                Err(_) => resolve_rand(value, None)?,
            };
        } else if let Some(value) = command.strip_prefix("ext/unix:") {
            // 1. Expand environment variables.
            // 2. Decode hex.
            // 3. Clean consecutive slashes.
            let mut unix = self.decode_hex(&self.expand_env(value)?);
            unix.clean_consecutive_slashes();

            // Reject empty pathnames.
            if unix.is_empty() {
                return Err(Errno::EINVAL);
            }

            // Note, we do not require an absolute pathname here,
            // because it is easy to hit UNIX_PATH_MAX which is
            // merely 108 bytes unlike PATH_MAX which is 4096 bytes.
            self.proxy_ext_unix = Some(unix);
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_pty_config(&mut self, command: &str) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        } else if let Some(value) = command.strip_prefix("row:") {
            let value = self.expand_env(value)?;
            self.pty_ws_x = if value == "none" {
                None
            } else {
                Some(value.parse::<libc::c_ushort>().or(Err(Errno::EINVAL))?)
            };
        } else if let Some(value) = command.strip_prefix("x:") {
            let value = self.expand_env(value)?;
            self.pty_ws_x = if value == "none" {
                None
            } else {
                Some(value.parse::<libc::c_ushort>().or(Err(Errno::EINVAL))?)
            };
        } else if let Some(value) = command.strip_prefix("col:") {
            let value = self.expand_env(value)?;
            self.pty_ws_y = if value == "none" {
                None
            } else {
                Some(value.parse::<libc::c_ushort>().or(Err(Errno::EINVAL))?)
            };
        } else if let Some(value) = command.strip_prefix("y:") {
            let value = self.expand_env(value)?;
            self.pty_ws_y = if value == "none" {
                None
            } else {
                Some(value.parse::<libc::c_ushort>().or(Err(Errno::EINVAL))?)
            };
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_rlimit_config(&mut self, command: &str) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        } else if let Some(value) = command.strip_prefix("as:") {
            self.rlimit_as = self.parse_rlimit_size(value)?;
        } else if let Some(value) = command.strip_prefix("core:") {
            self.rlimit_core = self.parse_rlimit_size(value)?;
        } else if let Some(value) = command.strip_prefix("cpu:") {
            self.rlimit_cpu = self.parse_rlimit_secs(value)?;
        } else if let Some(value) = command.strip_prefix("data:") {
            self.rlimit_data = self.parse_rlimit_size(value)?;
        } else if let Some(value) = command.strip_prefix("fsize:") {
            self.rlimit_fsize = self.parse_rlimit_size(value)?;
        } else if let Some(value) = command.strip_prefix("memlock:") {
            self.rlimit_memlock = self.parse_rlimit_size(value)?;
        } else if let Some(value) = command.strip_prefix("msgqueue:") {
            self.rlimit_msgqueue = self.parse_rlimit_size(value)?;
        } else if let Some(value) = command.strip_prefix("nice:") {
            self.rlimit_nice = self.parse_rlimit_nice(value)?;
        } else if let Some(value) = command.strip_prefix("nofile:") {
            self.rlimit_nofile = self.parse_rlimit_u64(value)?;
        } else if let Some(value) = command.strip_prefix("nproc:") {
            self.rlimit_nproc = self.parse_rlimit_u64(value)?;
        } else if let Some(value) = command.strip_prefix("rtprio:") {
            self.rlimit_rtprio = self.parse_rlimit_u64(value)?;
        } else if let Some(value) = command.strip_prefix("rttime:") {
            self.rlimit_rttime = self.parse_rlimit_micros(value)?;
        } else if let Some(value) = command.strip_prefix("sigpending:") {
            self.rlimit_sigpending = self.parse_rlimit_u64(value)?;
        } else if let Some(value) = command.strip_prefix("stack:") {
            self.rlimit_stack = self.parse_rlimit_size(value)?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_tpe_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("gid:") {
            self.tpe_gid = if value == "none" {
                None
            } else {
                Some(Gid::from_raw(
                    self.expand_env(value)?
                        .parse::<libc::gid_t>()
                        .or(Err(Errno::EINVAL))?,
                ))
            };
        } else if let Some(value) = command.strip_prefix("negate:") {
            self.set_flag(Flags::FL_TPE_NEGATE, value)?;
        } else if let Some(value) = command.strip_prefix("root_owned:") {
            self.set_flag(Flags::FL_TPE_ROOT_OWNED, value)?;
        } else if let Some(value) = command.strip_prefix("user_owned:") {
            self.set_flag(Flags::FL_TPE_USER_OWNED, value)?;
        } else if let Some(value) = command.strip_prefix("root_mount:") {
            self.set_flag(Flags::FL_TPE_ROOT_MOUNT, value)?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_time_command(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix(":") {
            let time = self.parse_time(value)?;
            if self.oci {
                Err(Errno::EOPNOTSUPP)
            } else if self.is_running() {
                Err(Errno::EBUSY)
            } else {
                self.boottime = time;
                self.monotime = time;
                Ok(())
            }
        } else if let Some(value) = command.strip_prefix("/boot:") {
            let time = self.parse_time(value)?;
            if self.oci {
                Err(Errno::EOPNOTSUPP)
            } else if self.is_running() {
                Err(Errno::EBUSY)
            } else {
                self.boottime = time;
                Ok(())
            }
        } else if let Some(value) = command.strip_prefix("/mono:") {
            let time = self.parse_time(value)?;
            if self.oci {
                Err(Errno::EOPNOTSUPP)
            } else if self.is_running() {
                Err(Errno::EBUSY)
            } else {
                self.monotime = time;
                Ok(())
            }
        } else {
            Err(Errno::EINVAL)
        }
    }

    fn handle_timeout_command(&mut self, value: &str) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        self.tmout = self.parse_timeout(value)?;

        Ok(())
    }

    fn parse_time(&self, value: &str) -> Result<Option<i64>, Errno> {
        let value = self.expand_env(value)?;
        if value == "none" || value == "off" {
            Ok(None)
        } else {
            Ok(Some(value.parse::<i64>().or(Err(Errno::EINVAL))?))
        }
    }

    fn parse_timeout(&self, value: &str) -> Result<Option<Duration>, Errno> {
        let value = self.expand_env(value)?;
        if value == "none" || value == "off" {
            Ok(None)
        } else {
            Ok(Some(str2secs(&value)?))
        }
    }

    fn parse_rlimit_u64(&self, value: &str) -> Result<Option<rlim_t>, Errno> {
        let value = self.expand_env(value)?;
        if value == "none" || value == "off" {
            Ok(None)
        } else if value == "inf" {
            Ok(Some(RLIM_INFINITY))
        } else {
            // Conversion is necessary on 32-bit.
            #[expect(clippy::useless_conversion)]
            Ok(Some(
                str2u64(value.as_bytes())?
                    .try_into()
                    .or(Err(Errno::EINVAL))?,
            ))
        }
    }

    fn parse_rlimit_size(&self, value: &str) -> Result<Option<rlim_t>, Errno> {
        let value = self.expand_env(value)?;
        if value == "none" || value == "off" {
            Ok(None)
        } else if value == "inf" {
            Ok(Some(RLIM_INFINITY))
        } else {
            // Conversion is necessary on 32-bit.
            #[expect(clippy::useless_conversion)]
            Ok(Some(
                parse_size::Config::new()
                    .with_binary()
                    .parse_size(value.as_ref())
                    .or(Err(Errno::EINVAL))?
                    .try_into()
                    .or(Err(Errno::EINVAL))?,
            ))
        }
    }

    fn parse_rlimit_secs(&self, value: &str) -> Result<Option<rlim_t>, Errno> {
        let value = self.expand_env(value)?;
        if value == "none" || value == "off" {
            Ok(None)
        } else if value == "inf" {
            Ok(Some(RLIM_INFINITY))
        } else {
            Ok(Some(
                str2secs(&value)?
                    .as_secs()
                    .try_into()
                    .or(Err(Errno::EINVAL))?,
            ))
        }
    }

    fn parse_rlimit_micros(&self, value: &str) -> Result<Option<rlim_t>, Errno> {
        let value = self.expand_env(value)?;
        if value == "none" || value == "off" {
            Ok(None)
        } else if value == "inf" {
            Ok(Some(RLIM_INFINITY))
        } else {
            Ok(Some(
                str2micros(&value)?
                    .as_micros()
                    .try_into()
                    .or(Err(Errno::EINVAL))?,
            ))
        }
    }

    fn parse_rlimit_nice(&self, value: &str) -> Result<Option<rlim_t>, Errno> {
        let value = self.expand_env(value)?;
        if value == "none" || value == "off" {
            Ok(None)
        } else if value == "inf" {
            Ok(Some(RLIM_INFINITY))
        } else {
            let mut nice = str2i64(value.as_bytes())?;
            if !(-20..=20).contains(&nice) {
                return Err(Errno::EINVAL);
            }
            nice = 20i64.checked_sub(nice).ok_or(Errno::EINVAL)?;
            Ok(Some(nice.try_into().or(Err(Errno::EINVAL))?))
        }
    }

    #[expect(clippy::cognitive_complexity)]
    fn handle_trace_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("exit_wait_all:") {
            self.set_flag(Flags::FL_EXIT_WAIT_ALL, value)?;
        } else if let Some(value) = command.strip_prefix("allow_unsafe_bind:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_BIND, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_chown:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CHOWN, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_chroot:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CHROOT, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_pivot_root:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PIVOT_ROOT, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_cpu:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CPU, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_dumpable:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_DUMPABLE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_any_addr:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_ANY_ADDR, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_ldso:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_LDSO, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_libc:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_LIBC, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_memory:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_MEMORY, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_nopie:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_NOPIE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_null:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_NULL, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_stack:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_STACK, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_script:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_SCRIPT, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_interactive:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_INTERACTIVE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_exec_speculative:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC_SPECULATIVE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_keyring:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_KEYRING, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_pkey:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PKEY, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_proc_files:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PROC_FILES, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_caps:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CAPS, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_cap_fixup:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CAP_FIXUP, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_env:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_ENV, value)?
        } else if let Some(value) = command.strip_prefix("allow_safe_bind:") {
            self.set_flag(Flags::FL_ALLOW_SAFE_BIND, value)?
        } else if let Some(value) = command.strip_prefix("allow_safe_kcapi:") {
            self.set_flag(Flags::FL_ALLOW_SAFE_KCAPI, value)?
        } else if let Some(value) = command.strip_prefix("allow_safe_setuid:") {
            self.set_flag(Flags::FL_ALLOW_SAFE_SETUID, value)?
        } else if let Some(value) = command.strip_prefix("allow_safe_setgid:") {
            self.set_flag(Flags::FL_ALLOW_SAFE_SETGID, value)?
        } else if let Some(value) = command.strip_prefix("allow_safe_syslog:") {
            self.set_flag(Flags::FL_ALLOW_SAFE_SYSLOG, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsupp_socket:") {
            self.set_flag(Flags::FL_ALLOW_UNSUPP_SOCKET, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_socket:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SOCKET, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_setsockopt:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SETSOCKOPT, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_syslog:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SYSLOG, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_page_cache:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PAGE_CACHE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_nice:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_NICE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_personality:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PERSONALITY, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_prctl:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PRCTL, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_prlimit:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PRLIMIT, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_namespace:") {
            self.set_nsflags(value)?;
        } else if let Some(value) = command.strip_prefix("allow_unsafe_oob:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_OOB, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_deprecated:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_DEPRECATED, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_cbpf:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CBPF, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_ebpf:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EBPF, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_kptr:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_KPTR, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_madvise:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MADVISE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_mbind:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MBIND, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_nocookie:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_NOCOOKIE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_nomseal:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_NOMSEAL, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_noxom:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_NOXOM, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_perf:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PERF, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_pipe:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PIPE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_ptrace:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PTRACE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_sigreturn:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SIGRETURN, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_time:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_TIME, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_open_path:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_OPEN_PATH, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_open_kfd:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_OPEN_KFD, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_mkbdev:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MKBDEV, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_mkcdev:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MKCDEV, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_stat_bdev:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_STAT_BDEV, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_stat_cdev:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_STAT_CDEV, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_notify_bdev:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_NOTIFY_BDEV, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_notify_cdev:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_NOTIFY_CDEV, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_create:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CREATE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_hardlinks:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_HARDLINKS, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_symlinks:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SYMLINKS, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_magiclinks:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MAGICLINKS, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_machine_id:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MACHINE_ID, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_proc_pid_status:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PROC_PID_STATUS, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_filename:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_FILENAME, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_uring:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_IOURING, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_msgqueue:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MSGQUEUE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_shm:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SHM, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_perm_msgqueue:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PERM_MSGQUEUE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_perm_shm:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PERM_SHM, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_rseq:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_RSEQ, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_sync:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SYNC, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_sysinfo:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SYSINFO, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_uname:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_UNAME, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_vmsplice:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_VMSPLICE, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_memfd:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MEMFD, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_xattr:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_XATTR, value)?
        } else if let Some(value) = command.strip_prefix("deny_dotdot:") {
            self.set_flag(Flags::FL_DENY_DOTDOT, value)?
        } else if let Some(value) = command.strip_prefix("deny_tsc:") {
            self.set_flag(Flags::FL_DENY_TSC, value)?
        } else if let Some(value) = command.strip_prefix("deny_vdso:") {
            self.set_flag(Flags::FL_DENY_VDSO, value)?
        } else if let Some(value) = command.strip_prefix("deny_exec_elf32:") {
            self.set_flag(Flags::FL_DENY_EXEC_ELF32, value)?
        } else if let Some(value) = command.strip_prefix("deny_exec_elf_dynamic:") {
            self.set_flag(Flags::FL_DENY_EXEC_ELF_DYNAMIC, value)?
        } else if let Some(value) = command.strip_prefix("deny_exec_elf_static:") {
            self.set_flag(Flags::FL_DENY_EXEC_ELF_STATIC, value)?
        } else if let Some(value) = command.strip_prefix("deny_exec_script:") {
            self.set_flag(Flags::FL_DENY_EXEC_SCRIPT, value)?
        } else if let Some(value) = command.strip_prefix("force_cloexec:") {
            self.set_flag(Flags::FL_FORCE_CLOEXEC, value)?
        } else if let Some(value) = command.strip_prefix("force_rand_fd:") {
            self.set_flag(Flags::FL_FORCE_RAND_FD, value)?
        } else if let Some(value) = command.strip_prefix("force_ro_open:") {
            self.set_flag(Flags::FL_FORCE_RO_OPEN, value)?
        } else if let Some(value) = command.strip_prefix("force_local_net:") {
            self.set_flag(Flags::FL_FORCE_LOCAL_NET, value)?
        } else if let Some(value) = command.strip_prefix("force_no_symlinks:") {
            self.set_flag(Flags::FL_FORCE_NO_SYMLINKS, value)?
        } else if let Some(value) = command.strip_prefix("force_no_magiclinks:") {
            self.set_flag(Flags::FL_FORCE_NO_MAGICLINKS, value)?
        } else if let Some(value) = command.strip_prefix("force_no_xdev:") {
            self.set_flag(Flags::FL_FORCE_NO_XDEV, value)?
        } else if let Some(value) = command.strip_prefix("sync_seccomp:") {
            self.set_flag(Flags::FL_SYNC_SCMP, value)?
        } else if let Some(value) = command.strip_prefix("force_umask:") {
            // Note, 0 is a valid umask so we'd rather disable with -1 or strbools.
            let umask = match self.expand_env(value)?.as_ref() {
                "-1" | "off" | "f" | "fa" | "fal" | "fals" | "false" | "✗" => None,
                _ => Some(
                    Mode::from_bits(libc::mode_t::from_str_radix(value, 8).or(Err(Errno::EINVAL))?)
                        .ok_or(Errno::EINVAL)?,
                ),
            };
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            self.umask = umask;
        } else if let Some(value) = command.strip_prefix("memory_access:") {
            let value = match self.expand_env(value)?.as_ref() {
                "0" => 0,
                "1" => 1,
                "2" => 2,
                _ => return Err(Errno::EINVAL),
            };
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            // mode:1 -> use proc_pid_mem(5) unconditionally.
            // mode:0 -> use cross memory fallback to proc_pid_mem(5).
            // mode:2 -> use cross memory unconditionally (default).
            PROC_PID_MEM_FORCE.store(value == 1, std::sync::atomic::Ordering::Relaxed);
            // mode:0 -> use cross memory fallback to proc_pid_mem(5).
            // mode:1 -> use proc_pid_mem(5) unconditionally.
            // mode:2 -> use cross memory unconditionally (default).
            PROC_PID_MEM_FBACK.store(value == 0, std::sync::atomic::Ordering::Relaxed);
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_unshare_config(&mut self, command: &str) -> Result<(), Errno> {
        #[expect(clippy::arithmetic_side_effects)]
        let (flags, state) = match command.chars().last() {
            Some('?') => {
                // Querying for Capability with ?.
                let flags = Flags::ns_from_str(&command[..command.len() - 1], false)?;
                return if self.flags.contains(flags) {
                    Ok(())
                } else {
                    Err(Errno::ENOENT)
                };
            }
            _ => {
                // Setting Capability with :{on,off}.
                let mut splits = command.splitn(2, ':');
                let flags = Flags::ns_from_str(splits.next().unwrap_or(""), false)?;
                let state = self.expand_env(splits.next().ok_or(Errno::EINVAL)?)?;
                let state = strbool(&state)?;
                if self.is_running() {
                    return Err(Errno::EBUSY);
                }
                (flags, state)
            }
        };

        // Namespace creation is delegated to Youki.
        if self.oci {
            return Err(Errno::EOPNOTSUPP);
        }

        if state {
            self.flags.insert(flags);
        } else {
            self.flags.remove(flags);
        }

        Ok(()) // set successful.
    }

    fn handle_bind_config(&mut self, command: BindCmd) -> Result<(), Errno> {
        if !matches!(command.op, '+' | '-' | '^') {
            return Err(Errno::EINVAL);
        }
        if self.oci {
            return Err(Errno::EOPNOTSUPP);
        }
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        // Expand environment variables and decode hex in source and destination.
        let src = self.decode_hex(&self.expand_env(&command.src)?);
        let dst = self.decode_hex(&self.expand_env(&command.dst)?);

        // Validate src/dst:
        //
        // 1. Deny if dst is not absolute or any ".." in src/dst
        if dst.is_relative() || src.has_parent_dot() || dst.has_parent_dot() {
            return Err(Errno::EINVAL);
        }
        // 2. Deny if src is `proc`, mounting alternative proc(5) fs
        //    can be used to circumvent path sandboxing.
        if src.is_equal(b"proc") {
            return Err(Errno::EPERM);
        }

        let mnt = BindMount {
            src,
            dst,
            opt: command.opt,
            dat: command.dat,
        };

        match command.op {
            '+' => self.add_bind_mount(mnt),
            '-' => self.del_bind_mount(mnt),
            '^' => self.rem_bind_mount(mnt),
            _ => return Err(Errno::EINVAL),
        };

        Ok(())
    }

    fn handle_segvguard_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("expiry:") {
            let value = self.expand_env(value)?;
            self.segvguard_expiry = str2secs(&value)?;
        } else if let Some(value) = command.strip_prefix("suspension:") {
            let value = self.expand_env(value)?;
            self.segvguard_suspension = str2secs(&value)?;
        } else if let Some(value) = command.strip_prefix("maxcrashes:") {
            let value = self.expand_env(value)?;
            self.segvguard_maxcrashes = value.parse::<u8>().or(Err(Errno::EINVAL))?;
        } else {
            return Err(Errno::EINVAL);
        }

        Ok(())
    }

    #[expect(clippy::cognitive_complexity)]
    fn handle_crypt_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("key:") {
            // Do NOT decode HEX for integer argument!
            let value = self.expand_env(value)?;
            let value = btoi::<KeySerial>(value.as_bytes()).or(Err(Errno::EINVAL))?;
            if value == 0 {
                // Reject sentinel value.
                return Err(Errno::EINVAL);
            }
            if self.is_running() || !matches!(self.crypt_id, None | Some(Secret::Key(_, _))) {
                // SAFETY: Do not allow changing at runtime.
                return Err(Errno::EBUSY);
            }
            self.crypt_id = Some(Secret::new(value, value));
        } else if let Some(value) = command.strip_prefix("key/enc:") {
            // Do NOT decode HEX for integer argument!
            let value = self.expand_env(value)?;
            let value = btoi::<KeySerial>(value.as_bytes()).or(Err(Errno::EINVAL))?;
            if value == 0 {
                // Reject sentinel value.
                return Err(Errno::EINVAL);
            }
            if self.is_running() || !matches!(self.crypt_id, None | Some(Secret::Key(_, _))) {
                // SAFETY: Do not allow changing at runtime.
                return Err(Errno::EBUSY);
            }
            match self.crypt_id {
                None => self.crypt_id = Some(Secret::new(value, 0)),
                Some(Secret::Key(_, auth_key_id)) => {
                    self.crypt_id = Some(Secret::new(value, auth_key_id))
                }
                _ => return Err(Errno::EBUSY),
            }
        } else if let Some(value) = command.strip_prefix("key/mac:") {
            // Do NOT decode HEX for integer argument!
            let value = self.expand_env(value)?;
            let value = btoi::<KeySerial>(value.as_bytes()).or(Err(Errno::EINVAL))?;
            if value == 0 {
                // Reject sentinel value.
                return Err(Errno::EINVAL);
            }
            if self.is_running() || !matches!(self.crypt_id, None | Some(Secret::Key(_, _))) {
                // SAFETY: Do not allow changing at runtime.
                return Err(Errno::EBUSY);
            }
            match self.crypt_id {
                None => self.crypt_id = Some(Secret::new(0, value)),
                Some(Secret::Key(main_key_id, _)) => {
                    self.crypt_id = Some(Secret::new(main_key_id, value))
                }
                _ => return Err(Errno::EBUSY),
            }
        } else if let Some(value) = command.strip_prefix("tmp:") {
            let value = self.expand_env(value)?;
            if value.is_empty() {
                return Err(Errno::EINVAL);
            } else if self.is_running() {
                // SAFETY: Do not allow changing crypt tmp at runtime.
                return Err(Errno::EBUSY);
            } else if value == "mem" {
                // Close old file descriptor as necessary.
                if let Some(fd) = self.crypt_tmp {
                    if fd >= 0 {
                        let _ = close(fd);
                    }
                }
                self.crypt_tmp = None;
            } else {
                let tmpdir = XPathBuf::from(value);
                if tmpdir.is_relative() {
                    return Err(Errno::EINVAL);
                }

                // SAFETY: `crypt/tmp` is a start-only command that runs
                // before sandboxing starts. Therefore, it is safe to
                // use `safe_open_abs` here.
                let fd = safe_open_abs(
                    &tmpdir,
                    OFlag::O_RDONLY | OFlag::O_DIRECTORY,
                    ResolveFlag::empty(),
                )?;

                // SAFETY: To make this file descriptor harder to spot by an
                // attacker we duplicate it to a random fd number.
                let fd = duprand(fd.as_raw_fd(), OFlag::O_CLOEXEC)?;
                info!("ctx": "run", "op": "opendir_crypt_tmp",
                    "msg": "opened backing directory for crypt sandboxing",
                    "fd": fd.as_raw_fd());

                // Close old file descriptor as necessary.
                if let Some(fd) = self.crypt_tmp {
                    if fd >= 0 {
                        let _ = close(fd);
                    }
                }

                self.crypt_tmp = Some(fd.into_raw_fd());
            }
        } else {
            return Err(Errno::EINVAL);
        }

        Ok(())
    }

    fn handle_force_rule_config(&mut self, command: ForceCmd) -> Result<(), Errno> {
        // Check for invalid action.
        if command.act == Some(Action::Allow) {
            return Err(Errno::EINVAL);
        }

        // Handle remove-all operator.
        if command.op == '^' {
            self.force_map.clear();
            return Ok(());
        }

        // Expand environment variables and decode hex.
        let src = if let Some(src) = command.src {
            self.decode_hex(&self.expand_env(src.as_str())?)
        } else {
            return Err(Errno::EINVAL);
        };
        match command.op {
            '-' => {
                self.force_map.remove(&src);
                return Ok(());
            }
            '+' => {}
            _ => unreachable!("BUG: fix force parser!"),
        }

        // Addition requires key and action.
        let key = if let Some(key) = command.key {
            HEXLOWER_PERMISSIVE
                .decode(self.expand_env(key.as_str())?.as_bytes())
                .or(Err(Errno::EINVAL))?
        } else {
            return Err(Errno::EINVAL);
        };
        // Protect user from adding invalid checksums.
        if !matches!(key.len(), 4 | 8 | 16 | 20 | 32 | 48 | 64) {
            return Err(Errno::EINVAL);
        }
        let act = command.act.unwrap_or_default();

        self.force_map.insert(src, (act, key)).map(drop)
    }

    fn handle_setid_rule_config(&mut self, command: SetIdCmd) -> Result<(), Errno> {
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        let id = command.id;
        let op = command.op;

        match id {
            'u' => {
                match (op, command.src, command.dst) {
                    ('+', Some(src), Some(dst)) => {
                        let source_uid = self.expand_env(src.as_str())?;
                        let target_uid = self.expand_env(dst.as_str())?;
                        let source_uid = parse_user(&source_uid)?;
                        let target_uid = parse_user(&target_uid)?;
                        self.add_uid_transit(source_uid, target_uid)?;
                    }
                    ('-', Some(src), Some(dst)) => {
                        let source_uid = self.expand_env(src.as_str())?;
                        let target_uid = self.expand_env(dst.as_str())?;
                        let source_uid = parse_user(&source_uid)?;
                        let target_uid = parse_user(&target_uid)?;
                        self.del_uid_transit(Some(source_uid), Some(target_uid));
                    }
                    ('^', Some(src), None) => {
                        let source_uid = self.expand_env(src.as_str())?;
                        let source_uid = parse_user(&source_uid)?;
                        self.del_uid_transit(Some(source_uid), None);
                    }
                    ('^', None, None) => {
                        self.del_uid_transit(None, None);
                    }
                    _ => return Err(Errno::EINVAL),
                };
            }
            'g' => {
                match (op, command.src, command.dst) {
                    ('+', Some(src), Some(dst)) => {
                        let source_gid = self.expand_env(src.as_str())?;
                        let target_gid = self.expand_env(dst.as_str())?;
                        let source_gid = parse_group(&source_gid)?;
                        let target_gid = parse_group(&target_gid)?;
                        self.add_gid_transit(source_gid, target_gid)?;
                    }
                    ('-', Some(src), Some(dst)) => {
                        let source_gid = self.expand_env(src.as_str())?;
                        let target_gid = self.expand_env(dst.as_str())?;
                        let source_gid = parse_group(&source_gid)?;
                        let target_gid = parse_group(&target_gid)?;
                        self.del_gid_transit(Some(source_gid), Some(target_gid));
                    }
                    ('^', Some(src), None) => {
                        let source_gid = self.expand_env(src.as_str())?;
                        let source_gid = parse_group(&source_gid)?;
                        self.del_gid_transit(Some(source_gid), None);
                    }
                    ('^', None, None) => {
                        self.del_gid_transit(None, None);
                    }
                    _ => return Err(Errno::EINVAL),
                };
            }
            _ => return Err(Errno::EINVAL),
        };

        Ok(())
    }

    fn handle_netlink_config(&mut self, command: NetlinkCmd) -> Result<(), Errno> {
        if self.is_running() {
            // Netlink family restrictions are applied at kernel level at startup.
            return Err(Errno::EBUSY);
        }

        match command.op {
            NetlinkOp::Clear => {
                self.netlink_families = NetlinkFamily::empty();
            }
            NetlinkOp::Add(families) => {
                for family in families {
                    let family = NetlinkFamily::from_str(&family)?;
                    self.netlink_families.insert(family);
                }
            }
            NetlinkOp::Del(families) => {
                for family in families {
                    let family = NetlinkFamily::from_str(&family)?;
                    self.netlink_families.remove(family);
                }
            }
        }

        Ok(())
    }

    fn handle_lock_rule_config(&mut self, command: LandlockCmd) -> Result<(), Errno> {
        // SAFETY: Landlock rules must only be passed at startup.
        if self.is_running() {
            return Err(Errno::EBUSY);
        }

        // Ensure Landlock rules are initialized.
        self.lock_rules
            .get_or_insert_with(Sandbox::default_lock_rules);

        // Take rules out so we don't hold a &mut borrow into `self`
        // while we pass `&self`. Thank you borrow checker!
        let mut rules = self.lock_rules.take().ok_or(Errno::EFAULT)?;
        let result = rules.edit(command, Some(self));
        self.lock_rules = Some(rules);
        result
    }

    fn handle_fs_rule_config(&mut self, command: FsCmd) -> Result<(), Errno> {
        let op = command.op;
        let act = command.action;

        let value = self.expand_env(&command.fs_type)?;
        let mut fs_types = Vec::new();
        for fs_type in value.split(',') {
            match fs_type {
                "all" => {
                    fs_types.extend(FS_MAGIC.iter().map(|&(_, fst)| FsType::from(fst)));
                }
                "ext4" | "ext3" | "ext2" => {
                    fs_types.extend(FsType::from_name("ext")?);
                }
                _ => {
                    fs_types.extend(FsType::from_name(fs_type)?);
                }
            }
        }
        if fs_types.is_empty() {
            return Err(Errno::EINVAL);
        }

        match op {
            '+' => {
                // add rule
                self.rule_add_fs(act, &fs_types)
            }
            '-' => {
                // remove rule
                self.rule_del_fs(act, &fs_types)
            }
            '^' => {
                // remove all matching rules
                self.rule_rem_fs(act, &fs_types)
            }
            _ => Err(Errno::EINVAL),
        }
    }

    fn handle_scmp_rule_config(&mut self, command: ScmpCmd) -> Result<(), Errno> {
        let op = command.op;
        let act = command.action;
        let caps = command.filter;

        // Reject ioctl which is for requests not paths.
        if caps.contains(Capability::CAP_IOCTL) {
            return Err(Errno::EINVAL);
        }

        let (pat, ip) = if let ScmpPattern::Host(host) = &command.pat {
            return self.handle_netalias_config(&command, host);
        } else if let ScmpPattern::Addr(addr) = &command.pat {
            (addr.as_str(), caps.intersects(Capability::CAP_NET))
        } else if let ScmpPattern::Path(path) = &command.pat {
            (path.as_str(), false)
        } else {
            unreachable!("BUG: parse path/addr in scmp rule parser!");
        };

        // SAFETY: Reject rules that must only be set at startup.
        if self.is_running() && caps.is_startup() {
            return Err(Errno::EBUSY);
        }

        match op {
            '+' => {
                // add rule
                if ip {
                    self.rule_add_cidr(act, caps, pat.as_ref())
                } else {
                    self.rule_add_glob(act, caps, pat.as_ref())
                }
            }
            '-' => {
                // remove rule
                if ip {
                    self.rule_del_cidr(act, caps, pat.as_ref())
                } else {
                    self.rule_del_glob(act, caps, pat.as_ref())
                }
            }
            '^' => {
                // remove all matching rules
                if ip {
                    self.rule_rem_cidr(act, caps, pat.as_ref())
                } else {
                    self.rule_rem_glob(act, caps, pat.as_ref())
                }
            }
            _ => Err(Errno::EINVAL),
        }
    }

    /// Remove CIDR with port range, removes all matching instances.
    pub fn rule_rem_cidr(&mut self, act: Action, caps: Capability, pat: &str) -> Result<(), Errno> {
        let pat = self.expand_env(pat)?;
        let pat = pat.parse::<AddressPattern>()?;
        for cap in caps {
            let rem = CidrRule {
                act,
                cap,
                pat: pat.clone(),
            };
            self.cidr_rules.retain(|rule| *rule != rem)?;
        }
        Ok(())
    }

    /// Remove CIDR with port range, removes the first instance from the end for predictability.
    pub fn rule_del_cidr(&mut self, act: Action, caps: Capability, pat: &str) -> Result<(), Errno> {
        let pat = self.expand_env(pat)?;
        let pat = pat.parse::<AddressPattern>()?;
        for cap in caps {
            let del = CidrRule {
                act,
                cap,
                pat: pat.clone(),
            };
            if let Some(idx) = self.cidr_rules.iter().position(|rule| *rule == del) {
                self.cidr_rules.remove(idx);
            }
        }
        Ok(())
    }

    /// Add CIDR with port range
    /// The rule is either a Unix shell style pattern, or
    /// a network address, one of the following formats:
    ///
    /// 1. GLOB-PATTERN
    /// 2. IP/NETMASK!$PORT
    ///
    /// - GLOB-PATTERN must start with a slash, `/`.
    /// - /NETMASK may be omitted.
    /// - PORT is a single integer or two in format port1-port2
    pub fn rule_add_cidr(&mut self, act: Action, caps: Capability, pat: &str) -> Result<(), Errno> {
        let pat = self.expand_env(pat)?;
        let pat = pat.parse::<AddressPattern>()?;
        for cap in caps {
            self.cidr_rules.push_front(CidrRule {
                act,
                cap,
                pat: pat.clone(),
            })?;
        }
        Ok(())
    }

    /// Add filesystem types.
    pub fn rule_add_fs(&mut self, act: Action, fs_types: &[FsType]) -> Result<(), Errno> {
        if act == Action::Filter {
            for fs_type in fs_types.iter().copied() {
                self.fs_arr.push_front(fs_type)?;
            }
        } else {
            for fs_type in fs_types.iter().copied() {
                self.fs_acl.push_front((fs_type, act))?;
            }
        }
        Ok(())
    }

    /// Remove filesystem types.
    pub fn rule_del_fs(&mut self, act: Action, fs_types: &[FsType]) -> Result<(), Errno> {
        if act == Action::Filter {
            for fs_type in fs_types.iter().copied() {
                if let Some(index) = self.fs_arr.iter().copied().position(|fst| fs_type == fst) {
                    self.fs_arr.remove(index);
                }
            }
        } else {
            for fs_type in fs_types.iter().copied() {
                if let Some(index) = self
                    .fs_acl
                    .iter()
                    .copied()
                    .position(|(fst, a)| act == a && fs_type == fst)
                {
                    self.fs_acl.remove(index);
                }
            }
        }

        Ok(())
    }

    /// Remove all matching filesystem types.
    pub fn rule_rem_fs(&mut self, act: Action, fs_types: &[FsType]) -> Result<(), Errno> {
        for fs_type in fs_types.iter().copied() {
            if act == Action::Filter {
                self.fs_arr.retain(|&fst| fs_type != fst)?;
            } else {
                self.fs_acl.retain(|&(fst, a)| act != a && fs_type != fst)?;
            }
        }

        Ok(())
    }

    /// Add Unix shell style pattern.
    pub fn rule_add_glob(&mut self, act: Action, caps: Capability, pat: &str) -> Result<(), Errno> {
        // Check for empty/invalid flags.
        if caps.is_empty() || !Capability::CAP_GLOB.contains(caps) {
            return Err(Errno::EINVAL);
        }

        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        match pat.first() {
            Some(b'/') => {} // Absolute path.
            Some(b'@') => {} // Abstract socket path.
            Some(b'!') => {
                // We reserve the prefix `!' for some special features:
                //
                // 1. Sending file descriptors to unnamed sockets may be
                //    allowed with `allow/net/sendfd+!unnamed`.
                // 2. Binding/Connecting to unnamed UNIX sockets may be
                //    allowed with e.g. `allow/net/bind+!unnamed`.
                // 3. Confining memory file descriptors with
                //    `allow/create+!memfd:*` or
                //    `allow/truncate+!memfd-hugetlb:*`.
                //
                // We use literal match for all cases except 4.
                let is_mfd = pat.starts_with(b"!memfd");
                let method = if is_mfd {
                    MatchMethod::Glob
                } else {
                    MatchMethod::Literal
                };
                for cap in caps {
                    if act == Action::Filter {
                        let arr = self.get_arr_mut(cap);
                        arr.push_front((pat.clone(), method))?;
                    } else {
                        let acl = self.get_acl_mut(cap);
                        acl.push_front((pat.clone(), method, act))?;
                    }
                }
                return Ok(());
            }
            _ => {
                // We match on canonicalized paths,
                // relative patterns are a common case of error,
                // let's just prevent them until someone comes
                // up with a valid usecase.
                return Err(Errno::EINVAL);
            }
        }

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.add_glob(act, caps, &pat, MatchMethod::Glob)?;
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.add_glob(act, caps, &pat, meth)?;

        Ok(())
    }

    /// Remove Unix shell style pattern, removes all matching instances.
    pub fn rule_rem_glob(&mut self, act: Action, caps: Capability, pat: &str) -> Result<(), Errno> {
        // Check for invalid flags.
        if caps.is_empty() || !Capability::CAP_GLOB.contains(caps) {
            return Err(Errno::EINVAL);
        }

        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.rem_glob(act, caps, &pat, MatchMethod::Glob)?;
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.rem_glob(act, caps, &pat, meth)?;

        Ok(())
    }

    /// Remove Unix shell style pattern, removes the first instance from the end for predictability.
    pub fn rule_del_glob(&mut self, act: Action, caps: Capability, pat: &str) -> Result<(), Errno> {
        // Check for empty/invalid flags.
        if caps.is_empty() || !Capability::CAP_GLOB.contains(caps) {
            return Err(Errno::EINVAL);
        }

        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.del_glob(act, caps, &pat, MatchMethod::Glob);
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.del_glob(act, caps, &pat, meth);

        Ok(())
    }

    /// Remove Unix shell style pattern from append-only acl, removes all matching instances.
    pub fn rule_rem_append(&mut self, pat: &str) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.rem_append(&pat, MatchMethod::Glob)?;
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.rem_append(&pat, meth)?;

        Ok(())
    }

    /// Remove Unix shell style pattern from append-only acl, removes the first instance from the end for predictability.
    pub fn rule_del_append(&mut self, pat: &str) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.del_append(&pat, MatchMethod::Glob);
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.del_append(&pat, meth);

        Ok(())
    }

    /// Add Unix shell style pattern to append-only acl.
    pub fn rule_add_append(&mut self, pat: &str) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        // Ensure absolute or special path.
        if !matches!(pat.first(), Some(b'/' | b'!')) {
            // We match on canonicalized paths, relative patterns are a
            // common case of error, let's just prevent them until
            // someone comes up with a valid usecase.
            return Err(Errno::EINVAL);
        }

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - 1); // foo/*** -> foo/**
            self.add_append(pat.clone(), MatchMethod::Glob)?;
            pat.truncate(len - 3); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.add_append(pat, meth)?;

        Ok(())
    }

    /// Simplifies the blocklists.
    pub fn rule_agg_block(&mut self, pat: &str) -> Result<(), Errno> {
        if !pat.is_empty() {
            return Err(Errno::EINVAL);
        }

        self.net_block_lst.0.simplify();
        self.net_block_lst.1.simplify();

        Ok(())
    }

    /// Clears the blocklists.
    pub fn rule_rem_block(&mut self, pat: &str) -> Result<(), Errno> {
        if !pat.is_empty() {
            return Err(Errno::EINVAL);
        }

        self.net_block_lst.0 = IpRange::new();
        self.net_block_lst.1 = IpRange::new();

        Ok(())
    }

    /// Remove an IP network from the blocklist.
    pub fn rule_del_block(&mut self, pat: &str) -> Result<(), Errno> {
        match parse_ipnet(pat) {
            Ok(IpNet::V4(addr)) => {
                self.net_block_lst.0.remove(addr);
            }
            Ok(IpNet::V6(addr)) => {
                self.net_block_lst.1.remove(addr);
            }
            Err(_) => return Err(Errno::EINVAL),
        }
        Ok(())
    }

    /// Add an IP network to the blocklist.
    pub fn rule_add_block(&mut self, pat: &str) -> Result<(), Errno> {
        match parse_ipnet(pat) {
            Ok(IpNet::V4(addr)) => {
                self.net_block_lst.0.add(addr);
            }
            Ok(IpNet::V6(addr)) => {
                self.net_block_lst.1.add(addr);
            }
            Err(_) => return Err(Errno::EINVAL),
        }
        Ok(())
    }

    /// Remove Unix shell style pattern from crypt acl, removes all matching instances.
    pub fn rule_rem_crypt(&mut self, pat: &str) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.rem_crypt(&pat, MatchMethod::Glob)?;
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.rem_crypt(&pat, meth)?;

        Ok(())
    }

    /// Remove Unix shell style pattern from crypt acl, removes the first instance from the end for predictability.
    pub fn rule_del_crypt(&mut self, pat: &str) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.del_crypt(&pat, MatchMethod::Glob);
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.del_crypt(&pat, meth);

        Ok(())
    }

    /// Add Unix shell style pattern to crypt acl.
    pub fn rule_add_crypt(&mut self, pat: &str) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        // Ensure absolute or special path.
        if !matches!(pat.first(), Some(b'/' | b'!')) {
            // We match on canonicalized paths, relative patterns are a
            // common case of error, let's just prevent them until
            // someone comes up with a valid usecase.
            return Err(Errno::EINVAL);
        }

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - 1); // foo/*** -> foo/**
            self.add_crypt(pat.clone(), MatchMethod::Glob)?;
            pat.truncate(len - 3); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.add_crypt(pat, meth)?;

        Ok(())
    }

    /// Clears the mask acl.
    pub fn rule_rem_mask(&mut self) -> Result<(), Errno> {
        self.rem_mask();

        Ok(())
    }

    /// Remove Unix shell style pattern from mask acl, removes the first instance from the end for predictability.
    pub fn rule_del_mask(&mut self, pat: &str) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.del_mask(&pat, MatchMethod::Glob)?;
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.del_mask(&pat, meth)
    }

    /// Add Unix shell style pattern to mask acl.
    pub fn rule_add_mask(
        &mut self,
        pat: &str,
        mask_all: Option<&str>,
        mask_dir: Option<&str>,
    ) -> Result<(), Errno> {
        // 1. Expand environment variables
        // 2. Decode hex
        // 3. Clean consecutive slashes
        let mut pat = self.decode_hex(&self.expand_env(pat)?);
        pat.clean_consecutive_slashes();

        let mask_all = if let Some(mask) = mask_all {
            let mut mask = self.decode_hex(&self.expand_env(mask)?);
            mask.clean_consecutive_slashes();

            // Ensure absolute or special path:
            // Relative patterns are a common case of error,
            // let's just prevent them until someone comes up
            // with a valid usecase.
            if !matches!(mask.first(), Some(b'/' | b'!')) {
                return Err(Errno::EINVAL);
            }

            Some(mask)
        } else {
            None
        };

        let mask_dir = if let Some(mask) = mask_dir {
            let mut mask = self.decode_hex(&self.expand_env(mask)?);
            mask.clean_consecutive_slashes();

            // Ensure absolute or special path:
            // Relative patterns are a common case of error,
            // let's just prevent them until someone comes up
            // with a valid usecase.
            if !matches!(mask.first(), Some(b'/' | b'!')) {
                return Err(Errno::EINVAL);
            }

            Some(mask)
        } else {
            None
        };

        // Ensure absolute or special path.
        if !matches!(pat.first(), Some(b'/' | b'!')) {
            // We match on canonicalized paths, relative patterns are a
            // common case of error, let's just prevent them until
            // someone comes up with a valid usecase.
            return Err(Errno::EINVAL);
        }

        #[expect(clippy::arithmetic_side_effects)]
        let (pat, meth) = if let Some(pat) = get_prefix(&pat) {
            (pat, MatchMethod::Prefix)
        } else if is_literal(pat.as_bytes()) {
            (pat, MatchMethod::Literal)
        } else if pat.ends_with(b"/***") {
            // Pattern followed by triple star.
            // We split this into multiple patterns.
            let len = pat.len();
            pat.truncate(len - b"*".len()); // foo/*** -> foo/**
            self.add_mask(
                pat.clone(),
                MatchMethod::Glob,
                mask_all.clone(),
                mask_dir.clone(),
            )?;
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.add_mask(pat, meth, mask_all, mask_dir)?;

        Ok(())
    }

    /// Return default LandlockPolicy for the Sandbox.
    #[expect(clippy::disallowed_methods)]
    pub fn default_lock_rules() -> LandlockPolicy {
        let mut policy = LandlockPolicy {
            // Scopes are enabled unconditionally until
            // there's a real need to make them optional.
            scoped_abs: true,
            scoped_sig: true,
            ..Default::default()
        };

        // SAFETY:
        //
        // Because Syd is included into the Landlock sandbox, we
        // require a minimum set of Landlock accesses by default
        // to function correctly.
        // 1. /dev/null Read + Write + Truncate
        // 2. /proc     Read + ReadDir
        policy
            .rule_add_fs(
                AccessFs::ReadFile | AccessFs::WriteFile | AccessFs::Truncate,
                XPath::from_bytes(b"/dev/null"),
            )
            .expect("allow/lock/read,write,truncate+/dev/null");

        policy
            .rule_add_fs(
                AccessFs::ReadFile | AccessFs::ReadDir,
                XPath::from_bytes(b"/proc"),
            )
            .expect("allow/lock/read,readdir+/proc");

        policy
    }

    /// Returns landlock(7) security policy,
    /// or None if Lock sandboxing is disabled.
    pub fn collect_landlock(&mut self) -> Option<LandlockPolicy> {
        // Take rules, collect is a onetime action.
        let mut policy = if let Some(policy) = self.lock_rules.take() {
            if !self.landlocked() {
                // Drop policy if Lock sandboxing is off.
                return None;
            }
            policy
        } else if !self.landlocked() {
            // Lock sandboxing is off and no allow/lock was passed.
            return None;
        } else {
            // Init policy with defaults if no allow/lock was passed.
            Sandbox::default_lock_rules()
        };

        // Explicitly set compatibility level.
        policy.compat_level = Some(self.landlock_compat_level());

        Some(policy)
    }

    /// Check if the given path is hidden (ie denylisted for stat sandboxing)
    pub fn is_hidden(&self, path: &XPath) -> bool {
        if self.enabled(Capability::CAP_STAT) {
            let (action, _) = self.check_path(Capability::CAP_STAT, path);
            action.is_denying()
        } else {
            false
        }
    }

    /// hex-decode a path glob pattern as necessary.
    pub fn decode_hex(&self, pat: &str) -> XPathBuf {
        if let Ok(pat) = HEXLOWER_PERMISSIVE.decode(pat.as_bytes()) {
            pat.into()
        } else {
            pat.into()
        }
    }

    /// Expand environment variables safely at startup.
    /// 1. No-op if sandbox is running.
    /// 2. Error return on envvar lookup errors.
    #[expect(clippy::cognitive_complexity)]
    pub fn expand_env<'b>(&self, input: &'b str) -> Result<Cow<'b, str>, Errno> {
        if self.is_running() {
            // SAFETY: Make no changes to input if sandboxing is already running.
            return Ok(Cow::Borrowed(input));
        }

        if self.config_expand_timeout.is_zero() {
            // SAFETY:
            // 1. Setting `config/expand:0` (default) switches
            // to the simpler, faster alternative `shellexpand`:
            return match shellexpand::full(input) {
                Ok(env) => {
                    if log_enabled!(LogLevel::Debug) && input != env {
                        debug!("ctx": "configure_expand", "op": "shellexpand",
                            "msg": format!("expanded variable `{input}' to `{env}' using shellexpand"),
                            "var": XPathBuf::from(input),
                            "env": XPathBuf::from(env.clone()));
                    }
                    Ok(Cow::Owned(env.into_owned()))
                }
                Err(err) => {
                    error!("ctx": "configure_expand", "op": "shellexpand",
                        "msg": format!("error during variable expansion: {err}"),
                        "var": XPathBuf::from(input));
                    Err(Errno::EINVAL)
                }
            };
        }

        // bionic libc does not support wordexp(3).
        #[cfg(target_os = "android")]
        unreachable!("BUG: Attempted wordexp(3) on unsupported libc!");

        // Perform environment expansion at startup only.
        // SAFETY:
        // 1. Empty expansion generate an error.
        // 2. Setting config/expand to 0 disables expansion.
        #[cfg(not(target_os = "android"))]
        match WordExp::expand_full(input, self.config_expand_timeout) {
            Ok(env) => {
                if log_enabled!(LogLevel::Debug) && input != env {
                    debug!("ctx": "configure_expand", "op": "wordexp",
                        "msg": format!("expanded variable `{input}' to `{env}' using wordexp"),
                        "var": XPathBuf::from(input),
                        "env": XPathBuf::from(env.clone()));
                }
                Ok(env)
            }
            Err(err) => {
                error!("ctx": "configure_expand", "op": "wordexp",
                    "msg": format!("error during variable expansion: {err}"),
                    "var": XPathBuf::from(input));
                Err(Errno::EINVAL)
            }
        }
    }

    /// Expand an ioctl(2) request.
    #[expect(clippy::type_complexity)]
    pub(crate) fn expand_ioctl(&self, input: &str) -> Result<Vec<(u64, u32)>, Errno> {
        let input = self.expand_env(input)?;
        let mut requests = Vec::new();

        if let Ok(request) = str2u64(input.as_bytes()) {
            for arch in SCMP_ARCH {
                let arch = scmp_arch_raw(*arch);
                requests.push((request, arch));
                if let Some(request) = extend_ioctl(request) {
                    requests.push((request, arch));
                }
            }

            return Ok(requests);
        }

        let ioctl = IoctlMap::new(None, true);
        let input = input.to_ascii_uppercase();
        for arch in SCMP_ARCH {
            #[expect(clippy::unnecessary_cast)]
            if let Some(request) = ioctl.get_value(&input, *arch) {
                let arch = scmp_arch_raw(*arch);
                let request = request as u64;
                requests.push((request, arch));
                if let Some(request) = extend_ioctl(request) {
                    requests.push((request, arch));
                }
            }
        }

        if !requests.is_empty() {
            Ok(requests)
        } else {
            Err(Errno::EINVAL)
        }
    }

    /// Check IPv{4,6} address for access and IP blocklist as necessary.
    pub(crate) fn check_ip(&self, cap: Capability, addr: IpAddr, port: u16) -> (Action, bool) {
        // Check for IP blocklist for accept{,4}, connect, sendto, send{m,}msg.
        if cap.is_block() {
            let block = match addr {
                IpAddr::V4(addr) => self.net_block_lst.0.contains(&addr),
                IpAddr::V6(addr) => self.net_block_lst.1.contains(&addr),
            };

            if block {
                let net_block_act = self.net_block_act();
                if net_block_act == Action::Filter {
                    // Filter is only checked for !(Allow|Filter).
                    // net_block_act can never be Allow.
                    return (Action::Filter, true);
                } else if cap.is_empty() {
                    // accept{,4}
                    return (net_block_act, false);
                } else {
                    // connect, sendto, send{m,}msg
                    return (net_block_act, self.filter_ip(cap, &addr, port));
                }
            } else if cap.is_empty() {
                // No ACL check for accept{,4}
                return (Action::Allow, true);
            }
        }

        // Check for CIDR rules next.
        for rule in &self.cidr_rules {
            if cap != rule.cap {
                continue;
            }
            if rule.act == Action::Filter {
                continue;
            }
            let port_match = rule
                .pat
                .port
                .as_ref()
                .map(|range| range.contains(&port))
                .unwrap_or(true);
            if port_match && rule.pat.addr.contains(&addr) {
                if matches!(rule.act, Action::Allow | Action::Filter) {
                    // Filter is only checked for !(Allow|Filter).
                    return (rule.act, true);
                } else {
                    return (rule.act, self.filter_ip(cap, &addr, port));
                }
            }
        }

        // If no specific rule is found, return based on capability
        // being enabled or not.
        if self.enabled(cap) {
            let action = self.default_action(cap);
            if matches!(action, Action::Allow | Action::Filter) {
                (action, true)
            } else {
                (self.default_action(cap), self.filter_ip(cap, &addr, port))
            }
        } else {
            (Action::Allow, true)
        }
    }

    /// Check UNIX socket for access.
    pub(crate) fn check_unix(&self, cap: Capability, path: &XPath) -> (Action, bool) {
        // First, see if there's a matching allow or deny rule for the path.
        if let Some(action) = self.match_action(cap, path) {
            return match action {
                Action::Allow | Action::Filter => (action, true),
                Action::Warn => return (Action::Warn, false),
                action => (action, self.filter_path(cap, path)),
            };
        }

        // If no specific rule is found, return based on capability being enabled or not.
        match self.default_action(cap) {
            Action::Allow => (Action::Allow, true),
            Action::Warn => (Action::Warn, false),
            Action::Filter => (Action::Filter, true),
            action => (action, self.filter_path(cap, path)),
        }
    }

    /// Check path for TPE.
    pub(crate) fn check_tpe<Fd: AsFd>(&self, file: Fd, path: &XPath) -> (Action, Option<String>) {
        // Check if TPE should be applied.
        let msg = if let Some(msg) = self.apply_tpe() {
            msg
        } else {
            return (Action::Allow, None);
        };

        let tpe_act = self.default_action(Capability::CAP_TPE);
        let root_owned = self.flags.tpe_root_owned();
        let user_owned = self.flags.tpe_user_owned();
        let root_mount = self.flags.tpe_root_mount();
        let mut sflags = STATX_MODE;
        let uid = if root_owned || user_owned {
            // File owner check required, request UID.
            sflags |= STATX_UID;
            if user_owned {
                Some(Uid::effective().as_raw())
            } else {
                None
            }
        } else {
            None
        };
        let mnt = if root_mount {
            // File mount check required, request mount id.
            sflags |= if *HAVE_STATX_MNT_ID_UNIQUE {
                STATX_MNT_ID_UNIQUE
            } else {
                STATX_MNT_ID
            };
            Some(ROOT_MNT_ID())
        } else {
            None
        };

        // Check if the file is root/user owned.
        // Check if the file is writable only by the owner.
        // Check if the file is on root filesystem.
        let statx = match fstatx(file, sflags) {
            Ok(statx) => statx,
            Err(errno) => return (tpe_act, Some(format!("{msg} and stat failed: {errno}"))),
        };

        let is0 = statx.stx_uid == 0;
        if root_owned && !is0 {
            return (tpe_act, Some(format!("{msg} and file non-root-owned")));
        }

        // uid is Some with user_owned=true.
        #[expect(clippy::disallowed_methods)]
        if user_owned && !is0 && statx.stx_uid != uid.unwrap() {
            return (tpe_act, Some(format!("{msg} and file non-user-owned")));
        }

        if mnt.map(|id| id != statx.stx_mnt_id).unwrap_or(false) {
            return (tpe_act, Some(format!("{msg} and file non-root-mounted")));
        }

        let mode = u32::from(statx.stx_mode);
        if mode & libc::S_IWOTH != 0 {
            return (tpe_act, Some(format!("{msg} and file world-writable")));
        }

        if mode & libc::S_IWGRP != 0 {
            return (tpe_act, Some(format!("{msg} and file group-writable")));
        }

        // Check if the parent directory is root/user owned.
        // Check if the parent directory is writable only by the owner.
        // Check if the parent directory is on root filesystem.
        //
        // SAFETY:
        // 1. Do not resolve symbolic links.
        // 2. Fail if the parent is not a directory.
        // 3. rootfs and procfs views must be identical.
        // All of these are necessary to avoid TOCTOU.
        let parent = path.parent();
        let parent: MaybeFd = if parent.is_root() {
            ROOT_FD().into()
        } else if parent.is_equal(b"/proc") {
            PROC_FD().into()
        } else {
            let (parent_fd, base) = if parent.starts_with(b"/proc/") {
                let base = XPath::from_bytes(&parent.as_bytes()[b"/proc/".len()..]);
                (PROC_FILE(), base)
            } else {
                let base = XPath::from_bytes(&parent.as_bytes()[1..]);
                (ROOT_FILE(), base)
            };

            match safe_open_path(parent_fd, base, OFlag::O_DIRECTORY, ResolveFlag::empty()) {
                Ok(parent) => parent.into(),
                Err(errno) => return (tpe_act, Some(format!("{msg} and open failed: {errno}"))),
            }
        };

        let statx = match fstatx(parent, sflags) {
            Ok(statx) => statx,
            Err(errno) => return (tpe_act, Some(format!("{msg} and stat failed: {errno}"))),
        };

        let is0 = statx.stx_uid == 0;
        if root_owned && !is0 {
            return (
                tpe_act,
                Some(format!("{msg} and file in non-root-owned directory")),
            );
        }

        // uid is Some with user_owned=true.
        #[expect(clippy::disallowed_methods)]
        if user_owned && !is0 && statx.stx_uid != uid.unwrap() {
            return (
                tpe_act,
                Some(format!("{msg} and file in non-user-owned directory")),
            );
        }

        if mnt.map(|id| id != statx.stx_mnt_id).unwrap_or(false) {
            return (
                tpe_act,
                Some(format!("{msg} and file in non-root-mounted directory")),
            );
        }

        let mode = u32::from(statx.stx_mode);
        if mode & libc::S_IWOTH != 0 {
            return (
                tpe_act,
                Some(format!("{msg} and file in world-writable directory")),
            );
        }

        if mode & libc::S_IWGRP != 0 {
            return (
                tpe_act,
                Some(format!("{msg} and file in group-writable directory")),
            );
        }

        // Checks passed, allow.
        (Action::Allow, None)
    }

    /// Check if TPE should be applied.
    fn apply_tpe(&self) -> Option<String> {
        let tpe_gid = if let Some(tpe_gid) = self.tpe_gid {
            tpe_gid
        } else {
            // TPE is applied if tpe_gid=None.
            return Some("user in untrusted group".to_string());
        };

        let egid = Gid::effective();
        if egid == tpe_gid {
            return if self.flags.tpe_negate() {
                None
            } else {
                Some("user in untrusted group".to_string())
            };
        }

        match getgroups() {
            Ok(gids) => {
                if self.flags.tpe_negate() {
                    if !gids.contains(&tpe_gid) {
                        Some("user not in trusted group".to_string())
                    } else {
                        None
                    }
                } else if gids.contains(&tpe_gid) {
                    Some("user in untrusted group".to_string())
                } else {
                    None
                }
            }
            Err(errno) => Some(format!("getgroups failed: {errno}")),
        }
    }

    /// Check filesystem for access.
    pub(crate) fn check_fs(&self, fs_type: FsType) -> (Action, bool) {
        // First, see if there's a matching allow or deny rule for the filesystem.
        if let Some(action) = self.match_fs_action(fs_type) {
            return match action {
                Action::Allow | Action::Filter => {
                    // Filter is only checked for !(Allow|Warn|Filter).
                    (action, true)
                }
                Action::Warn => (Action::Warn, false),
                _ => {
                    // If the action is !(Allow|Warn|Filter), then we
                    // must check if it's filtered.
                    (action, self.filter_fs(fs_type))
                }
            };
        }

        // If no specific rule is found, return based on capability being enabled or not.
        self.check_fs_nomatch(fs_type)
    }

    /// Check if the filesystem is filtered.
    pub fn filter_fs(&self, fs_type: FsType) -> bool {
        self.fs_arr.contains(&fs_type)
    }

    // If no specific rule is found, return based on Filesystem sandboxing being enabled or not.
    fn check_fs_nomatch(&self, fs_type: FsType) -> (Action, bool) {
        match self.default_action(Capability::CAP_FS) {
            Action::Allow => (Action::Allow, true),
            Action::Warn => (Action::Warn, false),
            Action::Filter => (Action::Filter, true),
            action => {
                // If the action is !(Allow|Warn|Filter), then we must
                // check if it's filtered.
                (action, self.filter_fs(fs_type))
            }
        }
    }

    /// Find a matching action (Allow or Deny) for the given filesystem.
    pub fn match_fs_action(&self, fs_type: FsType) -> Option<Action> {
        for (fst, action) in &self.fs_acl {
            if *fst == fs_type {
                return Some(*action);
            }
        }
        None
    }

    /// Check path for access.
    pub(crate) fn check_path(&self, cap: Capability, path: &XPath) -> (Action, bool) {
        // Drop trailing slash which can cause inconsistencies with expectations.
        #[expect(clippy::arithmetic_side_effects)]
        let pidx = path.len() - 1;
        let path = if pidx > 0 && path.as_bytes()[pidx] == b'/' {
            // SAFETY: Since we're operating on valid path bytes,
            // getting a slice is safe. This excludes the root path "/"
            // to avoid turning it into an empty path.
            XPath::from_bytes(&path.as_bytes()[..pidx])
        } else {
            path
        };

        // First, see if there's a matching allow or deny rule for the path.
        if let Some(action) = self.match_action(cap, path) {
            return match action {
                Action::Allow | Action::Filter => {
                    // Filter is only checked for !(Allow|Warn|Filter).
                    (action, true)
                }
                Action::Warn => (Action::Warn, false),
                _ => {
                    // If the action is !(Allow|Warn|Filter), then we
                    // must check if it's filtered.
                    (action, self.filter_path(cap, path))
                }
            };
        }

        // If no specific rule is found, return based on capability being enabled or not.
        self.check_path_nomatch(cap, path)
    }

    // If no specific rule is found, return based on capability being enabled or not.
    fn check_path_nomatch(&self, cap: Capability, path: &XPath) -> (Action, bool) {
        match self.default_action(cap) {
            Action::Allow => (Action::Allow, true),
            Action::Warn => (Action::Warn, false),
            Action::Filter => (Action::Filter, true),
            action => {
                // If the action is !(Allow|Warn|Filter), then we must
                // check if it's filtered.
                (action, self.filter_path(cap, path))
            }
        }
    }

    /// Find a matching action (Allow or Deny) for the given path.
    pub fn match_action(&self, cap: Capability, path: &XPath) -> Option<Action> {
        for (pattern, method, action) in self.get_acl(cap) {
            if globmatch(pattern.as_bytes(), path.as_bytes(), *method) {
                return Some(*action);
            }
        }
        None
    }

    /// Check if the given path is append-only.
    pub fn is_append(&self, path: &XPath) -> bool {
        for (pattern, method) in &self.append_acl {
            if globmatch(pattern.as_bytes(), path.as_bytes(), *method) {
                return true;
            }
        }
        false
    }

    /// Return true if append-only ACL is populated.
    pub fn has_append(&self) -> bool {
        !self.append_acl.is_empty()
    }

    /// Return true if sandbox may be locked,
    /// and append-only ACL is empty.
    pub fn skip_append(&self) -> bool {
        self.locked_pre() && !self.has_append() && !self.enabled(Capability::CAP_CRYPT)
    }

    /// Return true if crypt sandboxing list is populated.
    pub fn has_crypt(&self) -> bool {
        !self.crypt_acl.is_empty()
    }

    /// Return true if crypt sandboxing should be implied.
    pub fn must_crypt(&self) -> bool {
        self.has_crypt() || self.crypt_id.is_some() || self.crypt_tmp.is_some()
    }

    /// Check if the given path should be encrypted.
    pub fn is_crypt(&self, path: &XPath) -> bool {
        if self.enabled(Capability::CAP_CRYPT) {
            for (pattern, method) in &self.crypt_acl {
                if globmatch(pattern.as_bytes(), path.as_bytes(), *method) {
                    return true;
                }
            }
        }
        false
    }

    /// Check if the given path is masked, return optional mask path.
    pub fn is_masked(&self, path: &XPath) -> Option<&Mask> {
        for (pattern, rule) in &self.mask_acl {
            if globmatch(pattern.as_bytes(), path.as_bytes(), rule.meth) {
                return Some(&rule.mask);
            }
        }
        None
    }

    /// Check if the ip address with the given port is filtered.
    fn filter_ip(&self, cap: Capability, addr: &IpAddr, port: u16) -> bool {
        self.cidr_rules
            .iter()
            .filter(|filter| filter.act == Action::Filter && filter.cap == cap)
            .any(|filter| {
                let port_match = filter
                    .pat
                    .port
                    .as_ref()
                    .map(|range| range.contains(&port))
                    .unwrap_or(true);
                port_match && filter.pat.addr.contains(addr)
            })
    }

    /// Check if the path is filtered.
    pub fn filter_path(&self, cap: Capability, path: &XPath) -> bool {
        for (pattern, method) in self.get_arr(cap) {
            if globmatch(pattern.as_bytes(), path.as_bytes(), *method) {
                return true;
            }
        }
        false
    }

    // Accumulate force rules into a rule vector.
    #[expect(clippy::type_complexity)]
    fn force_rules(&self) -> Vec<(&XPathBuf, &(Action, Vec<u8>))> {
        self.force_map.into_iter().collect()
    }

    // Accumulate fs rules into a FsAclRule vector.
    fn fs_rules(&self) -> Vec<FsAclRule> {
        let mut rules = vec![];

        for fs_type in self.fs_arr.iter().copied() {
            rules.push((fs_type, Action::Filter));
        }
        for (fs_type, act) in self.fs_acl.iter().copied() {
            rules.push((fs_type, act));
        }

        rules
    }

    // Accumulate cidr rules into a CidrRule vector.
    fn cidr_rules(&self) -> Vec<CidrRule> {
        self.cidr_rules.into_iter().cloned().collect()
    }

    // Accumulate glob rules into a GlobRule vector.
    fn glob_rules(&self) -> Vec<GlobRule> {
        let mut rules = vec![];

        for cap in Capability::CAP_GLOB {
            for (glob, _) in self.get_arr(cap) {
                rules.push(GlobRule {
                    cap,
                    act: Action::Filter,
                    pat: glob.clone(),
                });
            }
            for (glob, _, act) in self.get_acl(cap) {
                rules.push(GlobRule {
                    cap,
                    act: *act,
                    pat: glob.clone(),
                });
            }
        }

        rules
    }

    fn get_acl(&self, cap: Capability) -> &Acl {
        match cap {
            Capability::CAP_WALK => &self.walk_acl,
            Capability::CAP_STAT => &self.stat_acl,
            Capability::CAP_READ => &self.read_acl,
            Capability::CAP_WRITE => &self.write_acl,
            Capability::CAP_EXEC => &self.exec_acl,
            Capability::CAP_CREATE => &self.create_acl,
            Capability::CAP_DELETE => &self.delete_acl,
            Capability::CAP_RENAME => &self.rename_acl,
            Capability::CAP_SYMLINK => &self.symlink_acl,
            Capability::CAP_TRUNCATE => &self.truncate_acl,
            Capability::CAP_CHDIR => &self.chdir_acl,
            Capability::CAP_READDIR => &self.readdir_acl,
            Capability::CAP_MKDIR => &self.mkdir_acl,
            Capability::CAP_RMDIR => &self.rmdir_acl,
            Capability::CAP_CHOWN => &self.chown_acl,
            Capability::CAP_CHGRP => &self.chgrp_acl,
            Capability::CAP_CHMOD => &self.chmod_acl,
            Capability::CAP_CHATTR => &self.chattr_acl,
            Capability::CAP_CHROOT => &self.chroot_acl,
            Capability::CAP_UTIME => &self.utime_acl,
            Capability::CAP_MKBDEV => &self.mkbdev_acl,
            Capability::CAP_MKCDEV => &self.mkcdev_acl,
            Capability::CAP_MKFIFO => &self.mkfifo_acl,
            Capability::CAP_MKTEMP => &self.mktemp_acl,
            Capability::CAP_NET_BIND => &self.net_bind_acl,
            Capability::CAP_NET_CONNECT => &self.net_conn_acl,
            Capability::CAP_NET_SENDFD => &self.net_sendfd_acl,
            _ => unreachable!(),
        }
    }

    pub(crate) fn get_acl_mut(&mut self, cap: Capability) -> &mut Acl {
        match cap {
            Capability::CAP_WALK => &mut self.walk_acl,
            Capability::CAP_STAT => &mut self.stat_acl,
            Capability::CAP_READ => &mut self.read_acl,
            Capability::CAP_WRITE => &mut self.write_acl,
            Capability::CAP_EXEC => &mut self.exec_acl,
            Capability::CAP_CREATE => &mut self.create_acl,
            Capability::CAP_DELETE => &mut self.delete_acl,
            Capability::CAP_RENAME => &mut self.rename_acl,
            Capability::CAP_SYMLINK => &mut self.symlink_acl,
            Capability::CAP_TRUNCATE => &mut self.truncate_acl,
            Capability::CAP_CHDIR => &mut self.chdir_acl,
            Capability::CAP_READDIR => &mut self.readdir_acl,
            Capability::CAP_MKDIR => &mut self.mkdir_acl,
            Capability::CAP_RMDIR => &mut self.rmdir_acl,
            Capability::CAP_CHOWN => &mut self.chown_acl,
            Capability::CAP_CHGRP => &mut self.chgrp_acl,
            Capability::CAP_CHMOD => &mut self.chmod_acl,
            Capability::CAP_CHATTR => &mut self.chattr_acl,
            Capability::CAP_CHROOT => &mut self.chroot_acl,
            Capability::CAP_UTIME => &mut self.utime_acl,
            Capability::CAP_MKBDEV => &mut self.mkbdev_acl,
            Capability::CAP_MKCDEV => &mut self.mkcdev_acl,
            Capability::CAP_MKFIFO => &mut self.mkfifo_acl,
            Capability::CAP_MKTEMP => &mut self.mktemp_acl,
            Capability::CAP_NET_BIND => &mut self.net_bind_acl,
            Capability::CAP_NET_CONNECT => &mut self.net_conn_acl,
            Capability::CAP_NET_SENDFD => &mut self.net_sendfd_acl,
            _ => unreachable!(),
        }
    }

    fn get_arr(&self, cap: Capability) -> &Arr {
        match cap {
            Capability::CAP_WALK => &self.walk_arr,
            Capability::CAP_STAT => &self.stat_arr,
            Capability::CAP_READ => &self.read_arr,
            Capability::CAP_WRITE => &self.write_arr,
            Capability::CAP_EXEC => &self.exec_arr,
            Capability::CAP_CREATE => &self.create_arr,
            Capability::CAP_DELETE => &self.delete_arr,
            Capability::CAP_RENAME => &self.rename_arr,
            Capability::CAP_SYMLINK => &self.symlink_arr,
            Capability::CAP_TRUNCATE => &self.truncate_arr,
            Capability::CAP_CHDIR => &self.chdir_arr,
            Capability::CAP_READDIR => &self.readdir_arr,
            Capability::CAP_MKDIR => &self.mkdir_arr,
            Capability::CAP_RMDIR => &self.rmdir_arr,
            Capability::CAP_CHOWN => &self.chown_arr,
            Capability::CAP_CHGRP => &self.chgrp_arr,
            Capability::CAP_CHMOD => &self.chmod_arr,
            Capability::CAP_CHATTR => &self.chattr_arr,
            Capability::CAP_CHROOT => &self.chroot_arr,
            Capability::CAP_UTIME => &self.utime_arr,
            Capability::CAP_MKBDEV => &self.mkbdev_arr,
            Capability::CAP_MKCDEV => &self.mkcdev_arr,
            Capability::CAP_MKFIFO => &self.mkfifo_arr,
            Capability::CAP_MKTEMP => &self.mktemp_arr,
            Capability::CAP_NET_BIND => &self.net_bind_arr,
            Capability::CAP_NET_CONNECT => &self.net_conn_arr,
            Capability::CAP_NET_SENDFD => &self.net_sendfd_arr,
            _ => unreachable!(),
        }
    }

    fn get_arr_mut(&mut self, cap: Capability) -> &mut Arr {
        match cap {
            Capability::CAP_WALK => &mut self.walk_arr,
            Capability::CAP_STAT => &mut self.stat_arr,
            Capability::CAP_READ => &mut self.read_arr,
            Capability::CAP_WRITE => &mut self.write_arr,
            Capability::CAP_EXEC => &mut self.exec_arr,
            Capability::CAP_CREATE => &mut self.create_arr,
            Capability::CAP_DELETE => &mut self.delete_arr,
            Capability::CAP_RENAME => &mut self.rename_arr,
            Capability::CAP_SYMLINK => &mut self.symlink_arr,
            Capability::CAP_TRUNCATE => &mut self.truncate_arr,
            Capability::CAP_CHDIR => &mut self.chdir_arr,
            Capability::CAP_READDIR => &mut self.readdir_arr,
            Capability::CAP_MKDIR => &mut self.mkdir_arr,
            Capability::CAP_RMDIR => &mut self.rmdir_arr,
            Capability::CAP_CHOWN => &mut self.chown_arr,
            Capability::CAP_CHGRP => &mut self.chgrp_arr,
            Capability::CAP_CHMOD => &mut self.chmod_arr,
            Capability::CAP_CHATTR => &mut self.chattr_arr,
            Capability::CAP_CHROOT => &mut self.chroot_arr,
            Capability::CAP_UTIME => &mut self.utime_arr,
            Capability::CAP_MKBDEV => &mut self.mkbdev_arr,
            Capability::CAP_MKCDEV => &mut self.mkcdev_arr,
            Capability::CAP_MKFIFO => &mut self.mkfifo_arr,
            Capability::CAP_MKTEMP => &mut self.mktemp_arr,
            Capability::CAP_NET_BIND => &mut self.net_bind_arr,
            Capability::CAP_NET_CONNECT => &mut self.net_conn_arr,
            Capability::CAP_NET_SENDFD => &mut self.net_sendfd_arr,
            _ => unreachable!(),
        }
    }

    /// Returns the default action for the given capability.
    pub fn default_action(&self, cap: Capability) -> Action {
        let idx = match cap {
            Capability::CAP_FS => DEF_ACT_FS_IDX,
            Capability::CAP_WALK => DEF_ACT_WALK_IDX,
            Capability::CAP_STAT => DEF_ACT_STAT_IDX,
            Capability::CAP_READ => DEF_ACT_READ_IDX,
            Capability::CAP_WRITE => DEF_ACT_WRITE_IDX,
            Capability::CAP_EXEC => DEF_ACT_EXEC_IDX,
            Capability::CAP_IOCTL => DEF_ACT_IOCTL_IDX,
            Capability::CAP_CREATE => DEF_ACT_CREATE_IDX,
            Capability::CAP_DELETE => DEF_ACT_DELETE_IDX,
            Capability::CAP_RENAME => DEF_ACT_RENAME_IDX,
            Capability::CAP_SYMLINK => DEF_ACT_SYMLINK_IDX,
            Capability::CAP_TRUNCATE => DEF_ACT_TRUNCATE_IDX,
            Capability::CAP_CHDIR => DEF_ACT_CHDIR_IDX,
            Capability::CAP_READDIR => DEF_ACT_READDIR_IDX,
            Capability::CAP_MKDIR => DEF_ACT_MKDIR_IDX,
            Capability::CAP_RMDIR => DEF_ACT_RMDIR_IDX,
            Capability::CAP_CHOWN => DEF_ACT_CHOWN_IDX,
            Capability::CAP_CHGRP => DEF_ACT_CHGRP_IDX,
            Capability::CAP_CHMOD => DEF_ACT_CHMOD_IDX,
            Capability::CAP_CHATTR => DEF_ACT_CHATTR_IDX,
            Capability::CAP_CHROOT => DEF_ACT_CHROOT_IDX,
            Capability::CAP_UTIME => DEF_ACT_UTIME_IDX,
            Capability::CAP_MKBDEV => DEF_ACT_MKBDEV_IDX,
            Capability::CAP_MKCDEV => DEF_ACT_MKCDEV_IDX,
            Capability::CAP_MKFIFO => DEF_ACT_MKFIFO_IDX,
            Capability::CAP_MKTEMP => DEF_ACT_MKTEMP_IDX,
            Capability::CAP_NET_BIND => DEF_ACT_NET_BIND_IDX,
            Capability::CAP_NET_CONNECT => DEF_ACT_NET_CONNECT_IDX,
            Capability::CAP_NET_SENDFD => DEF_ACT_NET_SENDFD_IDX,
            Capability::CAP_MEM => DEF_ACT_MEM_IDX,
            Capability::CAP_PID => DEF_ACT_PID_IDX,
            Capability::CAP_FORCE => DEF_ACT_FORCE_IDX,
            Capability::CAP_TPE => DEF_ACT_TPE_IDX,
            Capability::CAP_LOCK => DEF_ACT_LANDLOCK_IDX,
            _ => return Action::default(),
        };

        self.default_act
            .get(idx)
            .copied()
            .unwrap_or_else(Action::default)
    }

    /// Sets the default action for the given capability.
    pub fn set_default_action(&mut self, cap: Capability, action: Action) {
        let idx = match cap {
            Capability::CAP_FS => DEF_ACT_FS_IDX,
            Capability::CAP_WALK => DEF_ACT_WALK_IDX,
            Capability::CAP_STAT => DEF_ACT_STAT_IDX,
            Capability::CAP_READ => DEF_ACT_READ_IDX,
            Capability::CAP_WRITE => DEF_ACT_WRITE_IDX,
            Capability::CAP_EXEC => DEF_ACT_EXEC_IDX,
            Capability::CAP_IOCTL => DEF_ACT_IOCTL_IDX,
            Capability::CAP_CREATE => DEF_ACT_CREATE_IDX,
            Capability::CAP_DELETE => DEF_ACT_DELETE_IDX,
            Capability::CAP_RENAME => DEF_ACT_RENAME_IDX,
            Capability::CAP_SYMLINK => DEF_ACT_SYMLINK_IDX,
            Capability::CAP_TRUNCATE => DEF_ACT_TRUNCATE_IDX,
            Capability::CAP_CHDIR => DEF_ACT_CHDIR_IDX,
            Capability::CAP_READDIR => DEF_ACT_READDIR_IDX,
            Capability::CAP_MKDIR => DEF_ACT_MKDIR_IDX,
            Capability::CAP_RMDIR => DEF_ACT_RMDIR_IDX,
            Capability::CAP_CHOWN => DEF_ACT_CHOWN_IDX,
            Capability::CAP_CHGRP => DEF_ACT_CHGRP_IDX,
            Capability::CAP_CHMOD => DEF_ACT_CHMOD_IDX,
            Capability::CAP_CHATTR => DEF_ACT_CHATTR_IDX,
            Capability::CAP_CHROOT => DEF_ACT_CHROOT_IDX,
            Capability::CAP_UTIME => DEF_ACT_UTIME_IDX,
            Capability::CAP_MKBDEV => DEF_ACT_MKBDEV_IDX,
            Capability::CAP_MKCDEV => DEF_ACT_MKCDEV_IDX,
            Capability::CAP_MKFIFO => DEF_ACT_MKFIFO_IDX,
            Capability::CAP_MKTEMP => DEF_ACT_MKTEMP_IDX,
            Capability::CAP_NET_BIND => DEF_ACT_NET_BIND_IDX,
            Capability::CAP_NET_CONNECT => DEF_ACT_NET_CONNECT_IDX,
            Capability::CAP_NET_SENDFD => DEF_ACT_NET_SENDFD_IDX,
            Capability::CAP_MEM => DEF_ACT_MEM_IDX,
            Capability::CAP_PID => DEF_ACT_PID_IDX,
            Capability::CAP_FORCE => DEF_ACT_FORCE_IDX,
            Capability::CAP_TPE => DEF_ACT_TPE_IDX,
            Capability::CAP_LOCK => DEF_ACT_LANDLOCK_IDX,
            _ => return,
        };

        self.default_act[idx] = action
    }

    /// Returns net/block default action.
    fn net_block_act(&self) -> Action {
        self.default_act
            .get(DEF_ACT_NET_BLOCK_IDX)
            .copied()
            .unwrap_or_else(Action::default)
    }

    /// Sets the net/block default action.
    fn set_net_block_act(&mut self, action: Action) {
        self.default_act[DEF_ACT_NET_BLOCK_IDX] = action
    }

    /// Returns segvguard default action.
    fn segvguard_act(&self) -> Action {
        self.default_act
            .get(DEF_ACT_SEGVGUARD_IDX)
            .copied()
            .unwrap_or_else(Action::default)
    }

    /// Sets the segvguard default action.
    fn set_segvguard_act(&mut self, action: Action) {
        self.default_act[DEF_ACT_SEGVGUARD_IDX] = action
    }

    /// Returns landlock default action as a `CompatLevel`.
    fn landlock_compat_level(&self) -> CompatLevel {
        match self.default_act[DEF_ACT_LANDLOCK_IDX] {
            Action::Kill => CompatLevel::HardRequirement,
            Action::Deny => CompatLevel::SoftRequirement,
            Action::Warn => CompatLevel::BestEffort,
            act => unreachable!("BUG: Invalid Landlock default action `{act}'!"),
        }
    }

    /// Sets landlock default action.
    fn set_landlock_act(&mut self, action: Action) {
        self.default_act[DEF_ACT_LANDLOCK_IDX] = action
    }

    /// Return the proxy sandbox address for logging purposes.
    ///
    /// This may be a UNIX socket address or an address in format `IP!PORT`.
    pub fn proxy_repr(&self) -> String {
        self.proxy_ext_unix
            .as_ref()
            .map(|unix| unix.to_string())
            .unwrap_or_else(|| format!("{}!{}", self.proxy_ext_addr, self.proxy_ext_port))
    }

    /// Return IPv4 blocklist.
    pub fn block4(&self) -> &IpRange<Ipv4Net> {
        &self.net_block_lst.0
    }

    /// Return IPv6 blocklist.
    pub fn block6(&self) -> &IpRange<Ipv6Net> {
        &self.net_block_lst.1
    }

    /// Return true if IP blocklists are populated.
    pub fn has_block(&self) -> bool {
        !self.block4().is_empty() || !self.block6().is_empty()
    }

    /// Return true if Proxy is configured.
    pub fn has_proxy(&self) -> bool {
        self.enabled(Capability::CAP_PROXY)
    }

    /// Return true if Filesystem sandboxing is enabled.
    pub fn has_fs(&self) -> bool {
        self.enabled(Capability::CAP_FS)
    }

    /// Return true if PTY is configured.
    pub fn has_pty(&self) -> bool {
        self.enabled(Capability::CAP_PTY)
    }

    /// Initialize the KCAPI connection.
    pub(crate) fn set_crypt(&mut self) -> Result<(), Errno> {
        if self.enabled(Capability::CAP_CRYPT) {
            if let Some(ref mut crypt_id) = self.crypt_id {
                // SAFETY:
                // 1. `Secret::init` clears crypt_id from memory.
                // 2. `Secret::init` validates {enc,mac}_key_id is NOT zero.
                crypt_id.init()?;

                Ok(())
            } else {
                Err(Errno::ENOKEY)
            }
        } else {
            // Crypt sandboxing not enabled,
            // nothing to do.
            Ok(())
        }
    }

    /// Return true if ioctl names should be logged.
    pub fn log_ioctl(&self) -> bool {
        self.verbose >= 1
    }

    /// Return true if PR_SET_NAME prctl(2) should be logged.
    pub fn log_prctl(&self) -> bool {
        self.verbose >= 2
    }

    /// Return true if seccomp(2) requests should be enriched.
    pub fn log_scmp(&self) -> bool {
        self.verbose >= 3
    }

    /// Increase verbosity by one level, cap at max.
    pub fn increase_verbosity(&mut self) {
        let mut val = self.verbose;
        val = val.saturating_add(1).min(Self::LOG_MAX);
        self.verbose = val;
    }

    /// The highest supported verbosity level.
    const LOG_MAX: u8 = 3;

    /// Return a list of denylisted ioctl requests by architecture.
    pub(crate) fn get_ioctl_deny(&self) -> RawIoctlMap {
        let mut map = RawIoctlMap::default();

        for ((req, req_arch), deny) in &self.ioctl_set {
            if !*deny {
                continue;
            }

            #[expect(clippy::disallowed_methods)]
            map.entry(scmp_arch(*req_arch).unwrap())
                .or_insert_with(Vec::new)
                .push(*req);
        }

        map
    }

    /// Check if given ioctl(2) request is allowed.
    pub(crate) fn check_ioctl(&self, request: u64, arch: ScmpArch) -> Action {
        // Check if the request is explicitly allowed or denied.
        if let Some(deny) = self.ioctl_set.get(&(request, scmp_arch_raw(arch))).copied() {
            return if deny { Action::Deny } else { Action::Allow };
        }

        // Fallback to default action if ioctl sandboxing is enabled.
        if self.enabled(Capability::CAP_IOCTL) {
            self.default_action(Capability::CAP_IOCTL)
        } else {
            // Ioctl sandboxing is disabled (Blacklist mode).
            // Unknown requests are allowed.
            Action::Allow
        }
    }

    /// Add an ioctl request to the allowlist.
    fn add_ioctl_allow(&mut self, name: &str) -> Result<(), Errno> {
        self.add_ioctl(name, false)
    }

    /// Add an ioctl request to the denylist.
    fn add_ioctl_deny(&mut self, name: &str) -> Result<(), Errno> {
        self.add_ioctl(name, true)
    }

    /// Add an ioctl(2) request to the allowlist or denylist.
    fn add_ioctl(&mut self, name: &str, deny: bool) -> Result<(), Errno> {
        let ioctl = IoctlMap::new(None, true);
        for arch in SCMP_ARCH {
            #[expect(clippy::unnecessary_cast)]
            if let Some(value) = ioctl.get_value(name, *arch) {
                let arch = scmp_arch_raw(*arch);
                let request = value as u64;

                self.ioctl_set.insert((request, arch), deny)?;
                if let Some(request) = extend_ioctl(request) {
                    self.ioctl_set.insert((request, arch), deny)?;
                }
            }
        }

        Ok(())
    }

    fn add_append(&mut self, pat: XPathBuf, meth: MatchMethod) -> Result<(), Errno> {
        self.append_acl.push_front((pat, meth))
    }

    fn rem_append(&mut self, pat: &XPath, meth: MatchMethod) -> Result<(), Errno> {
        self.append_acl
            .retain(|(p, m)| meth != *m || !litmatch(pat.as_bytes(), p.as_bytes()))
    }

    fn del_append(&mut self, pat: &XPath, meth: MatchMethod) {
        if let Some(index) = self
            .append_acl
            .iter()
            .position(|(p, m)| meth == *m && litmatch(pat.as_bytes(), p.as_bytes()))
        {
            self.append_acl.remove(index);
        }
    }

    fn add_mask(
        &mut self,
        pat: XPathBuf,
        meth: MatchMethod,
        mask_all: Option<XPathBuf>,
        mask_dir: Option<XPathBuf>,
    ) -> Result<(), Errno> {
        let rule = MaskRule {
            meth,
            mask: Mask { mask_all, mask_dir },
        };
        self.mask_acl.push_front((pat, rule)).map(drop)
    }

    fn rem_mask(&mut self) {
        self.mask_acl.clear()
    }

    fn del_mask(&mut self, pat: &XPath, meth: MatchMethod) -> Result<(), Errno> {
        self.mask_acl.retain(|(pattern, rule)| {
            meth != rule.meth || !litmatch(pat.as_bytes(), pattern.as_bytes())
        })
    }

    fn add_glob(
        &mut self,
        act: Action,
        caps: Capability,
        pat: &XPath,
        meth: MatchMethod,
    ) -> Result<(), Errno> {
        for cap in caps {
            if act == Action::Filter {
                let arr = self.get_arr_mut(cap);
                arr.push_front((pat.to_owned(), meth))?;
            } else {
                let acl = self.get_acl_mut(cap);
                acl.push_front((pat.to_owned(), meth, act))?;
            }
        }

        Ok(())
    }

    fn rem_glob(
        &mut self,
        act: Action,
        caps: Capability,
        pat: &XPath,
        meth: MatchMethod,
    ) -> Result<(), Errno> {
        for cap in caps {
            if act == Action::Filter {
                let arr = self.get_arr_mut(cap);
                arr.retain(|(p, m)| meth != *m || *pat != *p)?;
            } else {
                let acl = self.get_acl_mut(cap);
                acl.retain(|(p, m, a)| meth != *m || act != *a || *pat != *p)?;
            }
        }

        Ok(())
    }

    fn del_glob(&mut self, act: Action, caps: Capability, pat: &XPath, meth: MatchMethod) {
        for cap in caps {
            if act == Action::Filter {
                let arr = self.get_arr_mut(cap);
                if let Some(index) = arr.iter().position(|(p, m)| meth == *m && *pat == *p) {
                    arr.remove(index);
                }
            } else {
                let acl = self.get_acl_mut(cap);
                if let Some(index) = acl
                    .iter()
                    .position(|(p, m, a)| meth == *m && act == *a && *pat == *p)
                {
                    acl.remove(index);
                }
            }
        }
    }

    fn rem_crypt(&mut self, pat: &XPath, meth: MatchMethod) -> Result<(), Errno> {
        self.crypt_acl
            .retain(|(p, m)| meth != *m || !litmatch(pat.as_bytes(), p.as_bytes()))
    }

    fn del_crypt(&mut self, pat: &XPath, meth: MatchMethod) {
        if let Some(index) = self
            .crypt_acl
            .iter()
            .position(|(p, m)| meth == *m && litmatch(pat.as_bytes(), p.as_bytes()))
        {
            self.crypt_acl.remove(index);
        }
    }

    fn add_crypt(&mut self, pat: XPathBuf, meth: MatchMethod) -> Result<(), Errno> {
        self.crypt_acl.push_front((pat, meth))
    }

    /// Get the process ID of the syd execve child.
    pub fn get_child_pid(&self) -> Pid {
        Pid::from_raw(self.cpid)
    }

    /// Set the process ID of the syd execve child.
    pub(crate) fn set_child(&mut self, pid: Pid, pid_fd: RawFd) {
        self.cpid = pid.as_raw();
        self.fpid = pid_fd;
    }

    /// Returns true if syd execve child is still alive.
    fn child_is_alive(&self) -> bool {
        self.fpid == libc::AT_FDCWD
            // SAFETY: fpid is a valid PID file descriptor.
            || unsafe { libc::syscall(libc::SYS_pidfd_send_signal, self.fpid, 0, 0, 0) }
                == 0
    }

    /// Return true of the sandbox is running.
    fn is_running(&self) -> bool {
        !self.fpid.is_negative()
    }

    /// Return the memory access mode of the sandbox.
    pub fn memory_access() -> u8 {
        if PROC_PID_MEM_FORCE.load(std::sync::atomic::Ordering::Relaxed) {
            // mode:1 -> use proc_pid_mem(5) unconditionally.
            1
        } else if PROC_PID_MEM_FBACK.load(std::sync::atomic::Ordering::Relaxed) {
            // mode:0 -> use cross memory fallback to proc_pid_mem(5).
            0
        } else {
            // mode:2 -> use cross memory unconditionally (default).
            2
        }
    }

    /// Returns true if proc_pid_mem(5) should be used
    /// instead of process_vm_readv(2), process_vm_writev(2)
    pub fn use_proc_pid_mem() -> bool {
        match Self::memory_access() {
            1 => true,
            0 if !*HAVE_CROSS_MEMORY_ATTACH => true,
            _ => false,
        }
    }

    /// Get pty row size
    pub fn pty_ws_x(&self) -> Option<libc::c_ushort> {
        self.pty_ws_x
    }

    /// Get pty column size
    pub fn pty_ws_y(&self) -> Option<libc::c_ushort> {
        self.pty_ws_y
    }

    /// Return the enabled capabilities out of the given set of capabilities.
    pub fn getcaps(&self, caps: Capability) -> Capability {
        *self.state & caps
    }

    /// Return true if the sandboxing is enabled for the given capability.
    pub fn enabled(&self, cap: Capability) -> bool {
        self.enabled_all(cap)
    }

    /// Return true if the sandboxing is enabled for the given capability.
    pub fn enabled_all(&self, caps: Capability) -> bool {
        self.state.contains(caps)
    }

    /// Return true if any of the sandboxing capabilities is enabled.
    pub fn enabled_any(&self, caps: Capability) -> bool {
        self.state.intersects(caps)
    }

    /// Chroot sandbox.
    pub fn chroot(&mut self) {
        self.chroot = true;
    }

    /// Return true if sandbox has chrooted.
    pub fn is_chroot(&self) -> bool {
        self.chroot
    }

    /// Lock sandbox.
    #[expect(clippy::cognitive_complexity)]
    pub fn lock(&mut self, state: LockState) -> Result<(), Errno> {
        if matches!(self.lock, Some(state) if state.is_locked()) {
            if state == LockState::Set && self.lock == Some(LockState::Set) {
                // Locking again when already locked is no-op.
                Ok(())
            } else if state == LockState::Read && self.lock == Some(LockState::Read) {
                // Locking Read again when already Read locked is no-op.
                Ok(())
            } else {
                // No going back once locked or switching states between Read and Set.
                // This is not physically possible due to mseal(2) boundary.
                Err(Errno::EBUSY)
            }
        } else if state.is_locked() {
            // Locked for the first and last time!
            // Farewell sandbox policy write rights.
            if self.is_running() {
                // If we're running already seal immediately,
                // otherwise seal will happen on cpid set.
                self.seal()?;
            }

            self.lock = Some(state);
            LOCKED.call_once(|| {});

            // SAFETY: Log global Syslog data so
            // that the ring buffer is no longer available,
            // unless trace/allow_safe_syslog:1 is set at startup.
            #[cfg(feature = "log")]
            if !self.flags.allow_safe_syslog() {
                if let Some(syslog) = crate::syslog::global_syslog() {
                    syslog.lock();
                }
            }

            info!("ctx": "lock_sandbox",
                "msg": format!("{}locked sandbox {} the start of sandbox process",
                    if state == LockState::Read { "read " } else { "" },
                    if self.is_running() { "after" } else { "before" }),
                "run": self.is_running(), "state": state);

            Ok(())
        } else if self.oci && state == LockState::Ipc {
            Err(Errno::EOPNOTSUPP)
        } else {
            self.lock = Some(state);
            Ok(())
        }
    }

    /// Returns true if the sandbox is locked.
    pub fn locked(&self) -> bool {
        matches!(self.lock, Some(state) if state.is_locked())
    }

    /// Returns true if the sandbox is locked without having to lock the
    /// sandbox first. This depends on a global atomic variable and
    /// will not work if you have more than once `Sandbox` instance.
    /// Use `locked` function instead in this case.
    pub fn locked_once() -> bool {
        LOCKED.is_completed()
    }

    /// Returns true if the sandbox is locked at startup.
    pub fn locked_pre(&self) -> bool {
        // `set_child_pid` will turn None to LockState::Set.
        match self.lock {
            None => true,
            Some(state) if state.is_locked() => true,
            _ => false,
        }
    }

    /// Returns true if the sandbox is read-locked for the given process ID.
    ///
    /// Used to gate open(2) part of the syd(2) virtual system call API for LockState::Read.
    pub fn locked_read_for(&self, pid: Pid) -> bool {
        match self.lock {
            None => false, // same state as cpid==0.
            Some(LockState::Off | LockState::Read) => false,
            Some(LockState::Exec) if self.cpid == 0 => false,
            Some(LockState::Exec) if self.cpid == pid.as_raw() => !self.child_is_alive(),
            _ => true,
        }
    }

    /// Returns true if the sandbox is locked for the given process ID.
    pub fn locked_for(&self, pid: Pid) -> bool {
        match self.lock {
            None => false, // same state as cpid==0.
            Some(LockState::Off) => false,
            Some(LockState::Exec) if self.cpid == 0 => false,
            Some(LockState::Exec) if self.cpid == pid.as_raw() => !self.child_is_alive(),
            _ => true,
        }
    }

    /// Returns true if Landlock sandboxing is enabled.
    pub fn landlocked(&self) -> bool {
        self.state.contains(Capability::CAP_LOCK)
    }

    /// Return masked sandbox OS release.
    pub fn os_release() -> &'static OsStr {
        let release = KERNEL_VERSION_STR.as_bytes();
        let relcopy = release.len().min(UTSNAME_LEN - 1);
        OsStr::from_bytes(&release[..relcopy])
    }

    /// Return masked sandbox uname.
    pub fn mask_uname(&self, utsname: &mut UtsName) {
        // Change the release with Syd kernel version.
        //
        // Step 1: Clear the release field.
        utsname.release.fill(0);

        // Step 2: Copy Syd kernel version string to utsname.release.
        // If the string is longer than 65 characters, it's truncated.
        let release = KERNEL_VERSION_STR.as_bytes();
        let relcopy = release.len().min(UTSNAME_LEN - 1);
        utsname.release[..relcopy].copy_from_slice(&release[..relcopy]);

        // Write nodename, domainname, and version fields based on sandbox.
        // Truncate to fit into 65 characters ensuring the NUL-byte.
        //
        // Write utsname.nodename as necessary.
        if let Some(hostname) = self.hostname.as_ref() {
            utsname.nodename.fill(0);
            let hname = hostname.as_bytes();
            let hcopy = hname.len().min(UTSNAME_LEN - 1);
            utsname.nodename[..hcopy].copy_from_slice(&hname[..hcopy]);
        }

        // Write utsname.domainname as necessary.
        if let Some(domainname) = self.domainname.as_ref() {
            utsname.domainname.fill(0);
            let dname = domainname.as_bytes();
            let dcopy = dname.len().min(UTSNAME_LEN - 1);
            utsname.domainname[..dcopy].copy_from_slice(&dname[..dcopy]);
        }

        // Write utsname.version as necessary.
        if let Some(version) = self.version.as_ref() {
            utsname.version.fill(0);
            let vname = version.as_bytes();
            let vcopy = vname.len().min(UTSNAME_LEN - 1);
            utsname.version[..vcopy].copy_from_slice(&vname[..vcopy]);
        }
    }

    /// Seals read-only sealable regions of the Sandbox.
    #[expect(clippy::cognitive_complexity)]
    pub fn seal(&mut self) -> Result<(), Errno> {
        if self.flags.allow_unsafe_nomseal() {
            // Sealing disabled at startup by user.
            return Ok(());
        }

        // Seal sandboxing options.
        self.flags = std::mem::take(&mut self.flags).seal(Some(c" Syd: sandbox/flags"))?;

        // Seal sandboxing categories.
        self.state = std::mem::take(&mut self.state).seal(Some(c" Syd: sandbox/capabilities"))?;

        // Seal default actions.
        self.default_act =
            std::mem::take(&mut self.default_act).seal(Some(c" Syd: sandbox/actions"))?;

        // Seal access control lists and filters.
        // Clear access control lists for which sandboxing is off.
        // Sealing turns empty vectors into guard pages.

        if !self.enabled(Capability::CAP_FS) {
            self.fs_acl.clear();
            self.fs_arr.clear();
        }
        self.fs_acl = std::mem::take(&mut self.fs_acl).seal(Some(c" Syd: sandbox/fs/rules"))?;
        self.fs_arr = std::mem::take(&mut self.fs_arr).seal(Some(c" Syd: sandbox/fs/filters"))?;

        if !self.enabled(Capability::CAP_WALK) {
            self.walk_acl.clear();
            self.walk_arr.clear();
        }
        self.walk_acl =
            std::mem::take(&mut self.walk_acl).seal(Some(c" Syd: sandbox/walk/rules"))?;
        self.walk_arr =
            std::mem::take(&mut self.walk_arr).seal(Some(c" Syd: sandbox/walk/filters"))?;

        if !self.enabled(Capability::CAP_STAT) {
            self.stat_acl.clear();
            self.stat_arr.clear();
        }
        self.stat_acl =
            std::mem::take(&mut self.stat_acl).seal(Some(c" Syd: sandbox/stat/rules"))?;
        self.stat_arr =
            std::mem::take(&mut self.stat_arr).seal(Some(c" Syd: sandbox/stat/filters"))?;

        if !self.enabled(Capability::CAP_READ) {
            self.read_acl.clear();
            self.read_arr.clear();
        }
        self.read_acl =
            std::mem::take(&mut self.read_acl).seal(Some(c" Syd: sandbox/read/rules"))?;
        self.read_arr =
            std::mem::take(&mut self.read_arr).seal(Some(c" Syd: sandbox/read/filters"))?;

        if !self.enabled(Capability::CAP_WRITE) {
            self.write_acl.clear();
            self.write_arr.clear();
        }
        self.write_acl =
            std::mem::take(&mut self.write_acl).seal(Some(c" Syd: sandbox/write/rules"))?;
        self.write_arr =
            std::mem::take(&mut self.write_arr).seal(Some(c" Syd: sandbox/write/filters"))?;

        if !self.enabled(Capability::CAP_EXEC) {
            self.exec_acl.clear();
            self.exec_arr.clear();
        }
        self.exec_acl =
            std::mem::take(&mut self.exec_acl).seal(Some(c" Syd: sandbox/exec/rules"))?;
        self.exec_arr =
            std::mem::take(&mut self.exec_arr).seal(Some(c" Syd: sandbox/exec/filters"))?;

        if !self.enabled(Capability::CAP_CREATE) {
            self.create_acl.clear();
            self.create_arr.clear();
        }
        self.create_acl =
            std::mem::take(&mut self.create_acl).seal(Some(c" Syd: sandbox/create/rules"))?;
        self.create_arr =
            std::mem::take(&mut self.create_arr).seal(Some(c" Syd: sandbox/create/filters"))?;

        if !self.enabled(Capability::CAP_DELETE) {
            self.delete_acl.clear();
            self.delete_arr.clear();
        }
        self.delete_acl =
            std::mem::take(&mut self.delete_acl).seal(Some(c" Syd: sandbox/delete/rules"))?;
        self.delete_arr =
            std::mem::take(&mut self.delete_arr).seal(Some(c" Syd: sandbox/delete/filters"))?;

        if !self.enabled(Capability::CAP_RENAME) {
            self.rename_acl.clear();
            self.rename_arr.clear();
        }
        self.rename_acl =
            std::mem::take(&mut self.rename_acl).seal(Some(c" Syd: sandbox/rename/rules"))?;
        self.rename_arr =
            std::mem::take(&mut self.rename_arr).seal(Some(c" Syd: sandbox/rename/filters"))?;

        if !self.enabled(Capability::CAP_SYMLINK) {
            self.symlink_acl.clear();
            self.symlink_arr.clear();
        }
        self.symlink_acl =
            std::mem::take(&mut self.symlink_acl).seal(Some(c" Syd: sandbox/symlink/rules"))?;
        self.symlink_arr =
            std::mem::take(&mut self.symlink_arr).seal(Some(c" Syd: sandbox/symlink/filters"))?;

        if !self.enabled(Capability::CAP_TRUNCATE) {
            self.truncate_acl.clear();
            self.truncate_arr.clear();
        }
        self.truncate_acl =
            std::mem::take(&mut self.truncate_acl).seal(Some(c" Syd: sandbox/truncate/rules"))?;
        self.truncate_arr =
            std::mem::take(&mut self.truncate_arr).seal(Some(c" Syd: sandbox/truncate/filters"))?;

        if !self.enabled(Capability::CAP_CHDIR) {
            self.chdir_acl.clear();
            self.chdir_arr.clear();
        }
        self.chdir_acl =
            std::mem::take(&mut self.chdir_acl).seal(Some(c" Syd: sandbox/chdir/rules"))?;
        self.chdir_arr =
            std::mem::take(&mut self.chdir_arr).seal(Some(c" Syd: sandbox/chdir/filters"))?;

        if !self.enabled(Capability::CAP_READDIR) {
            self.readdir_acl.clear();
            self.readdir_arr.clear();
        }
        self.readdir_acl =
            std::mem::take(&mut self.readdir_acl).seal(Some(c" Syd: sandbox/readdir/rules"))?;
        self.readdir_arr =
            std::mem::take(&mut self.readdir_arr).seal(Some(c" Syd: sandbox/readdir/filters"))?;

        if !self.enabled(Capability::CAP_MKDIR) {
            self.mkdir_acl.clear();
            self.mkdir_arr.clear();
        }
        self.mkdir_acl =
            std::mem::take(&mut self.mkdir_acl).seal(Some(c" Syd: sandbox/mkdir/rules"))?;
        self.mkdir_arr =
            std::mem::take(&mut self.mkdir_arr).seal(Some(c" Syd: sandbox/mkdir/filters"))?;

        if !self.enabled(Capability::CAP_RMDIR) {
            self.rmdir_acl.clear();
            self.rmdir_arr.clear();
        }
        self.rmdir_acl =
            std::mem::take(&mut self.rmdir_acl).seal(Some(c" Syd: sandbox/rmdir/rules"))?;
        self.rmdir_arr =
            std::mem::take(&mut self.rmdir_arr).seal(Some(c" Syd: sandbox/rmdir/filters"))?;

        if !self.enabled(Capability::CAP_CHOWN) {
            self.chown_acl.clear();
            self.chown_arr.clear();
        }
        self.chown_acl =
            std::mem::take(&mut self.chown_acl).seal(Some(c" Syd: sandbox/chown/rules"))?;
        self.chown_arr =
            std::mem::take(&mut self.chown_arr).seal(Some(c" Syd: sandbox/chown/filters"))?;

        if !self.enabled(Capability::CAP_CHGRP) {
            self.chgrp_acl.clear();
            self.chgrp_arr.clear();
        }
        self.chgrp_acl =
            std::mem::take(&mut self.chgrp_acl).seal(Some(c" Syd: sandbox/chgrp/rules"))?;
        self.chgrp_arr =
            std::mem::take(&mut self.chgrp_arr).seal(Some(c" Syd: sandbox/chgrp/filters"))?;

        if !self.enabled(Capability::CAP_CHMOD) {
            self.chmod_acl.clear();
            self.chmod_arr.clear();
        }
        self.chmod_acl =
            std::mem::take(&mut self.chmod_acl).seal(Some(c" Syd: sandbox/chmod/rules"))?;
        self.chmod_arr =
            std::mem::take(&mut self.chmod_arr).seal(Some(c" Syd: sandbox/chmod/filters"))?;

        if !self.enabled(Capability::CAP_CHATTR) {
            self.chattr_acl.clear();
            self.chattr_arr.clear();
        }
        self.chattr_acl =
            std::mem::take(&mut self.chattr_acl).seal(Some(c" Syd: sandbox/chattr/rules"))?;
        self.chattr_arr =
            std::mem::take(&mut self.chattr_arr).seal(Some(c" Syd: sandbox/chattr/filters"))?;

        if !self.enabled(Capability::CAP_CHROOT) {
            self.chroot_acl.clear();
            self.chroot_arr.clear();
        }
        self.chroot_acl =
            std::mem::take(&mut self.chroot_acl).seal(Some(c" Syd: sandbox/chroot/rules"))?;
        self.chroot_arr =
            std::mem::take(&mut self.chroot_arr).seal(Some(c" Syd: sandbox/chroot/filters"))?;

        if !self.enabled(Capability::CAP_UTIME) {
            self.utime_acl.clear();
            self.utime_arr.clear();
        }
        self.utime_acl =
            std::mem::take(&mut self.utime_acl).seal(Some(c" Syd: sandbox/utime/rules"))?;
        self.utime_arr =
            std::mem::take(&mut self.utime_arr).seal(Some(c" Syd: sandbox/utime/filters"))?;

        if !self.enabled(Capability::CAP_MKBDEV) {
            self.mkbdev_acl.clear();
            self.mkbdev_arr.clear();
        }
        self.mkbdev_acl =
            std::mem::take(&mut self.mkbdev_acl).seal(Some(c" Syd: sandbox/mkbdev/rules"))?;
        self.mkbdev_arr =
            std::mem::take(&mut self.mkbdev_arr).seal(Some(c" Syd: sandbox/mkbdev/filters"))?;

        if !self.enabled(Capability::CAP_MKCDEV) {
            self.mkcdev_acl.clear();
            self.mkcdev_arr.clear();
        }
        self.mkcdev_acl =
            std::mem::take(&mut self.mkcdev_acl).seal(Some(c" Syd: sandbox/mkcdev/rules"))?;
        self.mkcdev_arr =
            std::mem::take(&mut self.mkcdev_arr).seal(Some(c" Syd: sandbox/mkcdev/filters"))?;

        if !self.enabled(Capability::CAP_MKFIFO) {
            self.mkfifo_acl.clear();
            self.mkfifo_arr.clear();
        }
        self.mkfifo_acl =
            std::mem::take(&mut self.mkfifo_acl).seal(Some(c" Syd: sandbox/mkfifo/rules"))?;
        self.mkfifo_arr =
            std::mem::take(&mut self.mkfifo_arr).seal(Some(c" Syd: sandbox/mkfifo/filters"))?;

        if !self.enabled(Capability::CAP_MKTEMP) {
            self.mktemp_acl.clear();
            self.mktemp_arr.clear();
        }
        self.mktemp_acl =
            std::mem::take(&mut self.mktemp_acl).seal(Some(c" Syd: sandbox/mktemp/rules"))?;
        self.mktemp_arr =
            std::mem::take(&mut self.mktemp_arr).seal(Some(c" Syd: sandbox/mktemp/filters"))?;

        let has_net_bind = self.enabled(Capability::CAP_NET_BIND);
        let has_net_connect = self.enabled(Capability::CAP_NET_CONNECT);
        let has_net_sendfd = self.enabled(Capability::CAP_NET_SENDFD);
        if !has_net_bind {
            self.net_bind_acl.clear();
            self.net_bind_arr.clear();
        }
        self.net_bind_acl =
            std::mem::take(&mut self.net_bind_acl).seal(Some(c" Syd: sandbox/net/bind/rules"))?;
        self.net_bind_arr =
            std::mem::take(&mut self.net_bind_arr).seal(Some(c" Syd: sandbox/net/bind/filters"))?;

        // Note, trace/allow_safe_bind:1 requires edits to the connect ACL
        // after the sandbox is locked so we leave it here as an exception.
        if !has_net_connect {
            self.net_conn_acl.clear();
            self.net_conn_arr.clear();
        }
        let allow_safe_bind = self.flags.allow_safe_bind();
        if !allow_safe_bind {
            self.net_conn_acl = std::mem::take(&mut self.net_conn_acl)
                .seal(Some(c" Syd: sandbox/net/connect/rules"))?;
        }
        self.net_conn_arr = std::mem::take(&mut self.net_conn_arr)
            .seal(Some(c" Syd: sandbox/net/connect/filters"))?;

        if !has_net_sendfd {
            self.net_sendfd_acl.clear();
            self.net_sendfd_arr.clear();
        }
        self.net_sendfd_acl = std::mem::take(&mut self.net_sendfd_acl)
            .seal(Some(c" Syd: sandbox/net/sendfd/rules"))?;
        self.net_sendfd_arr = std::mem::take(&mut self.net_sendfd_arr)
            .seal(Some(c" Syd: sandbox/net/sendfd/filters"))?;

        // ACL for Append-only.
        self.append_acl =
            std::mem::take(&mut self.append_acl).seal(Some(c" Syd: sandbox/append/rules"))?;

        // ACL for Crypt sandboxing.
        self.crypt_acl =
            std::mem::take(&mut self.crypt_acl).seal(Some(c" Syd: sandbox/crypt/rules"))?;

        // ACL for Path masking.
        self.mask_acl =
            std::mem::take(&mut self.mask_acl).seal(Some(c" Syd: sandbox/mask/rules"))?;

        // Seal Cidr rules.
        // Note, trace/allow_safe_bind:1 requires edits to the connect ACL
        // after the sandbox is locked so we leave it here as an exception.
        self.cidr_rules.retain_mut(|rule| {
            if !has_net_bind {
                rule.cap.remove(Capability::CAP_NET_BIND);
            }
            if !has_net_connect {
                rule.cap.remove(Capability::CAP_NET_CONNECT);
            }
            if !has_net_sendfd {
                rule.cap.remove(Capability::CAP_NET_SENDFD);
            }
            !rule.cap.is_empty()
        })?;
        if !allow_safe_bind {
            self.cidr_rules =
                std::mem::take(&mut self.cidr_rules).seal(Some(c" Syd: sandbox/net/rules"))?;
        }

        // Seal verified execution map.
        if !self.enabled(Capability::CAP_FORCE) {
            self.force_map.clear();
        }
        self.force_map =
            std::mem::take(&mut self.force_map).seal(Some(c" Syd: sandbox/force/rules"))?;

        // Seal ioctl(2) set.
        self.ioctl_set =
            std::mem::take(&mut self.ioctl_set).seal(Some(c" Syd: sandbox/ioctl/requests"))?;

        Ok(())
    }

    /// Set operating system version at uname(2) boundary.
    ///
    /// Name is limited to 64 characters.
    pub fn set_uts_version(&mut self, value: &str) -> Result<(), Errno> {
        let name = self.expand_env(value)?;

        if name.len() >= UTSNAME_LEN {
            // utsname.version is limited to 65 characters,
            // including the terminating NUL-byte.
            return Err(Errno::ENAMETOOLONG);
        }

        self.version = if !matches!(name.as_ref(), "none" | "off") {
            Some(CString::new(name.as_ref()).or(Err(Errno::EINVAL))?)
        } else {
            None
        };

        Ok(())
    }

    /// Set sandbox NIS/YP domainname.
    ///
    /// Name is limited to 64 characters.
    /// As of version 3.39.3, this value may be changed at runtime.
    pub fn set_uts_domain(&mut self, value: &str) -> Result<(), Errno> {
        let name = self.expand_env(value)?;

        if name.len() >= UTSNAME_LEN {
            // utsname.domainname is limited to 65 characters,
            // including the terminating NUL-byte.
            return Err(Errno::ENAMETOOLONG);
        }

        self.domainname = if !matches!(name.as_ref(), "none" | "off") {
            Some(CString::new(name.as_ref()).or(Err(Errno::EINVAL))?)
        } else {
            None
        };

        Ok(())
    }

    /// Set sandbox hostname.
    ///
    /// Name is limited to 64 characters.
    /// As of version 3.39.3, this value may be changed at runtime.
    pub fn set_uts_host(&mut self, value: &str) -> Result<(), Errno> {
        let name = self.expand_env(value)?;

        if name.len() >= UTSNAME_LEN {
            // utsname.nodename is limited to 65 characters,
            // including the terminating NUL-byte.
            return Err(Errno::ENAMETOOLONG);
        }

        self.hostname = if !matches!(name.as_ref(), "none" | "off") {
            Some(CString::new(name.as_ref()).or(Err(Errno::EINVAL))?)
        } else {
            None
        };

        Ok(())
    }

    /// Set the value of the unshare-mount flag.
    pub fn set_unshare_mount(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_MOUNT);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_MOUNT);
        }
    }

    /// Set the value of the unshare-uts flag.
    pub fn set_unshare_uts(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_UTS);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_UTS);
        }
    }

    /// Set the value of the unshare-ipc flag.
    pub fn set_unshare_ipc(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_IPC);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_IPC);
        }
    }

    /// Set the value of the unshare-user flag.
    pub fn set_unshare_user(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_USER);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_USER);
        }
    }

    /// Set the value of the unshare-pid flag.
    pub fn set_unshare_pid(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_PID);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_PID);
        }
    }

    /// Set the value of the unshare-net flag.
    pub fn set_unshare_net(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_NET);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_NET);
        }
    }

    /// Set the value of the unshare-cgroup flag.
    pub fn set_unshare_cgroup(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_CGROUP);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_CGROUP);
        }
    }

    /// Set the value of the unshare-time flag.
    pub fn set_unshare_time(&mut self, state: bool) {
        if state {
            self.flags.insert(Flags::FL_UNSHARE_TIME);
        } else {
            self.flags.remove(Flags::FL_UNSHARE_TIME);
        }
    }

    /// Returns the TPE Gid.
    pub fn tpe_gid(&self) -> Option<Gid> {
        self.tpe_gid
    }

    /// Get SegvGuard entry expiry timeout.
    pub fn get_segvguard_expiry(&self) -> Duration {
        self.segvguard_expiry
    }

    /// Set SegvGuard entry expiry timeout.
    pub fn set_segvguard_expiry(&mut self, timeout: Duration) {
        self.segvguard_expiry = timeout;
    }

    /// SegvGuard entry suspension timeout.
    pub fn get_segvguard_suspension(&self) -> Duration {
        self.segvguard_suspension
    }

    /// SegvGuard entry suspension timeout.
    pub fn set_segvguard_suspension(&mut self, timeout: Duration) {
        self.segvguard_suspension = timeout;
    }

    /// Get SegvGuard max number of crashes before expiry.
    pub fn get_segvguard_maxcrashes(&self) -> u8 {
        self.segvguard_maxcrashes
    }

    /// Set SegvGuard max number of crashes before expiry.
    pub fn set_segvguard_maxcrashes(&mut self, maxcrashes: u8) {
        self.segvguard_maxcrashes = maxcrashes;
    }

    /// Record a crash in the SegvGuard map.
    /// Returns the current number of crashes for the given path,
    /// and two booleans, one specifies whether the executable was
    /// suspended from execution, the second specifies whether the
    /// executable has just been suspended from execution.
    pub fn add_segvguard_crash(&mut self, path: &XPath) -> (bool, bool, u8) {
        if let Some(value) = self.segvguard_map_expiry.get_mut(path) {
            *value = value.saturating_add(1);
            let (was_suspended, is_suspended) = if *value >= self.segvguard_maxcrashes {
                (
                    true,
                    self.segvguard_map_suspension
                        .insert(path.to_owned(), (), self.segvguard_suspension.into())
                        .is_none(),
                )
            } else {
                (false, false)
            };
            (was_suspended, is_suspended, *value)
        } else {
            self.segvguard_map_expiry
                .insert(path.to_owned(), 1, self.segvguard_expiry.into());
            let (was_suspended, is_suspended) = if self.segvguard_maxcrashes <= 1 {
                (
                    true,
                    self.segvguard_map_suspension
                        .insert(path.to_owned(), (), self.segvguard_suspension.into())
                        .is_none(),
                )
            } else {
                (false, false)
            };
            (was_suspended, is_suspended, 1)
        }
    }

    /// Check SegvGuard for access.
    pub fn check_segvguard(&self, path: &XPath) -> Option<Action> {
        // Setting SegvGuard default action to Allow disables SegvGuard.
        // Setting expiry timeout to 0 disables SegvGuard.
        let segvguard_act = self.segvguard_act();
        if segvguard_act == Action::Allow
            || self.segvguard_expiry.is_zero()
            || !self.segvguard_map_suspension.contains_key(path)
        {
            None
        } else {
            Some(segvguard_act)
        }
    }

    /// Return true if there're any SegvGuard suspended paths.
    pub fn has_segvguard(&self) -> bool {
        !self.segvguard_map_suspension.is_empty()
    }

    /// Return true if trace/allow_safe_setuid is true,
    /// and at least one UID transition has been defined.
    ///
    /// This is used to determine whether the setuid family
    /// system calls should be hooked in the main seccomp filter.
    pub fn has_uid_transit(&self) -> bool {
        self.flags.allow_safe_setuid() && !self.transit_uids.is_empty()
    }

    /// Add a UID transit.
    /// If the sandbox did not previously contain this transition, Ok(true) is returned.
    /// If the sandbox did contain this transition, Ok(false) is returned, sandbox is not modified.
    pub fn add_uid_transit(&mut self, source_uid: Uid, target_uid: Uid) -> Result<bool, Errno> {
        if source_uid.as_raw() == target_uid.as_raw() {
            return Err(Errno::EINVAL);
        } else if target_uid.as_raw() <= UID_MIN.as_raw()
            || source_uid.as_raw() > target_uid.as_raw()
        {
            return Err(Errno::EACCES);
        }

        let transit = (source_uid, target_uid);
        if self.transit_uids.contains(&transit) {
            return Ok(false);
        }

        if self
            .transit_uids
            .iter()
            .any(|&(s_uid, _)| s_uid == source_uid)
        {
            // Transition exists with same source UID but different target UID.
            // The user should remove the old transition to add this one.
            return Err(Errno::EEXIST);
        }

        self.transit_uids.push(transit);
        Ok(true)
    }

    /// Delete a UID transit.
    /// If both source and target is None, clears all transit UIDs.
    /// If source is not None and target is None, remove all transit UIDs with the source.
    /// If source is None and target is not None, remove all transit UIDs with the target.
    /// If both is not None, delete the matching UID.
    pub fn del_uid_transit(&mut self, source_uid: Option<Uid>, target_uid: Option<Uid>) {
        match (source_uid, target_uid) {
            (None, None) => self.transit_uids.clear(),
            (Some(source), None) => self.transit_uids.retain(|&(s_uid, _)| s_uid != source),
            (None, Some(target)) => self.transit_uids.retain(|&(_, t_uid)| t_uid != target),
            (Some(source), Some(target)) => self
                .transit_uids
                .retain(|&(s_uid, t_uid)| s_uid != source || t_uid != target),
        }
    }

    /// Check a UID transit.
    /// Returns true for allowed, false for not allowed.
    pub fn chk_uid_transit(&self, source_uid: Uid, target_uid: Uid) -> bool {
        if target_uid.as_raw() <= UID_MIN.as_raw() || source_uid.as_raw() >= target_uid.as_raw() {
            return false;
        }

        for (s_uid, t_uid) in &self.transit_uids {
            if source_uid == *s_uid && target_uid == *t_uid {
                return true;
            }
        }

        false
    }

    /// Return true if trace/allow_safe_setgid is true,
    /// and at least one GID transition has been defined.
    ///
    /// This is used to determine whether the setgid family
    /// system calls should be hooked in the main seccomp filter.
    pub fn has_gid_transit(&self) -> bool {
        self.flags.allow_safe_setgid() && !self.transit_gids.is_empty()
    }

    /// Add a GID transit.
    /// If the sandbox did not previously contain this transition, Ok(true) is returned.
    /// If the sandbox did contain this transition, Ok(false) is returned, sandbox is not modified.
    pub fn add_gid_transit(&mut self, source_gid: Gid, target_gid: Gid) -> Result<bool, Errno> {
        if source_gid.as_raw() == target_gid.as_raw() {
            return Err(Errno::EINVAL);
        } else if target_gid.as_raw() <= GID_MIN.as_raw()
            || source_gid.as_raw() > target_gid.as_raw()
        {
            return Err(Errno::EACCES);
        }

        let transit = (source_gid, target_gid);
        if self.transit_gids.contains(&transit) {
            return Ok(false);
        }

        if self
            .transit_gids
            .iter()
            .any(|&(s_gid, _)| s_gid == source_gid)
        {
            // Transition exists with same source GID but different target GID.
            // The user should remove the old transition to add this one.
            return Err(Errno::EEXIST);
        }

        self.transit_gids.push(transit);
        Ok(true)
    }

    /// Delete a GID transit.
    /// If both source and target is None, clears all transit GIDs.
    /// If source is not None and target is None, remove all transit GIDs with the source.
    /// If source is None and target is not None, remove all transit GIDs with the target.
    /// If both is not None, delete the matching GID.
    pub fn del_gid_transit(&mut self, source_gid: Option<Gid>, target_gid: Option<Gid>) {
        match (source_gid, target_gid) {
            (None, None) => self.transit_gids.clear(),
            (Some(source), None) => self.transit_gids.retain(|&(s_gid, _)| s_gid != source),
            (None, Some(target)) => self.transit_gids.retain(|&(_, t_gid)| t_gid != target),
            (Some(source), Some(target)) => self
                .transit_gids
                .retain(|&(s_gid, t_gid)| s_gid != source || t_gid != target),
        }
    }

    /// Check a GID transit.
    /// Returns true for allowed, false for not allowed.
    pub fn chk_gid_transit(&self, source_gid: Gid, target_gid: Gid) -> bool {
        if target_gid.as_raw() <= GID_MIN.as_raw() || source_gid.as_raw() >= target_gid.as_raw() {
            return false;
        }

        for (s_gid, t_gid) in &self.transit_gids {
            if source_gid == *s_gid && target_gid == *t_gid {
                return true;
            }
        }

        false
    }

    /// Add a bind mount action to the list of mount actions.
    pub fn add_bind_mount(&mut self, mount: BindMount) {
        if let Some(ref mut mounts) = self.bind_mounts {
            mounts.push(mount);
        } else {
            self.bind_mounts = Some(vec![mount]);
        }
    }

    /// Remove the first matching item from the end of the list of mount actions.
    pub fn del_bind_mount(&mut self, mount: BindMount) {
        if let Some(ref mut mounts) = self.bind_mounts {
            if let Some(pos) = mounts.iter().rposition(|m| m == &mount) {
                mounts.remove(pos);
            }
        }
    }

    /// Remove all matching items from the list of mount actions.
    pub fn rem_bind_mount(&mut self, mount: BindMount) {
        if let Some(ref mut mounts) = self.bind_mounts {
            mounts.retain(|m| m != &mount);
        }
    }

    /// Extract the bind mount list.
    pub fn collect_bind_mounts(&mut self) -> Option<Vec<BindMount>> {
        std::mem::take(&mut self.bind_mounts)
    }

    /// Return true if there're any bind mounts defined.
    pub fn has_bind_mounts(&self) -> bool {
        !self
            .bind_mounts
            .as_ref()
            .is_none_or(|bind_mounts| bind_mounts.is_empty())
    }

    /// Check the path against the Integrity Force map.
    pub fn check_force(&self, path: &XPath) -> Result<Action, IntegrityError> {
        if let Some((action, key)) = self.force_map.get(path) {
            let func = match HashAlgorithm::try_from(key.len()) {
                Ok(func) => func,
                _ => unreachable!("Hash with undefined length in Integrity Force map!"),
            };
            // SAFETY: Use safe open to avoid TOCTOU!
            let file = match safe_open(AT_FDCWD, path, OFlag::O_RDONLY, ResolveFlag::empty()) {
                Ok(fd) => BufReader::new(File::from(fd)),
                Err(errno) => return Err(IntegrityError::Sys(errno)),
            };
            let hash = crate::hash::hash(file, func)?;
            // Compare hash against saved hash.
            // SAFETY: Compare in constant time!
            return if hash.ct_eq(key).into() {
                Ok(Action::Allow)
            } else {
                Err(IntegrityError::Hash {
                    action: *action,
                    expected: HEXLOWER.encode(key),
                    found: HEXLOWER.encode(&hash),
                })
            };
        }
        Ok(self.default_action(Capability::CAP_FORCE))
    }

    /// Check the path against the Integrity Force map using the given File.
    pub fn check_force2<R: Read>(
        &self,
        path: &XPath,
        mut reader: R,
    ) -> Result<Action, IntegrityError> {
        if let Some((action, key)) = self.force_map.get(path) {
            let func = match HashAlgorithm::try_from(key.len()) {
                Ok(func) => func,
                _ => unreachable!("Hash with undefined length in Integrity Force map!"),
            };
            let hash = crate::hash::hash(&mut reader, func)?;
            // Compare hash against saved hash.
            // SAFETY: Compare in constant time!
            return if hash.ct_eq(key).into() {
                Ok(Action::Allow)
            } else {
                Err(IntegrityError::Hash {
                    action: *action,
                    expected: HEXLOWER.encode(key),
                    found: HEXLOWER.encode(&hash),
                })
            };
        }
        Ok(self.default_action(Capability::CAP_FORCE))
    }

    /// Returns the AF_ALG encryption & authentication setup socket FDs.
    pub(crate) fn crypt_setup(&self) -> Result<(RawFd, RawFd), Errno> {
        match &self.crypt_id {
            Some(Secret::Alg(aes_fd, mac_fd)) => Ok((*aes_fd, *mac_fd)),
            _ => Err(Errno::ENOKEY),
        }
    }

    /// Panic if the sandbox state allows it.
    pub fn panic(&self) -> Result<(), Errno> {
        // SAFETY: Skip if Crypt Sandboxing is on.
        // TODO: Wait for syd_aes threads to exit before panicking!
        if self.enabled(Capability::CAP_CRYPT) {
            return Err(Errno::EBUSY);
        }
        std::process::exit(127)
    }

    /// Reset the sandbox to its default state, keeping the child pid information intact.
    pub fn reset(&mut self) -> Result<(), Errno> {
        // SAFETY: We must preserve the state of the Sandbox lock!
        // SAFETY: We must preserve child pid{,fd} or lock:exec can be
        // bypassed!
        // SAFETY: We do not reset the state of Crypt sandboxing to ensure
        // ongoing encryption threads are correctly waited for on Syd exit.
        let crypt = self.enabled(Capability::CAP_CRYPT);
        let crypt_id = self.crypt_id.take();

        *self = Self {
            cpid: self.cpid,
            fpid: self.fpid,
            lock: self.lock,
            crypt_id,
            ..Self::default()
        };

        if crypt {
            self.state.insert(Capability::CAP_CRYPT);
        }

        // ATM, this function can never fail but we leave the Result
        // return as a possible extension for the future.
        Ok(())
    }

    /// Set namespace flags.
    fn set_nsflags(&mut self, value: &str) -> Result<(), Errno> {
        // Parse namespace flags.
        let nsflags = Flags::ns_from_str(value, true)?;

        // Reset flags for predictability.
        self.flags.remove(
            Flags::FL_ALLOW_UNSAFE_UNSHARE_MOUNT
                | Flags::FL_ALLOW_UNSAFE_UNSHARE_UTS
                | Flags::FL_ALLOW_UNSAFE_UNSHARE_IPC
                | Flags::FL_ALLOW_UNSAFE_UNSHARE_USER
                | Flags::FL_ALLOW_UNSAFE_UNSHARE_PID
                | Flags::FL_ALLOW_UNSAFE_UNSHARE_NET
                | Flags::FL_ALLOW_UNSAFE_UNSHARE_CGROUP
                | Flags::FL_ALLOW_UNSAFE_UNSHARE_TIME,
        );

        self.flags.insert(nsflags);

        Ok(())
    }

    /// Set or remove sandbox flag.
    fn set_flag(&mut self, flag: Flags, state: &str) -> Result<(), Errno> {
        // Check for empty/invalid flags.
        if flag.iter().count() != 1 {
            return Err(Errno::EINVAL);
        }
        // Reject flags that must only be set at startup.
        if self.is_running() && flag.is_startup() {
            return Err(Errno::EBUSY);
        }

        // Expand environment variables as necessary.
        let state = self.expand_env(state)?;

        if strbool(&state)? {
            self.flags.insert(flag);
        } else {
            self.flags.remove(flag);
        }

        Ok(())
    }

    /// Returns a new sandbox in default state.
    pub fn new() -> Self {
        Sandbox::default()
    }
}

// Note to self: To renumber the tests, do
// :let i=1 | g/sandbox_config_rules_\zs\d\+/s//\=i/ | let i+=1
// in VIM.
#[cfg(test)]
mod tests {
    use nix::unistd::Group;

    use super::*;
    use crate::err::SydResult as TestResult;

    fn get_nogroup() -> Result<(Gid, String), Errno> {
        // nogroup may be GID 65533 or 65534 depending on system.
        // nogroup may not even exist such as on Fedora (in which case nobody exists).
        // E.g. on Alpine it's 65533 meanwhile on Ubuntu it's 65534.
        let name = "nogroup".to_string();
        if let Ok(Some(group)) = Group::from_name(&name) {
            return Ok((group.gid, name));
        }

        let name = "nobody".to_string();
        if let Ok(Some(group)) = Group::from_name(&name) {
            return Ok((group.gid, name));
        }

        Err(Errno::ENOENT)
    }

    #[test]
    fn sandbox_config_api() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("")?;
        sandbox.config("3")?;
        assert!(sandbox.config("2").is_err(), "{sandbox}");
        assert!(sandbox.config("1").is_err(), "{sandbox}");
        assert!(sandbox.config("0").is_err(), "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_walk() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.state.contains(Capability::CAP_WALK));
        assert!(sandbox.config("sandbox/walk?").is_err());
        sandbox.config("sandbox/walk:on")?;
        assert!(sandbox.state.contains(Capability::CAP_WALK));
        assert!(sandbox.config("sandbox/walk?").is_ok());
        sandbox.config("sandbox/walk:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_WALK));
        assert!(sandbox.config("sandbox/walk?").is_err());

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_stat() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.state.contains(Capability::CAP_STAT));
        assert!(sandbox.config("sandbox/stat?").is_err());
        sandbox.config("sandbox/stat:on")?;
        assert!(sandbox.state.contains(Capability::CAP_STAT));
        assert!(sandbox.config("sandbox/stat?").is_ok());
        sandbox.config("sandbox/stat:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_STAT));
        assert!(sandbox.config("sandbox/stat?").is_err());

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_read() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_READ));
        assert!(sandbox.config("sandbox/read?").is_ok());
        sandbox.config("sandbox/read:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_READ));
        assert!(sandbox.config("sandbox/read?").is_err());
        sandbox.config("sandbox/read:on")?;
        assert!(sandbox.state.contains(Capability::CAP_READ));
        assert!(sandbox.config("sandbox/read?").is_ok());

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_write() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_WRITE));
        assert!(sandbox.config("sandbox/write?").is_ok());
        sandbox.config("sandbox/write:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_WRITE));
        assert!(sandbox.config("sandbox/write?").is_err());
        sandbox.config("sandbox/write:on")?;
        assert!(sandbox.state.contains(Capability::CAP_WRITE));
        assert!(sandbox.config("sandbox/write?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_exec() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_EXEC));
        assert!(sandbox.config("sandbox/exec?").is_ok());
        sandbox.config("sandbox/exec:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_EXEC));
        assert!(sandbox.config("sandbox/exec?").is_err());
        sandbox.config("sandbox/exec:on")?;
        assert!(sandbox.state.contains(Capability::CAP_EXEC));
        assert!(sandbox.config("sandbox/exec?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_ioctl() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_IOCTL));
        assert!(sandbox.config("sandbox/ioctl?").is_ok());
        sandbox.config("sandbox/ioctl:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_IOCTL));
        assert!(sandbox.config("sandbox/ioctl?").is_err());
        sandbox.config("sandbox/ioctl:on")?;
        assert!(sandbox.state.contains(Capability::CAP_IOCTL));
        assert!(sandbox.config("sandbox/ioctl?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_create() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_CREATE));
        assert!(sandbox.config("sandbox/create?").is_ok());
        sandbox.config("sandbox/create:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_CREATE));
        assert!(sandbox.config("sandbox/create?").is_err());
        sandbox.config("sandbox/create:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CREATE));
        assert!(sandbox.config("sandbox/create?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_delete() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_DELETE));
        assert!(sandbox.config("sandbox/delete?").is_ok());
        sandbox.config("sandbox/delete:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_DELETE));
        assert!(sandbox.config("sandbox/delete?").is_err());
        sandbox.config("sandbox/delete:on")?;
        assert!(sandbox.state.contains(Capability::CAP_DELETE));
        assert!(sandbox.config("sandbox/delete?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_rename() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_RENAME));
        assert!(sandbox.config("sandbox/rename?").is_ok());
        sandbox.config("sandbox/rename:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_RENAME));
        assert!(sandbox.config("sandbox/rename?").is_err());
        sandbox.config("sandbox/rename:on")?;
        assert!(sandbox.state.contains(Capability::CAP_RENAME));
        assert!(sandbox.config("sandbox/rename?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_symlink() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_SYMLINK));
        assert!(sandbox.config("sandbox/symlink?").is_ok());
        sandbox.config("sandbox/symlink:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_SYMLINK));
        assert!(sandbox.config("sandbox/symlink?").is_err());
        sandbox.config("sandbox/symlink:on")?;
        assert!(sandbox.state.contains(Capability::CAP_SYMLINK));
        assert!(sandbox.config("sandbox/symlink?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_truncate() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_TRUNCATE));
        assert!(sandbox.config("sandbox/truncate?").is_ok());
        sandbox.config("sandbox/truncate:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_TRUNCATE));
        assert!(sandbox.config("sandbox/truncate?").is_err());
        sandbox.config("sandbox/truncate:on")?;
        assert!(sandbox.state.contains(Capability::CAP_TRUNCATE));
        assert!(sandbox.config("sandbox/truncate?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_chdir() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.state.contains(Capability::CAP_CHDIR));
        assert!(sandbox.config("sandbox/chdir?").is_err());
        sandbox.config("sandbox/chdir:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CHDIR));
        assert!(sandbox.config("sandbox/chdir?").is_ok());
        sandbox.config("sandbox/chdir:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_CHDIR));
        assert!(sandbox.config("sandbox/chdir?").is_err());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_readdir() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_READDIR));
        assert!(sandbox.config("sandbox/readdir?").is_ok());
        sandbox.config("sandbox/readdir:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_READDIR));
        assert!(sandbox.config("sandbox/readdir?").is_err());
        sandbox.config("sandbox/readdir:on")?;
        assert!(sandbox.state.contains(Capability::CAP_READDIR));
        assert!(sandbox.config("sandbox/readdir?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_mkdir() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_MKDIR));
        assert!(sandbox.config("sandbox/mkdir?").is_ok());
        sandbox.config("sandbox/mkdir:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_MKDIR));
        assert!(sandbox.config("sandbox/mkdir?").is_err());
        sandbox.config("sandbox/mkdir:on")?;
        assert!(sandbox.state.contains(Capability::CAP_MKDIR));
        assert!(sandbox.config("sandbox/mkdir?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_rmdir() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_RMDIR));
        assert!(sandbox.config("sandbox/rmdir?").is_ok());
        sandbox.config("sandbox/rmdir:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_RMDIR));
        assert!(sandbox.config("sandbox/rmdir?").is_err());
        sandbox.config("sandbox/rmdir:on")?;
        assert!(sandbox.state.contains(Capability::CAP_RMDIR));
        assert!(sandbox.config("sandbox/rmdir?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_chown() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_CHOWN));
        assert!(sandbox.config("sandbox/chown?").is_ok());
        sandbox.config("sandbox/chown:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_CHOWN));
        assert!(sandbox.config("sandbox/chown?").is_err());
        sandbox.config("sandbox/chown:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CHOWN));
        assert!(sandbox.config("sandbox/chown?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_chgrp() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_CHGRP));
        assert!(sandbox.config("sandbox/chgrp?").is_ok());
        sandbox.config("sandbox/chgrp:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_CHGRP));
        assert!(sandbox.config("sandbox/chgrp?").is_err());
        sandbox.config("sandbox/chgrp:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CHGRP));
        assert!(sandbox.config("sandbox/chgrp?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_chattr() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_CHATTR));
        assert!(sandbox.config("sandbox/chattr?").is_ok());
        sandbox.config("sandbox/chattr:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_CHATTR));
        assert!(sandbox.config("sandbox/chattr?").is_err());
        sandbox.config("sandbox/chattr:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CHATTR));
        assert!(sandbox.config("sandbox/chattr?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_chroot() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_CHROOT));
        assert!(sandbox.config("sandbox/chroot?").is_ok());
        sandbox.config("sandbox/chroot:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_CHROOT));
        assert!(sandbox.config("sandbox/chroot?").is_err());
        sandbox.config("sandbox/chroot:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CHROOT));
        assert!(sandbox.config("sandbox/chroot?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_utime() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_UTIME));
        assert!(sandbox.config("sandbox/utime?").is_ok());
        sandbox.config("sandbox/utime:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_UTIME));
        assert!(sandbox.config("sandbox/utime?").is_err());
        sandbox.config("sandbox/utime:on")?;
        assert!(sandbox.state.contains(Capability::CAP_UTIME));
        assert!(sandbox.config("sandbox/utime?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_mkbdev() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_MKBDEV));
        assert!(sandbox.config("sandbox/mkbdev?").is_ok());
        sandbox.config("sandbox/mkbdev:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_MKBDEV));
        assert!(sandbox.config("sandbox/mkbdev?").is_err());
        sandbox.config("sandbox/mkbdev:on")?;
        assert!(sandbox.state.contains(Capability::CAP_MKBDEV));
        assert!(sandbox.config("sandbox/mkbdev?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_mkcdev() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_MKCDEV));
        assert!(sandbox.config("sandbox/mkcdev?").is_ok());
        sandbox.config("sandbox/mkcdev:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_MKCDEV));
        assert!(sandbox.config("sandbox/mkcdev?").is_err());
        sandbox.config("sandbox/mkcdev:on")?;
        assert!(sandbox.state.contains(Capability::CAP_MKBDEV));
        assert!(sandbox.config("sandbox/mkcdev?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_mkfifo() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_MKFIFO));
        assert!(sandbox.config("sandbox/mkfifo?").is_ok());
        sandbox.config("sandbox/mkfifo:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_MKFIFO));
        assert!(sandbox.config("sandbox/mkfifo?").is_err());
        sandbox.config("sandbox/mkfifo:on")?;
        assert!(sandbox.state.contains(Capability::CAP_MKFIFO));
        assert!(sandbox.config("sandbox/mkfifo?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_mktemp() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_MKTEMP));
        assert!(sandbox.config("sandbox/mktemp?").is_ok());
        sandbox.config("sandbox/mktemp:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_MKTEMP));
        assert!(sandbox.config("sandbox/mktemp?").is_err());
        sandbox.config("sandbox/mktemp:on")?;
        assert!(sandbox.state.contains(Capability::CAP_MKTEMP));
        assert!(sandbox.config("sandbox/mktemp?").is_ok());
        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_proxy() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.state.contains(Capability::CAP_PROXY));
        assert!(sandbox.config("sandbox/proxy?").is_err());

        sandbox.config("sandbox/proxy:on")?;
        assert!(sandbox.state.contains(Capability::CAP_PROXY));
        assert!(sandbox.config("sandbox/proxy?").is_ok());

        sandbox.config("sandbox/proxy:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_PROXY));
        assert!(sandbox.config("sandbox/proxy?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("sandbox/proxy:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("sandbox/proxy:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_fs() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_FS));
        assert!(sandbox.config("sandbox/fs?").is_ok());

        sandbox.config("sandbox/fs:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_FS));
        assert!(sandbox.config("sandbox/fs?").is_err());

        sandbox.config("sandbox/fs:on")?;
        assert!(sandbox.state.contains(Capability::CAP_FS));
        assert!(sandbox.config("sandbox/fs?").is_ok());

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_pty() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_PTY));
        assert!(sandbox.config("sandbox/pty?").is_ok());

        sandbox.config("sandbox/pty:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_PTY));
        assert!(sandbox.config("sandbox/pty?").is_err());

        sandbox.config("sandbox/pty:on")?;
        assert!(sandbox.state.contains(Capability::CAP_PTY));
        assert!(sandbox.config("sandbox/pty?").is_ok());

        sandbox.oci = true;
        assert_eq!(sandbox.config("sandbox/pty:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("sandbox/pty:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_crypt() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.state.contains(Capability::CAP_CRYPT));
        assert_eq!(sandbox.config("sandbox/crypt?"), Err(Errno::ENOENT));
        assert_eq!(sandbox.config("sandbox/crypt:on"), Ok(()));
        assert_eq!(sandbox.config("sandbox/crypt:off"), Ok(()));

        sandbox.config("sandbox/crypt:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CRYPT));
        assert!(sandbox.config("sandbox/crypt?").is_ok());
        sandbox.config("sandbox/crypt:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_CRYPT));
        assert!(sandbox.config("sandbox/crypt?").is_err());

        sandbox.config("sandbox/crypt:on")?;
        assert!(sandbox.state.contains(Capability::CAP_CRYPT));
        assert!(sandbox.config("sandbox/crypt?").is_ok());

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_network() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(sandbox.state.contains(Capability::CAP_NET_SENDFD));
        assert!(sandbox.config("sandbox/net?").is_ok());
        sandbox.config("sandbox/net:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(!sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(!sandbox.state.contains(Capability::CAP_NET_SENDFD));
        assert!(sandbox.config("sandbox/net?").is_err());
        sandbox.config("sandbox/net:on")?;
        assert!(sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(sandbox.state.contains(Capability::CAP_NET_SENDFD));
        assert!(sandbox.config("sandbox/net?").is_ok());

        sandbox.config("sandbox/net:off")?;
        sandbox.config("sandbox/net/bind:on")?;
        assert!(sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(!sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(!sandbox.state.contains(Capability::CAP_NET_SENDFD));
        assert!(sandbox.config("sandbox/net?").is_err());
        assert!(sandbox.config("sandbox/net/bind?").is_ok());
        assert!(sandbox.config("sandbox/net/connect?").is_err());
        assert!(sandbox.config("sandbox/net/sendfd?").is_err());
        sandbox.config("sandbox/net/bind:off")?;
        assert!(sandbox.config("sandbox/net?").is_err());
        assert!(sandbox.config("sandbox/net/bind?").is_err());
        assert!(sandbox.config("sandbox/net/connect?").is_err());
        assert!(sandbox.config("sandbox/net/sendfd?").is_err());

        sandbox.config("sandbox/net:off")?;
        sandbox.config("sandbox/net/connect:on")?;
        assert!(!sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(!sandbox.state.contains(Capability::CAP_NET_SENDFD));
        assert!(sandbox.config("sandbox/net?").is_err());
        assert!(sandbox.config("sandbox/net/bind?").is_err());
        assert!(sandbox.config("sandbox/net/connect?").is_ok());
        assert!(sandbox.config("sandbox/net/sendfd?").is_err());
        sandbox.config("sandbox/net/connect:off")?;
        assert!(sandbox.config("sandbox/net?").is_err());
        assert!(sandbox.config("sandbox/net/bind?").is_err());
        assert!(sandbox.config("sandbox/net/connect?").is_err());
        assert!(sandbox.config("sandbox/net/sendfd?").is_err());

        sandbox.config("sandbox/net:off")?;
        sandbox.config("sandbox/net/sendfd:on")?;
        assert!(!sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(!sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(sandbox.state.contains(Capability::CAP_NET_SENDFD));
        assert!(sandbox.config("sandbox/net?").is_err());
        assert!(sandbox.config("sandbox/net/bind?").is_err());
        assert!(sandbox.config("sandbox/net/connect?").is_err());
        assert!(sandbox.config("sandbox/net/sendfd?").is_ok());
        sandbox.config("sandbox/net/sendfd:off")?;
        assert!(sandbox.config("sandbox/net?").is_err());
        assert!(sandbox.config("sandbox/net/bind?").is_err());
        assert!(sandbox.config("sandbox/net/connect?").is_err());
        assert!(sandbox.config("sandbox/net/sendfd?").is_err());

        Ok(())
    }

    #[test]
    fn sandbox_config_sandbox_many() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.state = Sealable::new(Capability::empty());
        sandbox.config("sandbox/read,stat,walk:on")?;
        sandbox.config("sandbox/read,write,lock:off")?;
        sandbox.config("sandbox/lock,pid,mem,force,proxy,pty,ioctl:on")?;
        sandbox.config("sandbox/force,fs,mem,tpe,proxy,pty:off")?;
        sandbox.config("sandbox/net,exec:on")?;
        sandbox.config("sandbox/net/bind,net/sendfd:off")?;
        assert!(sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(sandbox.state.contains(Capability::CAP_EXEC));
        assert!(sandbox.state.contains(Capability::CAP_IOCTL));
        assert!(sandbox.state.contains(Capability::CAP_LOCK));
        assert!(sandbox.state.contains(Capability::CAP_PID));
        assert!(sandbox.state.contains(Capability::CAP_STAT));
        assert!(sandbox.state.contains(Capability::CAP_WALK));
        assert!(!sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(!sandbox.state.contains(Capability::CAP_NET_SENDFD));
        assert!(!sandbox.state.contains(Capability::CAP_FORCE));
        assert!(!sandbox.state.contains(Capability::CAP_FS));
        assert!(!sandbox.state.contains(Capability::CAP_TPE));
        assert!(!sandbox.state.contains(Capability::CAP_PROXY));
        assert!(!sandbox.state.contains(Capability::CAP_PTY));
        assert!(!sandbox.state.contains(Capability::CAP_MEM));
        assert!(!sandbox.state.contains(Capability::CAP_READ));
        assert!(!sandbox.state.contains(Capability::CAP_WRITE));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_mount() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_MOUNT));
        assert!(sandbox.config("unshare/mount?").is_err());
        sandbox.config("unshare/mount:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_MOUNT));
        assert!(sandbox.config("unshare/mount?").is_ok());
        sandbox.config("unshare/mount:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_MOUNT));
        assert!(sandbox.config("unshare/mount?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/mount:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/mount:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_uts() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_UTS));
        assert!(sandbox.config("unshare/uts?").is_err());
        sandbox.config("unshare/uts:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_UTS));
        assert!(sandbox.config("unshare/uts?").is_ok());
        sandbox.config("unshare/uts:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_UTS));
        assert!(sandbox.config("unshare/uts?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/uts:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/uts:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_ipc() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_IPC));
        assert!(sandbox.config("unshare/ipc?").is_err());
        sandbox.config("unshare/ipc:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_IPC));
        assert!(sandbox.config("unshare/ipc?").is_ok());
        sandbox.config("unshare/ipc:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_IPC));
        assert!(sandbox.config("unshare/ipc?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/ipc:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/ipc:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_user() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_USER));
        assert!(sandbox.config("unshare/user?").is_err());
        sandbox.config("unshare/user:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_USER));
        assert!(sandbox.config("unshare/user?").is_ok());
        sandbox.config("unshare/user:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_USER));
        assert!(sandbox.config("unshare/user?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/user:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/user:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_pid() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_PID));
        assert!(sandbox.config("unshare/pid?").is_err());
        sandbox.config("unshare/pid:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_PID));
        assert!(sandbox.config("unshare/pid?").is_ok());
        sandbox.config("unshare/pid:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_PID));
        assert!(sandbox.config("unshare/pid?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/pid:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/pid:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_net() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_NET));
        assert!(sandbox.config("unshare/net?").is_err());
        sandbox.config("unshare/net:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_NET));
        assert!(sandbox.config("unshare/net?").is_ok());
        sandbox.config("unshare/net:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_NET));
        assert!(sandbox.config("unshare/net?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/net:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/net:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_cgroup() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_CGROUP));
        assert!(sandbox.config("unshare/cgroup?").is_err());
        sandbox.config("unshare/cgroup:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_CGROUP));
        assert!(sandbox.config("unshare/cgroup?").is_ok());
        sandbox.config("unshare/cgroup:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_CGROUP));
        assert!(sandbox.config("unshare/cgroup?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/cgroup:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/cgroup:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_time() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_TIME));
        assert!(sandbox.config("unshare/time?").is_err());
        sandbox.config("unshare/time:on")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_TIME));
        assert!(sandbox.config("unshare/time?").is_ok());
        sandbox.config("unshare/time:off")?;
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_TIME));
        assert!(sandbox.config("unshare/time?").is_err());

        sandbox.oci = true;
        assert_eq!(sandbox.config("unshare/time:on"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("unshare/time:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_many() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.flags = Sealable::new(Flags::empty());
        sandbox.config("unshare/mount,uts:on")?;
        sandbox.config("unshare/mount,uts,ipc:off")?;
        sandbox.config("unshare/mount,uts,ipc,user:on")?;
        sandbox.config("unshare/user,pid:off")?;
        sandbox.config("unshare/net,cgroup:on")?;
        sandbox.config("unshare/cgroup:off")?;
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_MOUNT));
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_UTS));
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_IPC));
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_USER));
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_PID));
        assert!(sandbox.flags.contains(Flags::FL_UNSHARE_NET));
        assert!(!sandbox.flags.contains(Flags::FL_UNSHARE_CGROUP));

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_1() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.lock, None);

        sandbox.config("lock:off")?;
        assert_eq!(sandbox.lock, Some(LockState::Off));

        sandbox.config("lock:exec")?;
        assert_eq!(sandbox.lock, Some(LockState::Exec));

        sandbox.config("lock:ipc")?;
        assert_eq!(sandbox.lock, Some(LockState::Ipc));

        sandbox.oci = true;
        assert_eq!(sandbox.config("lock:ipc"), Err(Errno::EOPNOTSUPP));
        sandbox.oci = false;

        sandbox.config("lock:on")?;
        assert_eq!(sandbox.lock, Some(LockState::Set));

        // Lock cannot be altered once locked.
        for state in ["off", "exec", "ipc", "read"] {
            assert_eq!(
                sandbox.config(&format!("lock:{state}")),
                Err(Errno::EBUSY),
                "OOPS:{state}"
            );
        }

        // lock:on is a no-op when locked.
        sandbox.config("lock:on")?;
        assert_eq!(sandbox.lock, Some(LockState::Set));

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_2() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.lock, None);

        sandbox.config("lock:off")?;
        assert_eq!(sandbox.lock, Some(LockState::Off));

        sandbox.config("lock:exec")?;
        assert_eq!(sandbox.lock, Some(LockState::Exec));

        sandbox.config("lock:ipc")?;
        assert_eq!(sandbox.lock, Some(LockState::Ipc));

        sandbox.oci = true;
        assert_eq!(sandbox.config("lock:ipc"), Err(Errno::EOPNOTSUPP));
        sandbox.oci = false;

        sandbox.config("lock:read")?;
        assert_eq!(sandbox.lock, Some(LockState::Read));

        // Lock cannot be altered once locked.
        for state in ["off", "exec", "ipc", "on"] {
            assert_eq!(
                sandbox.config(&format!("lock:{state}")),
                Err(Errno::EBUSY),
                "OOPS:{state}"
            );
        }

        // lock:read is a no-op when read-locked.
        sandbox.config("lock:read")?;
        assert_eq!(sandbox.lock, Some(LockState::Read));

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_01() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert!(sandbox.collect_landlock().is_none());
        sandbox.config("sandbox/lock:on")?;
        let policy = sandbox.collect_landlock().unwrap();

        assert!(policy.scoped_abs);
        assert!(policy.scoped_sig);
        assert!(policy.read_pathset.is_some());
        assert!(policy.readdir_pathset.is_some());
        assert!(policy.write_pathset.is_some());
        assert!(policy.truncate_pathset.is_some());
        assert!(policy.exec_pathset.is_none());
        assert!(policy.ioctl_pathset.is_none());
        assert!(policy.create_pathset.is_none());
        assert!(policy.delete_pathset.is_none());
        assert!(policy.rename_pathset.is_none());
        assert!(policy.symlink_pathset.is_none());
        assert!(policy.mkdir_pathset.is_none());
        assert!(policy.rmdir_pathset.is_none());
        assert!(policy.mkbdev_pathset.is_none());
        assert!(policy.mkcdev_pathset.is_none());
        assert!(policy.mkfifo_pathset.is_none());
        assert!(policy.bind_pathset.is_none());
        assert!(policy.bind_portset.is_none());
        assert!(policy.conn_portset.is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_02() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.config("sandbox/lock:on")?;
        let policy = sandbox.collect_landlock().unwrap();

        assert_eq!(
            policy.read_pathset.as_ref().map(|s| s.len()).unwrap_or(0),
            2
        );
        assert_eq!(
            policy
                .readdir_pathset
                .as_ref()
                .map(|s| s.len())
                .unwrap_or(0),
            1
        );
        assert_eq!(
            policy.write_pathset.as_ref().map(|s| s.len()).unwrap_or(0),
            1
        );
        assert!(policy
            .read_pathset
            .as_ref()
            .map(|s| s.contains(XPath::from_bytes(b"/proc")))
            .unwrap_or(false));
        assert!(policy
            .readdir_pathset
            .as_ref()
            .map(|s| s.contains(XPath::from_bytes(b"/proc")))
            .unwrap_or(false));
        assert!(policy
            .read_pathset
            .as_ref()
            .map(|s| s.contains(XPath::from_bytes(b"/dev/null")))
            .unwrap_or(false));
        assert!(policy
            .write_pathset
            .as_ref()
            .map(|s| s.contains(XPath::from_bytes(b"/dev/null")))
            .unwrap_or(false));
        assert!(policy
            .truncate_pathset
            .as_ref()
            .map(|s| s.contains(XPath::from_bytes(b"/dev/null")))
            .unwrap_or(false));
        assert!(policy.exec_pathset.is_none());
        assert!(policy.ioctl_pathset.is_none());
        assert!(policy.create_pathset.is_none());
        assert!(policy.delete_pathset.is_none());
        assert!(policy.rename_pathset.is_none());
        assert!(policy.symlink_pathset.is_none());
        assert!(policy.mkdir_pathset.is_none());
        assert!(policy.rmdir_pathset.is_none());
        assert!(policy.mkbdev_pathset.is_none());
        assert!(policy.mkcdev_pathset.is_none());
        assert!(policy.mkfifo_pathset.is_none());
        assert!(policy.bind_pathset.is_none());
        assert!(policy.bind_portset.is_none());
        assert!(policy.conn_portset.is_none());

        sandbox.config("sandbox/lock:off")?;
        assert!(sandbox.collect_landlock().is_none());

        sandbox.config("sandbox/lock:on")?;
        assert!(sandbox.collect_landlock().is_some());

        sandbox.config("sandbox/lock:off")?;
        assert!(sandbox.collect_landlock().is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_03() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("allow/lock/read+/dev/null"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/read+/dev/null/"), Ok(()));
        assert_eq!(
            sandbox.config("allow/lock/read-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read^/dev/null"),
            Err(Errno::EACCES)
        );

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_04() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("allow/lock/write+/dev/null"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/write+/dev/null/"), Ok(()));
        assert_eq!(
            sandbox.config("allow/lock/write-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/write^/dev/null"),
            Err(Errno::EACCES)
        );

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_05() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("allow/lock/truncate+/dev/null"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/truncate+/dev/null/"), Ok(()));
        assert_eq!(
            sandbox.config("allow/lock/truncate-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/truncate^/dev/null"),
            Err(Errno::EACCES)
        );

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_06() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("allow/lock/read+/proc"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/read+/proc/1"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/readdir+/proc"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/readdir+/proc/1"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/read-/proc"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("allow/lock/read^/proc"), Err(Errno::EACCES));
        assert_eq!(
            sandbox.config("allow/lock/readdir-/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/readdir^/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(sandbox.config("allow/lock/write+/proc"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/write-/proc"), Ok(()));
        assert_eq!(sandbox.config("allow/lock/write^/proc"), Ok(()));

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_07() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        // Defaults for /dev/null are read, write and truncate.
        assert_eq!(
            sandbox.config("allow/lock/read-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/write-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/truncate-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read^/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/write^/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/truncate^/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read,write-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/write,truncate-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read,write^/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/write,truncate^/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/spath,tpath,read-/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/spath,tpath,read^/dev/null"),
            Err(Errno::EACCES)
        );

        // Defaults for /proc are read and readdir.
        assert_eq!(sandbox.config("allow/lock/read-/proc"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("allow/lock/read-/proc"), Err(Errno::EACCES));
        assert_eq!(
            sandbox.config("allow/lock/readdir-/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read,readdir-/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read,write-/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/exec,write,readdir-/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read^/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(sandbox.config("allow/lock/read^/proc"), Err(Errno::EACCES));
        assert_eq!(
            sandbox.config("allow/lock/readdir^/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read,readdir^/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/read,write^/proc"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/exec,write,readdir^/proc"),
            Err(Errno::EACCES)
        );

        assert_eq!(sandbox.config("allow/lock/read+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/read-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/read^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/readdir+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/readdir-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/readdir^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/write+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/write-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/write^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/exec+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/exec-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/exec^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/ioctl+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/ioctl-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/ioctl^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/create+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/create-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/create^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/delete+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/delete-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/delete^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/rename+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/rename-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/rename^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/symlink+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/symlink-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/symlink^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/truncate+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/truncate-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/truncate^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/mkdir+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkdir-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkdir^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/rmdir+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/rmdir-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/rmdir^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/mkbdev+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkbdev-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkbdev^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/mkcdev+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkcdev-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkcdev^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/mkfifo+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkfifo-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/mkfifo^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/bind+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind^"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("allow/lock/connect+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect^"), Err(Errno::EINVAL));

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_08() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        // Defaults for read are /proc and /dev/null.
        assert!(sandbox.config("allow/lock/read+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/read-/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .read_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        assert!(sandbox.config("allow/lock/read+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/read+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/read+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .read_pathset
                .as_ref()
                .unwrap()
                .len(),
            3
        );

        assert!(sandbox.config("allow/lock/read^/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .read_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        // Defaults for readdir is /proc.
        assert!(sandbox.config("allow/lock/readdir+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .readdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );
        assert!(sandbox.config("allow/lock/readdir-/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .readdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/readdir+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/readdir+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/readdir+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .readdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        assert!(sandbox.config("allow/lock/readdir^/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .readdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        // Default for write is /dev/null.
        assert!(sandbox.config("allow/lock/write+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .write_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        assert!(sandbox.config("allow/lock/write-/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .write_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/write+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/write+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/write+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .write_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        assert!(sandbox.config("allow/lock/write^/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .write_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        // Default for truncate is /dev/null.
        assert!(sandbox.config("allow/lock/truncate+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .truncate_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        assert!(sandbox.config("allow/lock/truncate-/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .truncate_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/truncate+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/truncate+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/truncate+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .truncate_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        assert!(sandbox.config("allow/lock/truncate^/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .truncate_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/exec+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .exec_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/exec-/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().exec_pathset.is_none());

        assert!(sandbox.config("allow/lock/exec+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/exec+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/exec+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .exec_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/exec^/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().exec_pathset.is_none());

        assert!(sandbox.config("allow/lock/ioctl+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .ioctl_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/ioctl-/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().ioctl_pathset.is_none());

        assert!(sandbox.config("allow/lock/ioctl+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/ioctl+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/ioctl+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .ioctl_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/ioctl^/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().ioctl_pathset.is_none());

        assert!(sandbox.config("allow/lock/create+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .create_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/create-/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .create_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/create+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/create+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/create+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .create_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/create^/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .create_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/delete+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .delete_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/delete-/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .delete_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/delete+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/delete+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/delete+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .delete_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/delete^/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .delete_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/rename+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .rename_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/rename-/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .rename_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/rename+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/rename+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/rename+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .rename_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/rename^/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .rename_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/symlink+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .symlink_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/symlink-/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .symlink_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/symlink+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/symlink+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/symlink+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .symlink_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/symlink^/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .symlink_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkdir+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkdir-/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().mkdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/mkdir+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkdir+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkdir+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkdir^/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().mkdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/rmdir+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .rmdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/rmdir-/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().rmdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/rmdir+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/rmdir+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/rmdir+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .rmdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/rmdir^/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().rmdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/mkbdev+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkbdev_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkbdev-/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkbdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkbdev+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkbdev+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkbdev+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkbdev_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkbdev^/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkbdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkcdev+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkcdev_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkcdev-/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkcdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkcdev+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkcdev+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkcdev+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkcdev_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkcdev^/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkcdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkfifo+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkfifo_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkfifo-/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkfifo_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkfifo+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkfifo+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/mkfifo+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkfifo_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/mkfifo^/abspath").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkfifo_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/bind+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .bind_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/bind-/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_pathset.is_none());

        assert!(sandbox.config("allow/lock/bind+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/bind+/abspath").is_ok());
        assert!(sandbox.config("allow/lock/bind+/abspath").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .bind_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/bind^/abspath").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_pathset.is_none());

        assert_eq!(sandbox.config("allow/lock/bind+22"), Ok(()));
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert_eq!(sandbox.config("allow/lock/bind-22"), Ok(()));
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+22").is_ok());
        assert!(sandbox.config("allow/lock/bind+22").is_ok());
        assert!(sandbox.config("allow/lock/bind+22").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind^22").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert_eq!(sandbox.config("allow/lock/connect+22"), Ok(()));
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert_eq!(sandbox.config("allow/lock/connect-22"), Ok(()));
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+22").is_ok());
        assert!(sandbox.config("allow/lock/connect+22").is_ok());
        assert!(sandbox.config("allow/lock/connect+22").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect^22").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_09() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        // Default for read is /dev/null and /proc.
        assert!(sandbox.config("allow/lock/read+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .read_pathset
                .as_ref()
                .unwrap()
                .len(),
            3
        );
        assert!(sandbox.config("allow/lock/read-foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .read_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        assert!(sandbox.config("allow/lock/read+foo").is_ok());
        assert!(sandbox.config("allow/lock/read+foo").is_ok());
        assert!(sandbox.config("allow/lock/read+foo").is_ok());
        assert!(sandbox.config("allow/lock/read^foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .read_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );

        // Default for readdir /proc.
        assert!(sandbox.config("allow/lock/readdir+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .readdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );
        assert!(sandbox.config("allow/lock/readdir-foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .readdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/readdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/readdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/readdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/readdir^foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .readdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        // Default for write is /dev/null.
        assert!(sandbox.config("allow/lock/write+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .write_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );
        assert!(sandbox.config("allow/lock/write-foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .write_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/write+foo").is_ok());
        assert!(sandbox.config("allow/lock/write+foo").is_ok());
        assert!(sandbox.config("allow/lock/write+foo").is_ok());
        assert!(sandbox.config("allow/lock/write^foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .write_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        // Default for truncate is /dev/null.
        assert!(sandbox.config("allow/lock/truncate+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .truncate_pathset
                .as_ref()
                .unwrap()
                .len(),
            2
        );
        assert!(sandbox.config("allow/lock/truncate-foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .truncate_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/truncate+foo").is_ok());
        assert!(sandbox.config("allow/lock/truncate+foo").is_ok());
        assert!(sandbox.config("allow/lock/truncate+foo").is_ok());
        assert!(sandbox.config("allow/lock/truncate^foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .truncate_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );

        assert!(sandbox.config("allow/lock/exec+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .exec_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/exec-foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().exec_pathset.is_none());

        assert!(sandbox.config("allow/lock/exec+foo").is_ok());
        assert!(sandbox.config("allow/lock/exec+foo").is_ok());
        assert!(sandbox.config("allow/lock/exec+foo").is_ok());
        assert!(sandbox.config("allow/lock/exec^foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().exec_pathset.is_none());

        assert!(sandbox.config("allow/lock/ioctl+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .ioctl_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/ioctl-foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().ioctl_pathset.is_none());

        assert!(sandbox.config("allow/lock/ioctl+foo").is_ok());
        assert!(sandbox.config("allow/lock/ioctl+foo").is_ok());
        assert!(sandbox.config("allow/lock/ioctl+foo").is_ok());
        assert!(sandbox.config("allow/lock/ioctl^foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().ioctl_pathset.is_none());

        assert!(sandbox.config("allow/lock/create+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .create_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/create-foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .create_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/create+foo").is_ok());
        assert!(sandbox.config("allow/lock/create+foo").is_ok());
        assert!(sandbox.config("allow/lock/create+foo").is_ok());
        assert!(sandbox.config("allow/lock/create^foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .create_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/delete+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .delete_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/delete-foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .delete_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/delete+foo").is_ok());
        assert!(sandbox.config("allow/lock/delete+foo").is_ok());
        assert!(sandbox.config("allow/lock/delete+foo").is_ok());
        assert!(sandbox.config("allow/lock/delete^foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .delete_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/rename+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .rename_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/rename-foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .rename_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/rename+foo").is_ok());
        assert!(sandbox.config("allow/lock/rename+foo").is_ok());
        assert!(sandbox.config("allow/lock/rename+foo").is_ok());
        assert!(sandbox.config("allow/lock/rename^foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .rename_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/symlink+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .symlink_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/symlink-foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .symlink_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/symlink+foo").is_ok());
        assert!(sandbox.config("allow/lock/symlink+foo").is_ok());
        assert!(sandbox.config("allow/lock/symlink+foo").is_ok());
        assert!(sandbox.config("allow/lock/symlink^foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .symlink_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkdir+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/mkdir-foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().mkdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/mkdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkdir^foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().mkdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/rmdir+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .rmdir_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/rmdir-foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().rmdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/rmdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/rmdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/rmdir+foo").is_ok());
        assert!(sandbox.config("allow/lock/rmdir^foo").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().rmdir_pathset.is_none());

        assert!(sandbox.config("allow/lock/mkbdev+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkbdev_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/mkbdev-foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkbdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkbdev+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkbdev+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkbdev+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkbdev^foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkbdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkcdev+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkcdev_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/mkcdev-foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkcdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkcdev+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkcdev+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkcdev+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkcdev^foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkcdev_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkfifo+foo").is_ok());
        assert_eq!(
            sandbox
                .lock_rules
                .as_ref()
                .unwrap()
                .mkfifo_pathset
                .as_ref()
                .unwrap()
                .len(),
            1
        );
        assert!(sandbox.config("allow/lock/mkfifo-foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkfifo_pathset
            .is_none());

        assert!(sandbox.config("allow/lock/mkfifo+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkfifo+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkfifo+foo").is_ok());
        assert!(sandbox.config("allow/lock/mkfifo^foo").is_ok());
        assert!(sandbox
            .lock_rules
            .as_ref()
            .unwrap()
            .mkfifo_pathset
            .is_none());

        assert_eq!(sandbox.config("allow/lock/bind+foo"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect+foo"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/bind,connect+foo"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect+/"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect+$"),
            Err(Errno::EINVAL)
        );
        assert!(sandbox.config("allow/lock/bind+/").is_ok());
        assert!(sandbox.config("allow/lock/bind+$").is_ok());

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_10() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("allow/lock/bind+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind+65542"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/bind+1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind+65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("allow/lock/bind-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind-65542"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/bind-1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind-65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("allow/lock/bind^"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind^65542"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/bind^1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind^65542-1"),
            Err(Errno::EINVAL)
        );
        assert!(sandbox.config("allow/lock/bind+0-0").is_ok());
        assert!(sandbox.config("allow/lock/bind+1-0").is_ok());
        assert!(sandbox.config("allow/lock/bind+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/bind+65535-0").is_ok());

        assert_eq!(sandbox.config("allow/lock/connect+"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/connect+65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect+1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect+65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("allow/lock/connect-"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/connect-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect-1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect-65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("allow/lock/connect^"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/connect^65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect^1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect^65542-1"),
            Err(Errno::EINVAL)
        );
        assert!(sandbox.config("allow/lock/connect+0-0").is_ok());
        assert!(sandbox.config("allow/lock/connect+1-0").is_ok());
        assert!(sandbox.config("allow/lock/connect+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/connect+65535-0").is_ok());

        assert_eq!(
            sandbox.config("allow/lock/bind,connect+"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect+65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect+1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect+65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect-"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect-1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect-65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect^"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect^65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect^1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/bind,connect^65542-1"),
            Err(Errno::EINVAL)
        );
        assert!(sandbox.config("allow/lock/bind,connect+0-0").is_ok());
        assert!(sandbox.config("allow/lock/bind,connect+1-0").is_ok());
        assert!(sandbox.config("allow/lock/bind,connect+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/bind,connect+65535-0").is_ok());

        assert_eq!(
            sandbox.config("allow/lock/connect,bind+"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind+65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind+1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind+65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind-"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind-1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind-65542-1"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind^"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind^65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind^1-65542"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("allow/lock/connect,bind^65542-1"),
            Err(Errno::EINVAL)
        );
        assert!(sandbox.config("allow/lock/connect,bind+0-0").is_ok());
        assert!(sandbox.config("allow/lock/connect,bind+1-0").is_ok());
        assert!(sandbox.config("allow/lock/connect,bind+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/connect,bind+65535-0").is_ok());

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_11() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert!(sandbox.config("allow/lock/bind+0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind-0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+0").is_ok());
        assert!(sandbox.config("allow/lock/bind+0").is_ok());
        assert!(sandbox.config("allow/lock/bind+0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind^0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind-0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/bind+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/bind+0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind^0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind-1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+1").is_ok());
        assert!(sandbox.config("allow/lock/bind+1").is_ok());
        assert!(sandbox.config("allow/lock/bind+1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind^1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind-1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/bind+1-42").is_ok());
        assert!(sandbox.config("allow/lock/bind+1-42").is_ok());
        assert!(sandbox.config("allow/lock/bind+1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_some());
        assert!(sandbox.config("allow/lock/bind^1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().bind_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect-0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+0").is_ok());
        assert!(sandbox.config("allow/lock/connect+0").is_ok());
        assert!(sandbox.config("allow/lock/connect+0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect^0").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect-0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/connect+0-65535").is_ok());
        assert!(sandbox.config("allow/lock/connect+0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect^0-65535").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect-1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+1").is_ok());
        assert!(sandbox.config("allow/lock/connect+1").is_ok());
        assert!(sandbox.config("allow/lock/connect+1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect^1").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect-1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        assert!(sandbox.config("allow/lock/connect+1-42").is_ok());
        assert!(sandbox.config("allow/lock/connect+1-42").is_ok());
        assert!(sandbox.config("allow/lock/connect+1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_some());
        assert!(sandbox.config("allow/lock/connect^1-42").is_ok());
        assert!(sandbox.lock_rules.as_ref().unwrap().conn_portset.is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_trace() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_SAFE_BIND));
        sandbox.config("trace/allow_safe_bind:true")?;
        assert!(sandbox.flags.contains(Flags::FL_ALLOW_SAFE_BIND));
        sandbox.config("trace/allow_safe_bind:false")?;
        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_SAFE_BIND));
        sandbox.config("trace/allow_safe_bind:t")?;
        assert!(sandbox.flags.contains(Flags::FL_ALLOW_SAFE_BIND));
        sandbox.config("trace/allow_safe_bind:f")?;
        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_SAFE_BIND));
        sandbox.config("trace/allow_safe_bind:1")?;
        assert!(sandbox.flags.contains(Flags::FL_ALLOW_SAFE_BIND));
        sandbox.config("trace/allow_safe_bind:0")?;
        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_SAFE_BIND));

        assert_eq!(
            sandbox.config("trace/allow_safe_bind_invalid:t"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("trace/allow_safe_bind!x"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("trace/allow_safe_bind:x"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("trace/allow_safe_bind:☮"),
            Err(Errno::EINVAL)
        );

        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_UNSUPP_SOCKET));
        sandbox.config("trace/allow_unsupp_socket:true")?;
        assert!(sandbox.flags.contains(Flags::FL_ALLOW_UNSUPP_SOCKET));
        sandbox.config("trace/allow_unsupp_socket:false")?;
        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_UNSUPP_SOCKET));
        sandbox.config("trace/allow_unsupp_socket:t")?;
        assert!(sandbox.flags.contains(Flags::FL_ALLOW_UNSUPP_SOCKET));
        sandbox.config("trace/allow_unsupp_socket:f")?;
        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_UNSUPP_SOCKET));
        sandbox.config("trace/allow_unsupp_socket:1")?;
        assert!(sandbox.flags.contains(Flags::FL_ALLOW_UNSUPP_SOCKET));
        sandbox.config("trace/allow_unsupp_socket:0")?;
        assert!(!sandbox.flags.contains(Flags::FL_ALLOW_UNSUPP_SOCKET));

        assert_eq!(
            sandbox.config("trace/allow_unsupp_socket_invalid:t"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("trace/allow_unsupp_socket!x"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("trace/allow_unsupp_socket:x"),
            Err(Errno::EINVAL)
        );
        assert_eq!(
            sandbox.config("trace/allow_unsupp_socket:☮"),
            Err(Errno::EINVAL)
        );

        assert_eq!(sandbox.config("trace/memory_access:0"), Ok(()));
        assert_eq!(sandbox.config("trace/memory_access:1"), Ok(()));
        assert_eq!(
            sandbox.config("trace/memory_access_invalid:t"),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("trace/memory_access!x"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("trace/memory_access:x"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("trace/memory_access:t"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("trace/memory_access:☮"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("trace/memory_access:f"), Err(Errno::EINVAL));

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_1() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // Invalid syntax
        assert_eq!(sandbox.config("setuid:0:65534"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setuid:0:0"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid:0:65534"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid:0:0"), Err(Errno::EINVAL));

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_2() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // ROOT not allowed in target.
        assert_eq!(sandbox.config("setuid+0:0"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid+0:0"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setuid+1:0"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("setgid+1:0"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("setuid+65534:0"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("setgid+65534:0"), Err(Errno::EACCES));

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_3() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // ID escalation is not allowed.
        assert_eq!(sandbox.config("setuid+65534:42"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("setgid+65534:42"), Err(Errno::EACCES));

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_4() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // Same ID is meaningless and is disallowed.
        assert_eq!(sandbox.config("setuid+1:1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid+1:1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setuid+65534:65534"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid+65534:65534"), Err(Errno::EINVAL));

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_5() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setuid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.config("setuid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setuid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setuid-0:65534"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_6() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setgid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, Gid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.config("setgid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setgid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setgid-0:65534"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_7() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // Adding a transition with same source but diff target fails.
        assert_eq!(sandbox.config("setuid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.config("setuid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setuid+0:65533"), Err(Errno::EEXIST));
        // Removing the transition and then re-adding with diff target is OK.
        assert_eq!(sandbox.config("setuid-0:65534"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.config("setuid+0:65533"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65533), "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_8() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // Adding a transition with same source but diff target fails.
        assert_eq!(sandbox.config("setgid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, Gid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.config("setgid+0:65534"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setgid+0:65533"), Err(Errno::EEXIST));
        // Removing the transition and then re-adding with diff target is OK.
        assert_eq!(sandbox.config("setgid-0:65534"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.config("setgid+0:65533"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, Gid::from_raw(65533), "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_9() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setuid+0:65534"), Ok(()));
        assert_eq!(sandbox.config("setuid+1:65533"), Ok(()));
        assert_eq!(sandbox.config("setuid+2:65532"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, Uid::from_raw(65533), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, Uid::from_raw(65532), "{sandbox}");
        assert_eq!(sandbox.config("setuid^"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_10() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        for gid in 0..=GID_MIN.as_raw() {
            let errno = if gid == 0 {
                Errno::EINVAL
            } else {
                Errno::EACCES
            };
            assert_eq!(sandbox.config(&format!("setgid+0:{gid}")), Err(errno));
        }

        let gid_1 = Gid::from_raw(GID_MIN.as_raw().checked_add(1).unwrap());
        let gid_2 = Gid::from_raw(GID_MIN.as_raw().checked_add(2).unwrap());
        let gid_3 = Gid::from_raw(GID_MIN.as_raw().checked_add(3).unwrap());

        assert_eq!(
            sandbox.config(&format!("setgid+0:{}", gid_1.as_raw())),
            Ok(())
        );
        assert_eq!(
            sandbox.config(&format!("setgid+1:{}", gid_2.as_raw())),
            Ok(())
        );
        assert_eq!(
            sandbox.config(&format!("setgid+2:{}", gid_3.as_raw())),
            Ok(())
        );
        assert_eq!(sandbox.transit_gids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, gid_1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, gid_2, "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, gid_3, "{sandbox}");
        assert_eq!(
            sandbox.config(&format!("setgid^0:{}", gid_1.as_raw())),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("setgid^0"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 2, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, gid_2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_11() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        for uid in 0..=UID_MIN.as_raw() {
            let errno = if uid == 0 {
                Errno::EINVAL
            } else {
                Errno::EACCES
            };
            assert_eq!(sandbox.config(&format!("setuid+0:{uid}")), Err(errno));
        }

        let uid_1 = Uid::from_raw(UID_MIN.as_raw().checked_add(1).unwrap());
        let uid_2 = Uid::from_raw(UID_MIN.as_raw().checked_add(2).unwrap());
        let uid_3 = Uid::from_raw(UID_MIN.as_raw().checked_add(3).unwrap());

        assert_eq!(
            sandbox.config(&format!("setuid+0:{}", uid_1.as_raw())),
            Ok(())
        );
        assert_eq!(
            sandbox.config(&format!("setuid+1:{}", uid_2.as_raw())),
            Ok(())
        );
        assert_eq!(
            sandbox.config(&format!("setuid+2:{}", uid_3.as_raw())),
            Ok(())
        );
        assert_eq!(sandbox.transit_uids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, uid_1, "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, uid_2, "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, uid_3, "{sandbox}");
        assert_eq!(
            sandbox.config(&format!("setuid^0:{}", uid_1.as_raw())),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("setuid^0"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 2, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, uid_2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetid_12() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        for gid in 0..=GID_MIN.as_raw() {
            let errno = if gid == 0 {
                Errno::EINVAL
            } else {
                Errno::EACCES
            };
            assert_eq!(sandbox.config(&format!("setgid+0:{gid}")), Err(errno));
        }

        let gid_1 = Gid::from_raw(GID_MIN.as_raw().checked_add(1).unwrap());
        let gid_2 = Gid::from_raw(GID_MIN.as_raw().checked_add(2).unwrap());
        let gid_3 = Gid::from_raw(GID_MIN.as_raw().checked_add(3).unwrap());

        assert_eq!(
            sandbox.config(&format!("setgid+0:{}", gid_1.as_raw())),
            Ok(())
        );
        assert_eq!(
            sandbox.config(&format!("setgid+1:{}", gid_2.as_raw())),
            Ok(())
        );
        assert_eq!(
            sandbox.config(&format!("setgid+2:{}", gid_3.as_raw())),
            Ok(())
        );
        assert_eq!(sandbox.transit_gids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, gid_1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, gid_2, "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, gid_3, "{sandbox}");
        assert_eq!(
            sandbox.config(&format!("setgid^0:{}", gid_1.as_raw())),
            Err(Errno::EINVAL)
        );
        assert_eq!(sandbox.config("setgid^0"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 2, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, gid_2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_1() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // Invalid syntax
        assert_eq!(sandbox.config("setuid:root:nobody"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setuid:root:root"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid:root:nobody"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid:root:root"), Err(Errno::EINVAL));

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_2() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // ROOT not allowed in target.
        assert_eq!(sandbox.config("setuid+root:root"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid+root:root"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setuid+nobody:root"), Err(Errno::EACCES));
        if let Ok((_, nogroup)) = get_nogroup() {
            assert_eq!(
                sandbox.config(&format!("setgid+{nogroup}:root")),
                Err(Errno::EACCES)
            );
        }

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_3() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // Same ID is meaningless and is disallowed.
        assert_eq!(sandbox.config("setuid+nobody:nobody"), Err(Errno::EINVAL));
        if let Ok((_, nogroup)) = get_nogroup() {
            assert_eq!(
                sandbox.config(&format!("setgid+{nogroup}:{nogroup}")),
                Err(Errno::EINVAL)
            );
        }

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_4() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setuid+root:nobody"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.config("setuid+root:nobody"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setuid+root:nobody"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setuid-root:nobody"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_5() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        let (nogroup_gid, nogroup) = match get_nogroup() {
            Ok((nogroup_gid, nogroup)) => (nogroup_gid, nogroup),
            Err(_) => return Ok(()), // should not happen, skip.
        };

        assert_eq!(sandbox.config(&format!("setgid+root:{nogroup}")), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, nogroup_gid, "{sandbox}");
        assert_eq!(sandbox.config(&format!("setgid+root:{nogroup}")), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config(&format!("setgid+root:{nogroup}")), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config(&format!("setgid-root:{nogroup}")), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_6() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        // Adding a transition with same source but diff target fails.
        assert_eq!(sandbox.config("setuid+root:nobody"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.config("setuid+root:nobody"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setuid+root:65533"), Err(Errno::EEXIST));
        // Removing the transition and then re-adding with diff target is OK.
        assert_eq!(sandbox.config("setuid-root:nobody"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.config("setuid+root:65533"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65533), "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_7() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        let (nogroup_gid, nogroup) = match get_nogroup() {
            Ok((nogroup_gid, nogroup)) => (nogroup_gid, nogroup),
            Err(_) => return Ok(()), // should not happen, skip.
        };

        // Adding a transition with same source but diff target fails.
        assert_eq!(sandbox.config(&format!("setgid+root:{nogroup}")), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, nogroup_gid, "{sandbox}");
        assert_eq!(sandbox.config(&format!("setgid+root:{nogroup}")), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.config("setgid+root:65532"), Err(Errno::EEXIST));
        // Removing the transition and then re-adding with diff target is OK.
        assert_eq!(sandbox.config(&format!("setgid-root:{nogroup}")), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.config("setgid+root:65532"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 1, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, Gid::from_raw(65532), "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_8() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setuid+root:65534"), Ok(()));
        assert_eq!(sandbox.config("setuid+1:65533"), Ok(()));
        assert_eq!(sandbox.config("setuid+2:65532"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, Uid::from_raw(65533), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, Uid::from_raw(65532), "{sandbox}");
        assert_eq!(sandbox.config("setuid^"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_9() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setgid+root:65534"), Ok(()));
        assert_eq!(sandbox.config("setgid+1:65533"), Ok(()));
        assert_eq!(sandbox.config("setgid+2:65532"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, Gid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, Gid::from_raw(65533), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, Gid::from_raw(65532), "{sandbox}");
        assert_eq!(sandbox.config("setgid^"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_10() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setuid+root:65534"), Ok(()));
        assert_eq!(sandbox.config("setuid+1:65533"), Ok(()));
        assert_eq!(sandbox.config("setuid+2:65532"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, Uid::from_raw(65533), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, Uid::from_raw(65532), "{sandbox}");
        assert_eq!(sandbox.config("setuid^root:1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setuid^root"), Ok(()));
        assert_eq!(sandbox.transit_uids.len(), 2, "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[0].1, Uid::from_raw(65533), "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_safesetuser_11() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.transit_uids.len(), 0, "{sandbox}");
        assert_eq!(sandbox.transit_gids.len(), 0, "{sandbox}");

        assert_eq!(sandbox.config("setgid+root:65534"), Ok(()));
        assert_eq!(sandbox.config("setgid+1:65533"), Ok(()));
        assert_eq!(sandbox.config("setgid+2:65532"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 3, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(0), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, Gid::from_raw(65534), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, Gid::from_raw(65533), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, Gid::from_raw(65532), "{sandbox}");
        assert_eq!(sandbox.config("setgid^root:1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("setgid^root"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 2, "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[0].1, Gid::from_raw(65533), "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_1() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/read+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        sandbox.config("allow/read-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        sandbox.config("lock:on")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_2() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/read+/usr")?;
        sandbox.config("allow/read+/usr/**")?;
        sandbox.config("allow/read+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");

        sandbox.config("allow/read^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        sandbox.config("lock:on")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_3() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/write+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("allow/write-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        sandbox.config("lock:on")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_4() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/write+/usr")?;
        sandbox.config("allow/write+/usr/**")?;
        sandbox.config("allow/write+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("allow/write^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        sandbox.config("lock:on")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_5() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/exec+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("allow/exec-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        // TODO: continue seal tests.

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_6() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/exec+/usr")?;
        sandbox.config("allow/exec+/usr/**")?;
        sandbox.config("allow/exec+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("allow/exec^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_7() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/net/bind+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("allow/net/bind-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_8() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/net/bind+/usr/**")?;
        sandbox.config("allow/net/bind+/usr")?;
        sandbox.config("allow/net/bind+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("allow/net/bind^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_9() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/net/connect+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("allow/net/connect-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_10() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/net/connect+/usr/**")?;
        sandbox.config("allow/net/connect+/usr/**")?;
        sandbox.config("allow/net/connect+/usr")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("allow/net/connect^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_11() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_12() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+127.0.0.0/8!1024")?;
        sandbox.config("allow/net/bind+127.0.0.0/8!1024-65535")?;
        sandbox.config("allow/net/bind+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_13() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_14() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+127.0.0.0/8!1024-65535")?;
        sandbox.config("allow/net/connect+127.0.0.0/7!1024-65535")?;
        sandbox.config("allow/net/connect+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_15() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_16() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+::1/8!1024-65535")?;
        sandbox.config("allow/net/bind+::1/8!1024-65535")?;
        sandbox.config("allow/net/bind+::1/8!1024-65525")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_17() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_18() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+::1/8!1024-65535")?;
        sandbox.config("allow/net/connect+::1/8!1024-65535")?;
        sandbox.config("allow/net/connect+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_19() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/read+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("deny/read-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_20() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/read+/usr/**")?;
        sandbox.config("deny/read+/usr/*")?;
        sandbox.config("deny/read+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("deny/read^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_21() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/write+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("deny/write-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_22() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/write+/usr/**")?;
        sandbox.config("deny/write+/usr/**")?;
        sandbox.config("deny/write+/usr/*")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("deny/write^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_23() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/exec+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("deny/exec-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_24() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/exec+/usr/**")?;
        sandbox.config("deny/exec+/usr/**")?;
        sandbox.config("deny/exec+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("deny/exec^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_25() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/net/bind+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("deny/net/bind-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_26() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/net/bind+/usr")?;
        sandbox.config("deny/net/bind+/usr/*")?;
        sandbox.config("deny/net/bind+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("deny/net/bind-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_27() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/net/connect+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("deny/net/connect-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_28() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/net/connect+/usr/**")?;
        sandbox.config("deny/net/connect+/usr/*")?;
        sandbox.config("deny/net/connect+/usr")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("deny/net/connect^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_29() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_30() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+127.0.1.0/8!1024-65535")?;
        sandbox.config("deny/net/bind+127.0.0.1/8!1024-65535")?;
        sandbox.config("deny/net/bind+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_31() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_32() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+127.0.0.0/8!1024-65535")?;
        sandbox.config("deny/net/connect+127.0.0.1/8!1024-65535")?;
        sandbox.config("deny/net/connect+127.0.0.0/8!1024-65535")?;
        sandbox.config("deny/net/connect+127.0.1.0/8!1024-65535")?;
        sandbox.config("deny/net/connect+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 5, "{sandbox}");
        sandbox.config("deny/net/connect^127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_33() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_34() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+::1/16!1024-65535")?;
        sandbox.config("deny/net/bind+::1/8!1024-65535")?;
        sandbox.config("deny/net/bind+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_35() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_36() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+::1/8!1024-65535")?;
        sandbox.config("deny/net/connect+::1/8!1024-65535")?;
        sandbox.config("deny/net/connect+::1!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/connect^::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_37() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/read+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("filter/read-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_38() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/read+/usr/**")?;
        sandbox.config("filter/read+/usr/**")?;
        sandbox.config("filter/read+/usr/*")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("filter/read^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_39() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/write+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("filter/write-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_40() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/write+/usr/**/")?;
        sandbox.config("filter/write+/usr/**")?;
        sandbox.config("filter/write+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("filter/write^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_41() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/exec+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("filter/exec-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_42() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/exec+/usr/**")?;
        sandbox.config("filter/exec+/usr/*")?;
        sandbox.config("filter/exec+/usr/**")?;
        sandbox.config("filter/exec+/usr/./**")?;
        sandbox.config("filter/exec+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 5, "{sandbox}");
        sandbox.config("filter/exec^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_43() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/net/bind+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("filter/net/bind-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_44() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/net/bind+/usr/**")?;
        sandbox.config("filter/net/bind+/usr/**")?;
        sandbox.config("filter/net/bind+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("filter/net/bind^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_45() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/net/connect+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("filter/net/connect-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_46() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/net/connect+/usr/**")?;
        sandbox.config("filter/net/connect+/usr/**/")?;
        sandbox.config("filter/net/connect+/usr/*")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("filter/net/connect-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_47() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_48() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+127.0.0.0/8!1024-65535")?;
        sandbox.config("filter/net/bind+127.0.0.0/8!1024-65535")?;
        sandbox.config("filter/net/bind+127.0.0.0/8!1023-65535")?;
        sandbox.config("filter/net/bind+127.0.0.0/8!1023-65534")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("filter/net/bind^127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_49() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_50() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+127.0.0.0/8!1024-65534")?;
        sandbox.config("filter/net/connect+127.0.0.0/8!1024-65535")?;
        sandbox.config("filter/net/connect+127.0.0.1/8!1024-65535")?;
        sandbox.config("filter/net/connect+127.0.0.0/8!1024-65535")?;
        sandbox.config("filter/net/connect+127.0.0.0/8!1025-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 5, "{sandbox}");
        sandbox.config("filter/net/connect^127.0.0.0/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_51() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_52() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+::1/8!1024-65535")?;
        sandbox.config("filter/net/bind+::1/8!1024-65535")?;
        sandbox.config("filter/net/bind+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/bind^::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_53() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_54() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+::1/8!1024-65535")?;
        sandbox.config("filter/net/connect+::1/8!1024-65535")?;
        sandbox.config("filter/net/connect+::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/connect^::1/8!1024-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_55() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_56() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+loopback4!0")?;
        sandbox.config("allow/net/bind+loopback4!0")?;
        sandbox.config("allow/net/bind+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_57() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_58() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+loopback4!0")?;
        sandbox.config("allow/net/connect+loopback4!0")?;
        sandbox.config("allow/net/connect+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_59() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_60() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+loopback4!0")?;
        sandbox.config("deny/net/bind+loopback4!0")?;
        sandbox.config("deny/net/bind+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_61() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_62() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+127.0.0.0/16!0-65535")?;
        sandbox.config("deny/net/connect+loopback4!0")?;
        sandbox.config("deny/net/connect+loopback4!0")?;
        sandbox.config("deny/net/connect+127.0.0.0/16!0-65535")?;
        sandbox.config("deny/net/connect+loopback4!0")?;
        sandbox.config("filter/net/connect+127.0.0.0/16!0-65535")?;
        sandbox.config("deny/net/connect+loopback4!0")?;
        sandbox.config("deny/net/bind+127.0.0.0/8!0-65535")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("deny/net/connect^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_63() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_64() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+loopback4!0")?;
        sandbox.config("filter/net/bind+loopback4!0")?;
        sandbox.config("filter/net/bind+loopback4!1")?;
        sandbox.config("filter/net/bind+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("filter/net/bind^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_65() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_66() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+loopback4!0")?;
        sandbox.config("filter/net/connect+loopback4!0")?;
        sandbox.config("filter/net/connect+loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/connect^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_67() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_68() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+loopback6!0")?;
        sandbox.config("allow/net/bind+loopback6!0")?;
        sandbox.config("allow/net/bind+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_69() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_70() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+loopback6!0")?;
        sandbox.config("allow/net/connect+loopback6!0")?;
        sandbox.config("allow/net/connect+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_71() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_72() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+loopback6!0")?;
        sandbox.config("deny/net/bind+loopback6!0")?;
        sandbox.config("deny/net/bind+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_73() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_74() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+loopback6!0")?;
        sandbox.config("deny/net/connect+loopback6!0")?;
        sandbox.config("deny/net/connect+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/connect^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_75() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_76() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+loopback6!0")?;
        sandbox.config("filter/net/bind+loopback6!0")?;
        sandbox.config("filter/net/bind+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/bind^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_77() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_78() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+loopback6!0")?;
        sandbox.config("filter/net/connect+loopback6!0")?;
        sandbox.config("filter/net/connect+loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/connect^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_79() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/bind-loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_80() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/bind-loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_81() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+loopback!0")?;
        sandbox.config("allow/net/bind+loopback!0")?;
        sandbox.config("allow/net/bind+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("allow/net/bind^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_82() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/connect-loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_83() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+loopback!0")?;
        sandbox.config("allow/net/connect+loopback!0")?;
        sandbox.config("allow/net/connect+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("allow/net/connect^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_84() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("deny/net/bind-loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_85() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+loopback!0")?;
        sandbox.config("deny/net/bind+loopback!0")?;
        sandbox.config("deny/net/bind+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("deny/net/bind^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_86() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("deny/net/connect-loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_87() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+loopback!0")?;
        sandbox.config("deny/net/connect+loopback!0")?;
        sandbox.config("deny/net/connect+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("deny/net/connect^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_88() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("filter/net/bind-loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_89() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+loopback!0")?;
        sandbox.config("filter/net/bind+loopback!0")?;
        sandbox.config("filter/net/bind+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("filter/net/bind^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_90() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("filter/net/connect-loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_91() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+loopback!0")?;
        sandbox.config("filter/net/connect+loopback!0")?;
        sandbox.config("filter/net/connect+loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("filter/net/connect^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_92() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("allow/net/bind-local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_93() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+local4!0")?;
        sandbox.config("allow/net/bind+local4!0")?;
        sandbox.config("allow/net/bind+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("allow/net/bind^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_94() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("allow/net/connect-local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_95() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+local4!0")?;
        sandbox.config("allow/net/connect+local4!0")?;
        sandbox.config("allow/net/connect+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("allow/net/connect^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_96() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("deny/net/bind-local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_97() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+local4!0")?;
        sandbox.config("deny/net/bind+local4!0")?;
        sandbox.config("deny/net/bind+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("deny/net/bind^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_98() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("deny/net/connect-local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_99() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+local4!0")?;
        sandbox.config("deny/net/connect+local4!0")?;
        sandbox.config("deny/net/connect+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("deny/net/connect^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_100() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("filter/net/bind-local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_101() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+local4!0")?;
        sandbox.config("filter/net/bind+local4!0")?;
        sandbox.config("filter/net/bind+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/bind^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_102() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("filter/net/connect-local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_103() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+local4!0")?;
        sandbox.config("filter/net/connect+local4!0")?;
        sandbox.config("filter/net/connect+local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/connect^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_104() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("allow/net/bind-local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_105() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+local6!0")?;
        sandbox.config("allow/net/bind+local6!0")?;
        sandbox.config("allow/net/bind+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("allow/net/bind^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_106() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("allow/net/connect-local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_107() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+local6!0")?;
        sandbox.config("allow/net/connect+local6!0")?;
        sandbox.config("allow/net/connect+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("allow/net/connect^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_108() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("deny/net/bind-local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_109() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+local6!0")?;
        sandbox.config("deny/net/bind+local6!0")?;
        sandbox.config("deny/net/bind+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("deny/net/bind^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_110() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("deny/net/connect-local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_111() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+local6!0")?;
        sandbox.config("deny/net/connect+local6!0")?;
        sandbox.config("deny/net/connect+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("deny/net/connect^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_112() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("filter/net/bind-local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_113() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+local6!0")?;
        sandbox.config("filter/net/bind+local6!0")?;
        sandbox.config("filter/net/bind+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/bind^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_114() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("filter/net/connect-local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_115() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+local6!0")?;
        sandbox.config("filter/net/connect+local6!0")?;
        sandbox.config("filter/net/connect+local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/connect^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_116() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("filter/net/bind-local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_117() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+local!0")?;
        sandbox.config("filter/net/bind+local!0")?;
        sandbox.config("filter/net/bind+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 24, "{sandbox}");
        sandbox.config("filter/net/bind^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_118() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("filter/net/connect-local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_119() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+local!0")?;
        sandbox.config("filter/net/connect+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 16, "{sandbox}");
        sandbox.config("filter/net/connect^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_120() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("allow/net/bind-local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_121() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+local!1")?;
        sandbox.config("allow/net/bind+local!0")?;
        sandbox.config("allow/net/bind+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 24, "{sandbox}");
        sandbox.config("allow/net/bind^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_122() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("allow/net/connect-local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_123() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+127.0.0.2!0")?;
        sandbox.config("allow/net/connect+local!0")?;
        sandbox.config("allow/net/connect+local!0")?;
        sandbox.config("allow/net/connect+local!1")?;
        assert_eq!(sandbox.cidr_rules.len(), 25, "{sandbox}");
        sandbox.config("allow/net/connect^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 9, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_124() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("deny/net/bind-local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_125() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+local!0")?;
        sandbox.config("deny/net/bind+127.0.0.1!0")?;
        sandbox.config("deny/net/bind+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 17, "{sandbox}");
        sandbox.config("deny/net/bind^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_126() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("deny/net/connect-local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_127() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+local!0")?;
        sandbox.config("deny/net/connect+local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 16, "{sandbox}");
        sandbox.config("deny/net/connect^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_128() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_129() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+linklocal4!0")?;
        sandbox.config("allow/net/bind+linklocal4!0")?;
        sandbox.config("allow/net/bind+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_130() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_131() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+127.0.0.3!7")?;
        sandbox.config("allow/net/connect+linklocal4!0")?;
        sandbox.config("allow/net/connect+linklocal4!0")?;
        sandbox.config("allow/net/connect+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("allow/net/connect^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_132() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_133() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+linklocal4!0")?;
        sandbox.config("deny/net/bind+linklocal4!0")?;
        sandbox.config("deny/net/bind+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_134() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_135() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+linklocal4!0")?;
        sandbox.config("deny/net/connect+linklocal4!0")?;
        sandbox.config("deny/net/connect+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/connect^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_136() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_137() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+linklocal4!0")?;
        sandbox.config("filter/net/bind+linklocal4!0")?;
        sandbox.config("filter/net/bind+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/bind^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_138() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_139() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+linklocal4!0")?;
        sandbox.config("filter/net/connect+linklocal4!0")?;
        sandbox.config("filter/net/connect+linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/connect^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_140() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_141() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+linklocal6!0")?;
        sandbox.config("allow/net/bind+linklocal6!0")?;
        sandbox.config("allow/net/bind+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_142() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_143() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+linklocal6!0")?;
        sandbox.config("allow/net/connect+linklocal6!0")?;
        sandbox.config("allow/net/connect+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_144() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_145() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+linklocal6!0")?;
        sandbox.config("deny/net/bind+linklocal6!0")?;
        sandbox.config("deny/net/bind+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_146() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_147() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+linklocal6!0")?;
        sandbox.config("deny/net/connect+linklocal6!0")?;
        sandbox.config("deny/net/connect+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/connect^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_148() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_149() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+linklocal6!0")?;
        sandbox.config("filter/net/bind+linklocal6!0")?;
        sandbox.config("filter/net/bind+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/bind^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_150() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_151() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+linklocal6!0")?;
        sandbox.config("filter/net/connect+linklocal6!0")?;
        sandbox.config("filter/net/connect+linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/connect^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_152() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("filter/net/bind-linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_153() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+linklocal!0")?;
        sandbox.config("filter/net/bind+linklocal!0")?;
        sandbox.config("filter/net/bind+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("filter/net/bind^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_154() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("filter/net/connect-linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_155() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+linklocal!0")?;
        sandbox.config("filter/net/connect+linklocal!0")?;
        sandbox.config("filter/net/connect+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("filter/net/connect^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_156() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/bind-linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_157() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+linklocal!0")?;
        sandbox.config("allow/net/bind+linklocal!0")?;
        sandbox.config("allow/net/bind+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("allow/net/bind^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_158() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/connect-linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_159() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+linklocal!0")?;
        sandbox.config("allow/net/connect+linklocal!0")?;
        sandbox.config("allow/net/connect+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("allow/net/connect^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_160() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("deny/net/bind-linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_161() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+linklocal!0")?;
        sandbox.config("deny/net/bind+linklocal!0")?;
        sandbox.config("deny/net/bind+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("deny/net/bind^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_162() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("deny/net/connect-linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_163() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+linklocal!0")?;
        sandbox.config("deny/net/connect+linklocal!0")?;
        sandbox.config("deny/net/connect+linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("deny/net/connect^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_164() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_165() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+any4!0")?;
        sandbox.config("allow/net/bind+any4!0")?;
        sandbox.config("allow/net/bind+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_166() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_167() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+any4!0")?;
        sandbox.config("allow/net/connect+any4!0")?;
        sandbox.config("allow/net/connect+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_168() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_169() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+any4!0")?;
        sandbox.config("deny/net/bind+any4!0")?;
        sandbox.config("deny/net/bind+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_170() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_171() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+any4!0")?;
        sandbox.config("deny/net/connect+any4!0")?;
        sandbox.config("deny/net/connect+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/connect^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_172() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_173() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+any4!0")?;
        sandbox.config("filter/net/bind+any4!0")?;
        sandbox.config("filter/net/bind+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/bind^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_174() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_175() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+any4!0")?;
        sandbox.config("filter/net/connect+any4!0")?;
        sandbox.config("filter/net/connect+any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/connect^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_176() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_177() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+any6!0")?;
        sandbox.config("allow/net/bind+any6!0")?;
        sandbox.config("allow/net/bind+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/bind^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_178() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_179() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+any6!0")?;
        sandbox.config("allow/net/connect+any6!0")?;
        sandbox.config("allow/net/connect+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_180() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_181() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+any6!0")?;
        sandbox.config("deny/net/bind+any6!0")?;
        sandbox.config("deny/net/bind+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/bind^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_182() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_183() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+any6!0")?;
        sandbox.config("deny/net/connect+any6!0")?;
        sandbox.config("deny/net/connect+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("deny/net/connect^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_184() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/bind-any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_185() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+any6!0")?;
        sandbox.config("filter/net/bind+any6!0")?;
        sandbox.config("filter/net/bind+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/bind^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_186() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("filter/net/connect-any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_187() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+any6!0")?;
        sandbox.config("filter/net/connect+any6!0")?;
        sandbox.config("filter/net/connect+any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("filter/net/connect^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_188() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/bind-any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_189() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+any!0")?;
        sandbox.config("allow/net/bind+any!0")?;
        sandbox.config("allow/net/bind+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("allow/net/bind^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_190() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/connect-any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_191() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+any!0")?;
        sandbox.config("allow/net/connect+any!0")?;
        sandbox.config("allow/net/connect+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("allow/net/connect^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_192() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("deny/net/bind-any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_193() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+any!0")?;
        sandbox.config("deny/net/bind+any!0")?;
        sandbox.config("deny/net/bind+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("deny/net/bind^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_194() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("deny/net/connect-any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_195() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+any!0")?;
        sandbox.config("deny/net/connect+any!0")?;
        sandbox.config("deny/net/connect+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("deny/net/connect^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_196() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("filter/net/bind-any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_197() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/bind+any!0")?;
        sandbox.config("filter/net/bind+any!0")?;
        sandbox.config("filter/net/bind+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("filter/net/bind^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_198() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("filter/net/connect-any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_199() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("filter/net/connect+any!0")?;
        sandbox.config("filter/net/connect+any!0")?;
        sandbox.config("filter/net/connect+any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("filter/net/connect^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_200() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..8 {
            sandbox.config("allow/net/bind+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        for _ in 0..8 {
            sandbox.config("allow/net/bind-loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_201() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..8 {
            sandbox.config("allow/net/bind+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("allow/net/bind^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_202() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..9 {
            sandbox.config("allow/net/connect+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 9, "{sandbox}");
        for _ in 0..9 {
            sandbox.config("allow/net/connect-loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_203() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..9 {
            sandbox.config("allow/net/connect+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 9, "{sandbox}");
        sandbox.config("allow/net/connect^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_204() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..10 {
            sandbox.config("deny/net/bind+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        for _ in 0..10 {
            sandbox.config("deny/net/bind-loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_205() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..10 {
            sandbox.config("deny/net/bind+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        sandbox.config("deny/net/bind^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_206() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..11 {
            sandbox.config("deny/net/connect+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 11, "{sandbox}");
        for _ in 0..11 {
            sandbox.config("deny/net/connect-loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_207() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..11 {
            sandbox.config("deny/net/connect+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 11, "{sandbox}");
        sandbox.config("deny/net/connect^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_208() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..12 {
            sandbox.config("filter/net/bind+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        for _ in 0..12 {
            sandbox.config("filter/net/bind-loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_209() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..12 {
            sandbox.config("filter/net/bind+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/bind^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_210() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..13 {
            sandbox.config("filter/net/connect+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 13, "{sandbox}");
        for _ in 0..13 {
            sandbox.config("filter/net/connect-loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_211() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..13 {
            sandbox.config("filter/net/connect+loopback4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 13, "{sandbox}");
        sandbox.config("filter/net/connect^loopback4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_212() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..8 {
            sandbox.config("allow/net/bind+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        for _ in 0..8 {
            sandbox.config("allow/net/bind-loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_213() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..8 {
            sandbox.config("allow/net/bind+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("allow/net/bind^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_214() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..9 {
            sandbox.config("allow/net/connect+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 9, "{sandbox}");
        for _ in 0..9 {
            sandbox.config("allow/net/connect-loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_215() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..9 {
            sandbox.config("allow/net/connect+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 9, "{sandbox}");
        sandbox.config("allow/net/connect^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_216() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..10 {
            sandbox.config("deny/net/bind+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        for _ in 0..10 {
            sandbox.config("deny/net/bind-loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_217() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..10 {
            sandbox.config("deny/net/bind+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        sandbox.config("deny/net/bind^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_218() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..11 {
            sandbox.config("deny/net/connect+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 11, "{sandbox}");
        for _ in 0..11 {
            sandbox.config("deny/net/connect-loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_219() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..11 {
            sandbox.config("deny/net/connect+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 11, "{sandbox}");
        sandbox.config("deny/net/connect^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_220() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..12 {
            sandbox.config("filter/net/bind+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        for _ in 0..12 {
            sandbox.config("filter/net/bind-loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_221() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..12 {
            sandbox.config("filter/net/bind+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/bind^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_222() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..13 {
            sandbox.config("filter/net/connect+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 13, "{sandbox}");
        for _ in 0..13 {
            sandbox.config("filter/net/connect-loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_223() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..13 {
            sandbox.config("filter/net/connect+loopback6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 13, "{sandbox}");
        sandbox.config("filter/net/connect^loopback6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_224() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..2 {
            sandbox.config("allow/net/bind+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        for _ in 0..2 {
            sandbox.config("allow/net/bind-loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_225() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..2 {
            sandbox.config("allow/net/bind+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("allow/net/bind^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_226() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..3 {
            sandbox.config("allow/net/connect+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        for _ in 0..3 {
            sandbox.config("allow/net/connect-loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_227() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..3 {
            sandbox.config("allow/net/connect+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("allow/net/connect^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_228() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..4 {
            sandbox.config("deny/net/bind+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        for _ in 0..4 {
            sandbox.config("deny/net/bind-loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_229() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..4 {
            sandbox.config("deny/net/bind+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("deny/net/bind^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_230() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..5 {
            sandbox.config("deny/net/connect+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        for _ in 0..5 {
            sandbox.config("deny/net/connect-loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_231() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..5 {
            sandbox.config("deny/net/connect+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        sandbox.config("deny/net/connect^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_232() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..6 {
            sandbox.config("filter/net/bind+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        for _ in 0..6 {
            sandbox.config("filter/net/bind-loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_233() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..6 {
            sandbox.config("filter/net/bind+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/bind^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_234() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..7 {
            sandbox.config("filter/net/connect+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 14, "{sandbox}");
        for _ in 0..7 {
            sandbox.config("filter/net/connect-loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_235() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..7 {
            sandbox.config("filter/net/connect+loopback!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 14, "{sandbox}");
        sandbox.config("filter/net/connect^loopback!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_236() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..14 {
            sandbox.config("allow/net/bind+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 14, "{sandbox}");
        for _ in 0..14 {
            sandbox.config("allow/net/bind-local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_237() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..14 {
            sandbox.config("allow/net/bind+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 14, "{sandbox}");
        sandbox.config("allow/net/bind^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_238() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..15 {
            sandbox.config("allow/net/connect+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 15, "{sandbox}");
        for _ in 0..15 {
            sandbox.config("allow/net/connect-local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_239() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..15 {
            sandbox.config("allow/net/connect+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 15, "{sandbox}");
        sandbox.config("allow/net/connect^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_240() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..16 {
            sandbox.config("deny/net/bind+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 16, "{sandbox}");
        for _ in 0..16 {
            sandbox.config("deny/net/bind-local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_241() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..16 {
            sandbox.config("deny/net/bind+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 16, "{sandbox}");
        sandbox.config("deny/net/bind^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_242() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..17 {
            sandbox.config("deny/net/connect+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 17, "{sandbox}");
        for _ in 0..17 {
            sandbox.config("deny/net/connect-local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_243() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..17 {
            sandbox.config("deny/net/connect+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 17, "{sandbox}");
        sandbox.config("deny/net/connect^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_244() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..18 {
            sandbox.config("filter/net/bind+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 18, "{sandbox}");
        for _ in 0..18 {
            sandbox.config("filter/net/bind-local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_245() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..18 {
            sandbox.config("filter/net/bind+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 18, "{sandbox}");
        sandbox.config("filter/net/bind^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_246() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..19 {
            sandbox.config("filter/net/connect+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 19, "{sandbox}");
        for _ in 0..19 {
            sandbox.config("filter/net/connect-local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_247() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..19 {
            sandbox.config("filter/net/connect+local4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 19, "{sandbox}");
        sandbox.config("filter/net/connect^local4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_248() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 20, "{sandbox}");
        for _ in 0..20 {
            sandbox.config("allow/net/bind-local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_249() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 20, "{sandbox}");
        sandbox.config("allow/net/bind^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_250() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 21, "{sandbox}");
        for _ in 0..21 {
            sandbox.config("allow/net/connect-local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_251() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 21, "{sandbox}");
        sandbox.config("allow/net/connect^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_252() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 22, "{sandbox}");
        for _ in 0..22 {
            sandbox.config("deny/net/bind-local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_253() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 22, "{sandbox}");
        sandbox.config("deny/net/bind^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_254() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 23, "{sandbox}");
        for _ in 0..23 {
            sandbox.config("deny/net/connect-local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_255() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 23, "{sandbox}");
        sandbox.config("deny/net/connect^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_256() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 24, "{sandbox}");
        for _ in 0..24 {
            sandbox.config("filter/net/bind-local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_257() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 24, "{sandbox}");
        sandbox.config("filter/net/bind^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_258() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 25, "{sandbox}");
        for _ in 0..25 {
            sandbox.config("filter/net/connect-local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_259() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+local6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4 * 25, "{sandbox}");
        sandbox.config("filter/net/connect^local6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_260() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 20, "{sandbox}");
        for _ in 0..20 {
            sandbox.config("allow/net/bind-local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_261() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 20, "{sandbox}");
        sandbox.config("allow/net/bind^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_262() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 21, "{sandbox}");
        for _ in 0..21 {
            sandbox.config("allow/net/connect-local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_263() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 21, "{sandbox}");
        sandbox.config("allow/net/connect^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_264() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 22, "{sandbox}");
        for _ in 0..22 {
            sandbox.config("deny/net/bind-local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_265() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 22, "{sandbox}");
        sandbox.config("deny/net/bind^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_266() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 23, "{sandbox}");
        for _ in 0..23 {
            sandbox.config("deny/net/connect-local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_267() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 23, "{sandbox}");
        sandbox.config("deny/net/connect^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_268() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 24, "{sandbox}");
        for _ in 0..24 {
            sandbox.config("filter/net/bind-local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_269() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 24, "{sandbox}");
        sandbox.config("filter/net/bind^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_270() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 25, "{sandbox}");
        for _ in 0..25 {
            sandbox.config("filter/net/connect-local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_271() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+local!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8 * 25, "{sandbox}");
        sandbox.config("filter/net/connect^local!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_272() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..4 {
            sandbox.config("deny/net/bind+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        for _ in 0..4 {
            sandbox.config("deny/net/bind-any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_273() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..4 {
            sandbox.config("deny/net/bind+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 4, "{sandbox}");
        sandbox.config("deny/net/bind^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_274() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..5 {
            sandbox.config("deny/net/connect+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 5, "{sandbox}");
        for _ in 0..5 {
            sandbox.config("deny/net/connect-any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_275() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..5 {
            sandbox.config("deny/net/connect+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 5, "{sandbox}");
        sandbox.config("deny/net/connect^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_276() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..14 {
            sandbox.config("allow/net/bind+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 14, "{sandbox}");
        for _ in 0..14 {
            sandbox.config("allow/net/bind-linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_277() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..14 {
            sandbox.config("allow/net/bind+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 14, "{sandbox}");
        sandbox.config("allow/net/bind^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_278() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..15 {
            sandbox.config("allow/net/connect+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 15, "{sandbox}");
        for _ in 0..15 {
            sandbox.config("allow/net/connect-linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_279() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..15 {
            sandbox.config("allow/net/connect+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 15, "{sandbox}");
        sandbox.config("allow/net/connect^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_280() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..16 {
            sandbox.config("deny/net/bind+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 16, "{sandbox}");
        for _ in 0..16 {
            sandbox.config("deny/net/bind-linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_281() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..16 {
            sandbox.config("deny/net/bind+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 16, "{sandbox}");
        sandbox.config("deny/net/bind^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_282() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..17 {
            sandbox.config("deny/net/connect+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 17, "{sandbox}");
        for _ in 0..17 {
            sandbox.config("deny/net/connect-linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_283() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..17 {
            sandbox.config("deny/net/connect+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 17, "{sandbox}");
        sandbox.config("deny/net/connect^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_284() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..18 {
            sandbox.config("filter/net/bind+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 18, "{sandbox}");
        for _ in 0..18 {
            sandbox.config("filter/net/bind-linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_285() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..18 {
            sandbox.config("filter/net/bind+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 18, "{sandbox}");
        sandbox.config("filter/net/bind^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_286() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..19 {
            sandbox.config("filter/net/connect+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 19, "{sandbox}");
        for _ in 0..19 {
            sandbox.config("filter/net/connect-linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_287() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..19 {
            sandbox.config("filter/net/connect+linklocal4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 19, "{sandbox}");
        sandbox.config("filter/net/connect^linklocal4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_288() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 20, "{sandbox}");
        for _ in 0..20 {
            sandbox.config("allow/net/bind-linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_289() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 20, "{sandbox}");
        sandbox.config("allow/net/bind^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_290() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 21, "{sandbox}");
        for _ in 0..21 {
            sandbox.config("allow/net/connect-linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_291() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 21, "{sandbox}");
        sandbox.config("allow/net/connect^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_292() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 22, "{sandbox}");
        for _ in 0..22 {
            sandbox.config("deny/net/bind-linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_293() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 22, "{sandbox}");
        sandbox.config("deny/net/bind^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_294() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 23, "{sandbox}");
        for _ in 0..23 {
            sandbox.config("deny/net/connect-linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_295() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 23, "{sandbox}");
        sandbox.config("deny/net/connect^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_296() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 24, "{sandbox}");
        for _ in 0..24 {
            sandbox.config("filter/net/bind-linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_297() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 24, "{sandbox}");
        sandbox.config("filter/net/bind^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_298() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 25, "{sandbox}");
        for _ in 0..25 {
            sandbox.config("filter/net/connect-linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_299() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+linklocal6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 25, "{sandbox}");
        sandbox.config("filter/net/connect^linklocal6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_300() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 20, "{sandbox}");
        for _ in 0..20 {
            sandbox.config("allow/net/bind-linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_301() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..20 {
            sandbox.config("allow/net/bind+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 20, "{sandbox}");
        sandbox.config("allow/net/bind^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_302() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 21, "{sandbox}");
        for _ in 0..21 {
            sandbox.config("allow/net/connect-linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_303() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..21 {
            sandbox.config("allow/net/connect+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 21, "{sandbox}");
        sandbox.config("allow/net/connect^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_304() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 22, "{sandbox}");
        for _ in 0..22 {
            sandbox.config("deny/net/bind-linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_305() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..22 {
            sandbox.config("deny/net/bind+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 22, "{sandbox}");
        sandbox.config("deny/net/bind^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_306() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 23, "{sandbox}");
        for _ in 0..23 {
            sandbox.config("deny/net/connect-linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_307() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..23 {
            sandbox.config("deny/net/connect+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 23, "{sandbox}");
        sandbox.config("deny/net/connect^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_308() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 24, "{sandbox}");
        for _ in 0..24 {
            sandbox.config("filter/net/bind-linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_309() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..24 {
            sandbox.config("filter/net/bind+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 24, "{sandbox}");
        sandbox.config("filter/net/bind^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_310() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 25, "{sandbox}");
        for _ in 0..25 {
            sandbox.config("filter/net/connect-linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_311() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..25 {
            sandbox.config("filter/net/connect+linklocal!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2 * 25, "{sandbox}");
        sandbox.config("filter/net/connect^linklocal!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_312() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..2 {
            sandbox.config("allow/net/bind+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        for _ in 0..2 {
            sandbox.config("allow/net/bind-any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_313() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..2 {
            sandbox.config("allow/net/bind+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 2, "{sandbox}");
        sandbox.config("allow/net/bind^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_314() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..3 {
            sandbox.config("allow/net/connect+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        for _ in 0..3 {
            sandbox.config("allow/net/connect-any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_315() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..3 {
            sandbox.config("allow/net/connect+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 3, "{sandbox}");
        sandbox.config("allow/net/connect^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_316() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..6 {
            sandbox.config("filter/net/bind+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        for _ in 0..6 {
            sandbox.config("filter/net/bind-any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_317() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..6 {
            sandbox.config("filter/net/bind+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 6, "{sandbox}");
        sandbox.config("filter/net/bind^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_318() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..7 {
            sandbox.config("filter/net/connect+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 7, "{sandbox}");
        for _ in 0..7 {
            sandbox.config("filter/net/connect-any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_319() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..7 {
            sandbox.config("filter/net/connect+any4!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 7, "{sandbox}");
        sandbox.config("filter/net/connect^any4!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_320() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..8 {
            sandbox.config("allow/net/bind+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        for _ in 0..8 {
            sandbox.config("allow/net/bind-any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_321() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..8 {
            sandbox.config("allow/net/bind+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 8, "{sandbox}");
        sandbox.config("allow/net/bind^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_322() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..9 {
            sandbox.config("allow/net/connect+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 9, "{sandbox}");
        for _ in 0..9 {
            sandbox.config("allow/net/connect-any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_323() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..9 {
            sandbox.config("allow/net/connect+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 9, "{sandbox}");
        sandbox.config("allow/net/connect^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_324() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..10 {
            sandbox.config("deny/net/bind+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        for _ in 0..10 {
            sandbox.config("deny/net/bind-any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_325() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..10 {
            sandbox.config("deny/net/bind+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 10, "{sandbox}");
        sandbox.config("deny/net/bind^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_326() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..11 {
            sandbox.config("deny/net/connect+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 11, "{sandbox}");
        for _ in 0..11 {
            sandbox.config("deny/net/connect-any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_327() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..11 {
            sandbox.config("deny/net/connect+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 11, "{sandbox}");
        sandbox.config("deny/net/connect^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_328() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..12 {
            sandbox.config("filter/net/bind+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        for _ in 0..12 {
            sandbox.config("filter/net/bind-any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_329() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..12 {
            sandbox.config("filter/net/bind+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 12, "{sandbox}");
        sandbox.config("filter/net/bind^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_330() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..13 {
            sandbox.config("filter/net/connect+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 13, "{sandbox}");
        for _ in 0..13 {
            sandbox.config("filter/net/connect-any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_331() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..13 {
            sandbox.config("filter/net/connect+any6!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 13, "{sandbox}");
        sandbox.config("filter/net/connect^any6!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_332() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..14 {
            sandbox.config("allow/net/bind+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 14 * 2, "{sandbox}");
        for _ in 0..14 {
            sandbox.config("allow/net/bind-any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_333() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..14 {
            sandbox.config("allow/net/bind+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 14 * 2, "{sandbox}");
        sandbox.config("allow/net/bind^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_334() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..15 {
            sandbox.config("allow/net/connect+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 15 * 2, "{sandbox}");
        for _ in 0..15 {
            sandbox.config("allow/net/connect-any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_335() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..15 {
            sandbox.config("allow/net/connect+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 15 * 2, "{sandbox}");
        sandbox.config("allow/net/connect^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_336() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..16 {
            sandbox.config("deny/net/bind+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 16 * 2, "{sandbox}");
        for _ in 0..16 {
            sandbox.config("deny/net/bind-any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_337() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..16 {
            sandbox.config("deny/net/bind+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 16 * 2, "{sandbox}");
        sandbox.config("deny/net/bind^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_338() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..17 {
            sandbox.config("deny/net/connect+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 17 * 2, "{sandbox}");
        for _ in 0..17 {
            sandbox.config("deny/net/connect-any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_339() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..17 {
            sandbox.config("deny/net/connect+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 17 * 2, "{sandbox}");
        sandbox.config("deny/net/connect^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_340() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..18 {
            sandbox.config("filter/net/bind+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 18 * 2, "{sandbox}");
        for _ in 0..18 {
            sandbox.config("filter/net/bind-any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_341() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..18 {
            sandbox.config("filter/net/bind+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 18 * 2, "{sandbox}");
        sandbox.config("filter/net/bind^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_342() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..19 {
            sandbox.config("filter/net/connect+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 19 * 2, "{sandbox}");
        for _ in 0..19 {
            sandbox.config("filter/net/connect-any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_343() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        for _ in 0..19 {
            sandbox.config("filter/net/connect+any!0")?;
        }
        assert_eq!(sandbox.cidr_rules.len(), 19 * 2, "{sandbox}");
        sandbox.config("filter/net/connect^any!0")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_344() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/stat+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("allow/stat-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_345() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("allow/stat+/usr/*")?;
        sandbox.config("allow/stat+/usr/**")?;
        sandbox.config("allow/stat+/usr/**")?;
        sandbox.config("allow/stat+/usr/**")?;
        sandbox.config("allow/stat+/usr")?;
        assert_eq!(sandbox.glob_rules().len(), len + 5, "{sandbox}");
        sandbox.config("allow/stat^/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 2, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_346() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("deny/stat+/usr/**")?;
        sandbox.config("deny/stat+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 2, "{sandbox}");
        sandbox.config("deny/stat-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("deny/stat-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_347() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.glob_rules().len();

        sandbox.config("filter/stat+/usr/**")?;
        sandbox.config("filter/stat+/usr/**")?;
        sandbox.config("filter/stat+/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 3, "{sandbox}");
        sandbox.config("filter/stat-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 2, "{sandbox}");
        sandbox.config("filter/stat-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len + 1, "{sandbox}");
        sandbox.config("filter/stat-/usr/**")?;
        assert_eq!(sandbox.glob_rules().len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_348() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/bind+1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/bind-1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/bind+1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/bind-1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("allow/net/connect+1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("allow/net/connect-1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        sandbox.config("deny/net/connect+1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 1, "{sandbox}");
        sandbox.config("deny/net/connect-1.1.1.1!80")?;
        assert_eq!(sandbox.cidr_rules.len(), 0, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_349() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.config("mask"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+:"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+::"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+a:b"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+a:/b"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+/a:b"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+/a:b"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+a:b:c"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+/a:b:c"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+a:/b:c"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+a:b:/c"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+/dev/null:"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+/dev/null:a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask^/"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask^/proc"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask!"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask!/proc"), Err(Errno::EINVAL));

        for p in [
            "/proc/cmdline",
            "/proc/kmsg",
            "/dev/kmsg",
            "/proc/loadavg",
            "/proc/meminfo",
            "/proc/version",
        ] {
            sandbox.config(&format!("mask+{p}"))?;
        }
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/config.gz"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cpuinfo"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/diskstats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/filesystems"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kallsyms"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kcore"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/latency_stats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/stat"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/uptime"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/vmstat"))
            .is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_350() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        for p in [
            "/proc/cmdline",
            "/proc/kmsg",
            "/dev/kmsg",
            "/proc/loadavg",
            "/proc/meminfo",
            "/proc/version",
        ] {
            sandbox.config(&format!("mask+{p}"))?;
        }
        let len = sandbox.mask_acl.len();
        sandbox.config("mask-/proc/cmdline")?;
        assert_eq!(sandbox.mask_acl.len(), len - 1, "{sandbox}");
        sandbox.config("mask-/proc/kmsg")?;
        assert_eq!(sandbox.mask_acl.len(), len - 2, "{sandbox}");
        sandbox.config("mask-/dev/kmsg")?;
        assert_eq!(sandbox.mask_acl.len(), len - 3, "{sandbox}");
        sandbox.config("mask-/proc/loadavg")?;
        assert_eq!(sandbox.mask_acl.len(), len - 4, "{sandbox}");
        sandbox.config("mask-/proc/meminfo")?;
        assert_eq!(sandbox.mask_acl.len(), len - 5, "{sandbox}");
        sandbox.config("mask-/proc/version")?;
        assert_eq!(sandbox.mask_acl.len(), len - 6, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_351() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        for p in [
            "/proc/cmdline",
            "/proc/kmsg",
            "/dev/kmsg",
            "/proc/loadavg",
            "/proc/meminfo",
            "/proc/version",
        ] {
            sandbox.config(&format!("mask+{p}"))?;
        }
        let len = sandbox.mask_acl.len();
        sandbox.config("mask+/proc/f?l?syst?ms")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/filesystems"))
            .is_some());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_352() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        for p in [
            "/proc/cmdline",
            "/proc/kmsg",
            "/dev/kmsg",
            "/proc/loadavg",
            "/proc/meminfo",
            "/proc/version",
        ] {
            sandbox.config(&format!("mask+{p}"))?;
        }
        let len = sandbox.mask_acl.len();
        sandbox.config("mask+/proc/f?l?syst?ms")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");
        sandbox.config("mask-/proc/f?l?syst?ms")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/filesystems"))
            .is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_353() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        for p in [
            "/proc/cmdline",
            "/proc/kmsg",
            "/dev/kmsg",
            "/proc/loadavg",
            "/proc/meminfo",
            "/proc/version",
        ] {
            sandbox.config(&format!("mask+{p}"))?;
        }
        let len = sandbox.mask_acl.len();
        sandbox.config("mask+/proc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");
        sandbox.config("mask-/proc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/config.gz"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cpuinfo"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/diskstats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/filesystems"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kallsyms"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kcore"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/latency_stats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/stat"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/uptime"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/vmstat"))
            .is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_354() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        for p in [
            "/proc/cmdline",
            "/proc/kmsg",
            "/dev/kmsg",
            "/proc/loadavg",
            "/proc/meminfo",
            "/proc/version",
        ] {
            sandbox.config(&format!("mask+{p}"))?;
        }
        let len = sandbox.mask_acl.len();
        for _ in 0..7 {
            sandbox.config("mask+/proc/f?l?syst?ms")?;
        }
        assert_eq!(sandbox.mask_acl.len(), len + 7, "{sandbox}");
        assert_eq!(sandbox.config("mask-/proc/f?l?syst?ms"), Ok(()));
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/config.gz"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cpuinfo"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/diskstats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/filesystems"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kallsyms"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kcore"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/latency_stats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/stat"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/uptime"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/vmstat"))
            .is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_355() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        for p in [
            "/proc/cmdline",
            "/proc/kmsg",
            "/dev/kmsg",
            "/proc/loadavg",
            "/proc/meminfo",
            "/proc/version",
        ] {
            sandbox.config(&format!("mask+{p}"))?;
        }
        let len = sandbox.mask_acl.len();

        for _ in 0..7 {
            sandbox.config("mask+/proc/***")?;
        }
        assert_eq!(sandbox.mask_acl.len(), len + 7, "{sandbox}");
        sandbox.config("mask-/proc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        for _ in 0..7 {
            sandbox.config("mask+/p?oc/***")?;
        }
        assert_eq!(sandbox.mask_acl.len(), len + 14, "{sandbox}");
        sandbox.config("mask-/p?oc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/config.gz"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cpuinfo"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/diskstats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/filesystems"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kallsyms"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kcore"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/latency_stats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/stat"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/uptime"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/vmstat"))
            .is_none());

        assert_eq!(sandbox.config("mask^/proc/cmdline"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask^/"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask^"), Ok(()));
        assert_eq!(sandbox.mask_acl.len(), 0, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/loadavg"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/meminfo"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/config.gz"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cpuinfo"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/diskstats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/filesystems"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kallsyms"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kcore"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/latency_stats"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/stat"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/uptime"))
            .is_none());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/vmstat"))
            .is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_356() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        // Absolute paths are required.
        assert_eq!(sandbox.config("mask+foo"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+foo:bar"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+/foo:bar"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+foo:/bar"), Err(Errno::EINVAL));

        // Empty path not permitted.
        assert_eq!(sandbox.config("mask+/foo:"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("mask+/dev/***:/dev/null"), Ok(()));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/dev")).is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/zero"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/fd/1"))
            .is_some());
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/de")).is_none());
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/opt")).is_none());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_357() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.config("append"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("append+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("append-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("append^"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("append!"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("append!/proc"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("append+/proc/cmd*"), Ok(()));
        assert_eq!(sandbox.config("append+/*/*msg"), Ok(()));
        assert_eq!(sandbox.config("append+!memfd:*"), Ok(()));
        assert_eq!(sandbox.config("append+!memfd:syd-kcov"), Ok(()));

        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"!memfd:syd")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"!memfd:syd-kcov")));
        assert!(!sandbox.is_append(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_358() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.append_acl.len();
        sandbox.config("append+/proc/cmd*ine")?;
        assert_eq!(sandbox.append_acl.len(), len + 1, "{sandbox}");
        sandbox.config("append+/proc/*msg")?;
        assert_eq!(sandbox.append_acl.len(), len + 2, "{sandbox}");
        sandbox.config("append+/dev/km*")?;
        assert_eq!(sandbox.append_acl.len(), len + 3, "{sandbox}");

        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(!sandbox.is_append(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_359() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.append_acl.len();
        sandbox.config("append+/proc/v?rs??n")?;
        assert_eq!(sandbox.append_acl.len(), len + 1, "{sandbox}");

        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_360() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.append_acl.len();
        sandbox.config("append+/proc/v?rs??n")?;
        assert_eq!(sandbox.append_acl.len(), len + 1, "{sandbox}");
        sandbox.config("append-/proc/v?rs??n")?;
        assert_eq!(sandbox.append_acl.len(), len, "{sandbox}");

        assert!(!sandbox.is_append(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_361() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.append_acl.len();
        sandbox.config("append+/proc/***")?;
        assert_eq!(sandbox.append_acl.len(), len + 1, "{sandbox}");
        sandbox.config("append-/proc/***")?;
        assert_eq!(sandbox.append_acl.len(), len, "{sandbox}");
        sandbox.config("append+/proc/***")?;
        assert_eq!(sandbox.append_acl.len(), len + 1, "{sandbox}");

        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(!sandbox.is_append(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_append(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_362() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.append_acl.len();
        for _ in 0..7 {
            sandbox.config("append+/proc/v?rs??n")?;
        }
        assert_eq!(sandbox.append_acl.len(), len + 7, "{sandbox}");
        sandbox.config("append^/proc/v?rs??n")?;
        assert_eq!(sandbox.append_acl.len(), len, "{sandbox}");

        assert!(!sandbox.is_append(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_363() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.append_acl.len();
        for _ in 0..7 {
            sandbox.config("append+/proc/***")?;
        }
        assert_eq!(sandbox.append_acl.len(), len + 7, "{sandbox}");
        sandbox.config("append^/proc/***")?;
        assert_eq!(sandbox.append_acl.len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_364() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.config("mask"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask!"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("mask!/proc"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("mask+/proc/cmd*"), Ok(()));
        assert_eq!(sandbox.config("mask+/*/*msg"), Ok(()));
        assert_eq!(sandbox.config("mask+!memfd*"), Ok(()));

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"!memfd:syd"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"!memfd:syd-kcov"))
            .is_some());
        assert!(!sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());

        assert_eq!(sandbox.config("mask^"), Ok(()));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_365() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.mask_acl.len();
        sandbox.config("mask+/proc/cmd*ine")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");
        sandbox.config("mask+/proc/*msg")?;
        assert_eq!(sandbox.mask_acl.len(), len + 2, "{sandbox}");
        sandbox.config("mask+/dev/km*")?;
        assert_eq!(sandbox.mask_acl.len(), len + 3, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(!sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_366() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.mask_acl.len();
        sandbox.config("mask+/proc/v?rs??n")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_367() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.mask_acl.len();
        sandbox.config("mask+/proc/v?rs??n")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");
        sandbox.config("mask-/proc/v?rs??n")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        assert!(!sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_368() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.mask_acl.len();
        sandbox.config("mask+/proc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");
        sandbox.config("mask-/proc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");
        sandbox.config("mask+/proc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len + 1, "{sandbox}");

        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/cmdline"))
            .is_some());
        assert!(!sandbox
            .is_masked(&XPath::from_bytes(b"/dev/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/kmsg"))
            .is_some());
        assert!(sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_369() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.mask_acl.len();
        for _ in 0..7 {
            sandbox.config("mask+/proc/v?rs??n")?;
        }
        assert_eq!(sandbox.mask_acl.len(), len + 7, "{sandbox}");
        sandbox.config("mask-/proc/v?rs??n")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        assert!(!sandbox
            .is_masked(&XPath::from_bytes(b"/proc/version"))
            .is_some());

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_370() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.mask_acl.len();
        for _ in 0..7 {
            sandbox.config("mask+/proc/***")?;
        }
        assert_eq!(sandbox.mask_acl.len(), len + 7, "{sandbox}");
        sandbox.config("mask-/proc/***")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_371() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.mask_acl.len();
        for _ in 0..7 {
            sandbox.config("mask+/proc/***")?;
        }
        assert_eq!(sandbox.mask_acl.len(), len + 7, "{sandbox}");
        sandbox.config("mask^")?;
        assert_eq!(sandbox.mask_acl.len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_372() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(sandbox.config("crypt"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("crypt+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("crypt-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("crypt^"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("crypt!"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("crypt!/proc"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("crypt+/proc/cmd*"), Ok(()));
        assert_eq!(sandbox.config("crypt+/*/*msg"), Ok(()));
        assert_eq!(sandbox.config("crypt+!memfd:*"), Ok(()));
        assert_eq!(sandbox.config("crypt+!memfd:syd-kcov"), Ok(()));

        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"!memfd:syd")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"!memfd:syd-kcov")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        sandbox.config("sandbox/crypt:on")?;
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"!memfd:syd")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"!memfd:syd-kcov")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_373() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.crypt_acl.len();
        sandbox.config("crypt+/proc/cmd*ine")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 1, "{sandbox}");
        sandbox.config("crypt+/proc/*msg")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 2, "{sandbox}");
        sandbox.config("crypt+/dev/km*")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 3, "{sandbox}");

        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        sandbox.config("sandbox/crypt:on")?;
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_374() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.crypt_acl.len();
        sandbox.config("crypt+/proc/v?rs??n")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 1, "{sandbox}");

        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        sandbox.config("sandbox/crypt:on")?;
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_375() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.crypt_acl.len();
        sandbox.config("crypt+/proc/v?rs??n")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 1, "{sandbox}");
        sandbox.config("crypt-/proc/v?rs??n")?;
        assert_eq!(sandbox.crypt_acl.len(), len, "{sandbox}");

        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_376() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.crypt_acl.len();
        sandbox.config("crypt+/proc/***")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 1, "{sandbox}");
        sandbox.config("crypt-/proc/***")?;
        assert_eq!(sandbox.crypt_acl.len(), len, "{sandbox}");
        sandbox.config("crypt+/proc/***")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 1, "{sandbox}");

        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        sandbox.config("sandbox/crypt:on")?;
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_377() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.crypt_acl.len();
        for _ in 0..7 {
            sandbox.config("crypt+/proc/v?rs??n")?;
        }
        assert_eq!(sandbox.crypt_acl.len(), len + 7, "{sandbox}");
        sandbox.config("crypt^/proc/v?rs??n")?;
        assert_eq!(sandbox.crypt_acl.len(), len, "{sandbox}");

        assert!(!sandbox.is_crypt(&XPath::from_bytes(b"/proc/version")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_378() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.crypt_acl.len();
        for _ in 0..7 {
            sandbox.config("crypt+/proc/***")?;
        }
        assert_eq!(sandbox.crypt_acl.len(), len + 7, "{sandbox}");
        sandbox.config("crypt-/proc/***")?;
        assert_eq!(sandbox.crypt_acl.len(), len + 6, "{sandbox}");
        sandbox.config("crypt^/proc/***")?;
        assert_eq!(sandbox.crypt_acl.len(), len, "{sandbox}");

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_379() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let len = sandbox.fs_acl.len();
        for _ in 0..7 {
            sandbox.config("allow/fs+ext4")?;
        }
        assert_eq!(sandbox.fs_acl.len(), len + 7, "{sandbox}");
        sandbox.config("allow/fs-ext4")?;
        assert_eq!(sandbox.fs_acl.len(), len + 6, "{sandbox}");
        sandbox.config("allow/fs^ext4")?;
        assert_eq!(sandbox.fs_acl.len(), len, "{sandbox}");
        Ok(())
    }

    #[test]
    fn sandbox_config_rules_380() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert_eq!(
            sandbox.default_action(Capability::CAP_FS),
            Action::Deny,
            "{sandbox}"
        );
        sandbox.set_default_action(Capability::CAP_FS, Action::Kill);
        assert_eq!(
            sandbox.default_action(Capability::CAP_FS),
            Action::Kill,
            "{sandbox}"
        );
        for (fs_name, fs_type) in FS_MAGIC {
            let fs_type = FsType::from(fs_type);
            assert_eq!(
                sandbox.check_fs(fs_type).0,
                Action::Kill,
                "{fs_name}:{sandbox}"
            );
            sandbox.config(&format!("filter/fs+{fs_name}"))?;
            assert_eq!(
                sandbox.check_fs(fs_type),
                (Action::Kill, true),
                "{fs_name}:{sandbox}"
            );
        }
        Ok(())
    }

    #[test]
    fn sandbox_config_rules_381() -> TestResult<()> {
        const MAGIC: fs_type_t = 0xEF53;
        let mut sandbox = Sandbox::default();
        sandbox.config("allow/fs+ext4")?;
        assert_eq!(sandbox.check_fs(MAGIC.into()).0, Action::Allow, "{sandbox}");
        sandbox.config("abort/fs+ext4")?;
        assert_eq!(
            sandbox.check_fs(MAGIC.into()),
            (Action::Abort, false),
            "{sandbox}"
        );
        sandbox.config("filter/fs+ext4")?;
        assert_eq!(
            sandbox.check_fs(MAGIC.into()),
            (Action::Abort, true),
            "{sandbox}"
        );
        sandbox.config("filter/fs-ext4")?;
        assert_eq!(
            sandbox.check_fs(MAGIC.into()),
            (Action::Abort, false),
            "{sandbox}"
        );
        sandbox.config("panic/fs+ext4")?;
        assert_eq!(
            sandbox.check_fs(MAGIC.into()),
            (Action::Panic, false),
            "{sandbox}"
        );
        sandbox.config("panic/fs-ext4")?;
        assert_eq!(
            sandbox.check_fs(MAGIC.into()),
            (Action::Abort, false),
            "{sandbox}"
        );
        sandbox.config("abort/fs-ext4")?;
        assert_eq!(sandbox.check_fs(MAGIC.into()).0, Action::Allow, "{sandbox}");
        Ok(())
    }

    #[test]
    fn sandbox_glob_doublestar_does_not_match_basename() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/dev/**")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev")),
            None,
            "/dev =~ /dev/**, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_doublestar_matches_basename_with_slash() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/dev/**")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev/")),
            Some(Action::Allow),
            "/dev/ !~ /dev/**, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_doublestar_matches_pathname() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/dev/**")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev/null")),
            Some(Action::Allow),
            "/dev/null !~ /dev/**, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_triplestar_matches_basename_with_literal() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/dev/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev")),
            Some(Action::Allow),
            "/dev =~ /dev/***, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_triplestar_matches_basename_with_glob() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/*/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev")),
            Some(Action::Allow),
            "/dev =~ /*/***, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_triplestar_matches_basename_with_slash_and_literal() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/dev/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev/")),
            Some(Action::Allow),
            "/dev/ !~ /dev/***, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_triplestar_matches_basename_with_slash_and_glob() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/*/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev/")),
            Some(Action::Allow),
            "/dev/ !~ /*/***, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_triplestar_matches_pathname_with_literal() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/dev/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev/null")),
            Some(Action::Allow),
            "/dev/null !~ /dev/***, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_glob_triplestar_matches_pathname_with_glob() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        sandbox.config("allow/read+/*/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/dev/null")),
            Some(Action::Allow),
            "/dev/null !~ /*/***, {sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_access_last_matching_rule_wins() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/read:on")?;

        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );
        sandbox.config("allow/read+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/read+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("allow/read+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/read+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("deny/read-/etc/passwd")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("allow/read-/etc/passwd")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_READ, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );

        assert_eq!(
            sandbox.match_action(Capability::CAP_WRITE, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );
        sandbox.config("allow/write+/etc/**")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WRITE, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/write+/etc/**")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WRITE, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("allow/write+/etc/**")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WRITE, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/write+/etc/**")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WRITE, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("deny/write-/etc/**")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_WRITE, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("allow/write-/etc/**")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_WRITE, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );

        assert_eq!(
            sandbox.match_action(Capability::CAP_EXEC, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );
        sandbox.config("allow/exec+/etc/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_EXEC, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/exec+/etc/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_EXEC, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("allow/exec+/etc/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_EXEC, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/exec+/etc/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_EXEC, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("deny/exec-/etc/***")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_EXEC, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("allow/exec-/etc/***")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_EXEC, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );

        assert_eq!(
            sandbox.match_action(Capability::CAP_WALK, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );
        sandbox.config("allow/walk+/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WALK, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/walk+/etc/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WALK, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("allow/walk+/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WALK, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/walk+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WALK, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("deny/walk-/etc/***")?;
        sandbox.config("deny/walk-/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_WALK, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("allow/walk-/***")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_WALK, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );

        assert_eq!(
            sandbox.match_action(Capability::CAP_STAT, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );
        sandbox.config("allow/stat+/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_STAT, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/stat+/etc/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_STAT, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("allow/stat+/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_STAT, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/stat+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_STAT, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("deny/stat-/etc/***")?;
        sandbox.config("deny/stat-/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_STAT, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("allow/stat-/***")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_STAT, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );

        assert_eq!(
            sandbox.match_action(Capability::CAP_NET_BIND, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );
        sandbox.config("allow/net/bind+/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_NET_BIND, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/net/bind+/etc/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_NET_BIND, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("allow/net/bind+/***")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_NET_BIND, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/net/bind+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_NET_BIND, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("deny/net/bind-/etc/***")?;
        sandbox.config("deny/net/bind-/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(Capability::CAP_NET_BIND, &XPath::from_bytes(b"/etc/passwd")),
            Some(Action::Allow),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("allow/net/bind-/***")?;
        }
        assert_eq!(
            sandbox.match_action(Capability::CAP_NET_BIND, &XPath::from_bytes(b"/etc/passwd")),
            None,
            "{sandbox}"
        );

        assert_eq!(
            sandbox.match_action(
                Capability::CAP_NET_CONNECT,
                &XPath::from_bytes(b"/etc/passwd")
            ),
            None,
            "{sandbox}"
        );
        sandbox.config("allow/net/connect+/***")?;
        assert_eq!(
            sandbox.match_action(
                Capability::CAP_NET_CONNECT,
                &XPath::from_bytes(b"/etc/passwd")
            ),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/net/connect+/etc/***")?;
        assert_eq!(
            sandbox.match_action(
                Capability::CAP_NET_CONNECT,
                &XPath::from_bytes(b"/etc/passwd")
            ),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("allow/net/connect+/***")?;
        assert_eq!(
            sandbox.match_action(
                Capability::CAP_NET_CONNECT,
                &XPath::from_bytes(b"/etc/passwd")
            ),
            Some(Action::Allow),
            "{sandbox}"
        );
        sandbox.config("deny/net/connect+/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(
                Capability::CAP_NET_CONNECT,
                &XPath::from_bytes(b"/etc/passwd")
            ),
            Some(Action::Deny),
            "{sandbox}"
        );
        sandbox.config("deny/net/connect-/etc/***")?;
        sandbox.config("deny/net/connect-/etc/passwd")?;
        assert_eq!(
            sandbox.match_action(
                Capability::CAP_NET_CONNECT,
                &XPath::from_bytes(b"/etc/passwd")
            ),
            Some(Action::Allow),
            "{sandbox}"
        );
        for _ in 0..2 {
            sandbox.config("allow/net/connect-/***")?;
        }
        assert_eq!(
            sandbox.match_action(
                Capability::CAP_NET_CONNECT,
                &XPath::from_bytes(b"/etc/passwd")
            ),
            None,
            "{sandbox}"
        );

        Ok(())
    }

    #[test]
    fn sandbox_check_filter_ip_port_range() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        sandbox.config("sandbox/net:on")?;
        sandbox.config("allow/net/connect+any!0")?;

        let addr = "127.0.0.1".parse::<IpAddr>().unwrap();
        assert_eq!(
            sandbox.check_ip(Capability::CAP_NET_CONNECT, addr, 0),
            (Action::Allow, true)
        );
        for port in 1..=65535 {
            assert_eq!(
                sandbox.check_ip(Capability::CAP_NET_CONNECT, addr, port),
                (Action::Deny, false),
                "{addr}!{port} {sandbox}"
            );
        }

        sandbox.config("filter/net/connect+any!1-65535")?;
        assert_eq!(
            sandbox.check_ip(Capability::CAP_NET_CONNECT, addr, 0),
            (Action::Allow, true)
        );
        for port in 1..=65535 {
            assert_eq!(
                sandbox.check_ip(Capability::CAP_NET_CONNECT, addr, port),
                (Action::Deny, true),
                "{addr}!{port} {sandbox}"
            );
        }

        Ok(())
    }

    #[test]
    fn sandbox_check_netlink_01() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(
            sandbox.netlink_families.is_empty(),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );

        sandbox.config("allow/net/link+route")?;
        assert!(
            !sandbox.netlink_families.is_empty(),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );
        assert!(
            sandbox
                .netlink_families
                .contains(NetlinkFamily::NETLINK_ROUTE),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );

        Ok(())
    }

    #[test]
    fn sandbox_check_netlink_02() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(
            sandbox.netlink_families.is_empty(),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );

        sandbox.config("allow/net/link+route,crypto,ecryptfs,inet_diag")?;
        sandbox.config("allow/net/link-ecryptfs,sock_diag")?;
        assert!(
            !sandbox.netlink_families.is_empty(),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );
        assert!(
            sandbox
                .netlink_families
                .contains(NetlinkFamily::NETLINK_ROUTE),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );
        assert!(
            sandbox
                .netlink_families
                .contains(NetlinkFamily::NETLINK_CRYPTO),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );
        assert!(
            !sandbox
                .netlink_families
                .contains(NetlinkFamily::NETLINK_ECRYPTFS),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );
        assert!(
            !sandbox
                .netlink_families
                .contains(NetlinkFamily::NETLINK_SOCK_DIAG),
            "netlink_families:{}",
            sandbox.netlink_families.bits()
        );

        Ok(())
    }

    #[test]
    fn sandbox_check_root() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("root:"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("root:/../escape/me"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("root:relative"), Err(Errno::EINVAL));

        assert_eq!(sandbox.config("root:tmpfs"), Ok(()));
        assert_eq!(sandbox.root, Some(XPathBuf::from("tmpfs")));

        assert_eq!(sandbox.config("root:none"), Ok(()));
        assert_eq!(sandbox.root, None);

        assert_eq!(sandbox.config("root:/lol"), Ok(()));
        assert_eq!(sandbox.root, Some(XPathBuf::from("/lol")));

        assert_eq!(sandbox.config("root:off"), Ok(()));
        assert_eq!(sandbox.root, None);

        sandbox.oci = true;
        assert_eq!(sandbox.config("root:tmpfs"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("root:/lol"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("root:none"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("root:off"), Err(Errno::EOPNOTSUPP));

        Ok(())
    }

    #[test]
    fn sandbox_config_ipc() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.ipc, None);

        sandbox.config("ipc:/foo")?;
        assert_eq!(sandbox.ipc, Some(XPathBuf::from("/foo")));

        sandbox.config("ipc:none")?;
        assert_eq!(sandbox.ipc, None);

        sandbox.config("ipc:@foo")?;
        assert_eq!(sandbox.ipc, Some(XPathBuf::from("@foo")));

        sandbox.config("ipc:off")?;
        assert_eq!(sandbox.ipc, None);

        assert_eq!(sandbox.config("ipc:"), Err(Errno::EINVAL));
        assert_eq!(sandbox.ipc, None);

        assert_eq!(sandbox.config("ipc:foo"), Ok(()));
        assert_eq!(sandbox.ipc, Some(XPathBuf::from("foo")));
        sandbox.config("ipc:off")?;
        assert_eq!(sandbox.ipc, None);

        sandbox.oci = true;
        assert_eq!(sandbox.config("ipc:/foo"), Err(Errno::EOPNOTSUPP));
        assert_eq!(sandbox.config("ipc:@foo"), Err(Errno::EOPNOTSUPP));
        sandbox.config("ipc:none")?;
        sandbox.config("ipc:off")?;
        assert_eq!(sandbox.ipc, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_env() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("setenv!SYD_=1"), Err(Errno::EPERM));
        assert_eq!(sandbox.config("setenv!SYD_X=1"), Err(Errno::EPERM));
        assert_eq!(sandbox.config("setenv!SYD_LOG_FD=1"), Err(Errno::EPERM));
        assert_eq!(sandbox.config("unsetenv!SYD_"), Err(Errno::EPERM));
        assert_eq!(sandbox.config("unsetenv!SYD_X"), Err(Errno::EPERM));
        assert_eq!(sandbox.config("unsetenv!SYD_LOG_FD"), Err(Errno::EPERM));

        Ok(())
    }

    #[test]
    fn test_check_ioctl_allow_deny_precedence() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let req = 0x5401;

        // Initial state: Blacklist mode (CAP_IOCTL absent).
        // Default state is Whitelist mode, so we must turn it off.
        sandbox.config("sandbox/ioctl:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_IOCTL));
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Allow);

        // Explicit Allow
        sandbox.config("allow/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Allow);

        // Explicit Deny overrides Allow (Last Match Wins in config sequence).
        sandbox.config("deny/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Deny);

        // Re-allow
        sandbox.config("allow/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Allow);

        Ok(())
    }

    #[test]
    fn test_check_ioctl_whitelist_mode_default_deny() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let req = 0x5401;

        // Enable Whitelist mode
        sandbox.config("sandbox/ioctl:on")?;
        assert!(sandbox.state.contains(Capability::CAP_IOCTL));

        // Set Default Action to Deny
        sandbox.config("default/ioctl:deny")?;

        // Unknown -> Default (Deny)
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Deny);

        // Explicit Allow -> Allow
        sandbox.config("allow/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Allow);

        // Explicit Deny -> Deny
        sandbox.config("deny/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Deny);

        Ok(())
    }

    #[test]
    fn test_check_ioctl_blacklist_mode_explicit_deny() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let req = 0x5401;

        // Enable Blacklist mode
        sandbox.config("sandbox/ioctl:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_IOCTL));

        // Unknown -> Allow (Blacklist default)
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Allow);

        // Explicit Deny -> Deny (CRITICAL FIX CHECK)
        // Explicit deny returns Action::Deny.
        sandbox.config("deny/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Deny);

        // Explicit Allow -> Allow
        sandbox.config("allow/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Allow);

        Ok(())
    }

    #[test]
    fn test_check_ioctl_whitelist_mode_default_allow() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let req = 0x5401;

        // Whitelist mode + Default Allow
        sandbox.config("sandbox/ioctl:on")?;
        sandbox.config("default/ioctl:allow")?;

        // Unknown -> Default (Allow)
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Allow);

        // Explicit Deny -> Deny
        sandbox.config("deny/ioctl+0x5401")?;
        assert_eq!(sandbox.check_ioctl(req, ScmpArch::native()), Action::Deny);

        Ok(())
    }

    #[test]
    fn sandbox_config_rlimit_1() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.config("rlimit/as:2M")?;
        assert_eq!(sandbox.rlimit_as, Some(2 * 1024 * 1024));

        sandbox.config("rlimit/core:1G")?;
        assert_eq!(sandbox.rlimit_core, Some(1024 * 1024 * 1024));

        sandbox.config("rlimit/cpu:10s")?;
        assert_eq!(sandbox.rlimit_cpu, Some(10));
        sandbox.config("rlimit/cpu:1m")?;
        assert_eq!(sandbox.rlimit_cpu, Some(60));

        sandbox.config("rlimit/data:512K")?;
        assert_eq!(sandbox.rlimit_data, Some(512 * 1024));

        sandbox.config("rlimit/fsize:100")?;
        assert_eq!(sandbox.rlimit_fsize, Some(100));

        sandbox.config("rlimit/nice:-5")?;
        assert_eq!(sandbox.rlimit_nice, Some(25));
        sandbox.config("rlimit/nice:10")?;
        assert_eq!(sandbox.rlimit_nice, Some(10));

        sandbox.config("rlimit/nofile:1024")?;
        assert_eq!(sandbox.rlimit_nofile, Some(1024));

        sandbox.config("rlimit/nproc:100")?;
        assert_eq!(sandbox.rlimit_nproc, Some(100));

        sandbox.config("rlimit/rtprio:50")?;
        assert_eq!(sandbox.rlimit_rtprio, Some(50));

        sandbox.config("rlimit/rttime:1s")?;
        assert_eq!(sandbox.rlimit_rttime, Some(1_000_000));

        Ok(())
    }

    #[test]
    fn sandbox_config_rlimit_2() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        // inf/none/off checks
        sandbox.config("rlimit/as:inf")?;
        assert_eq!(sandbox.rlimit_as, Some(RLIM_INFINITY));
        sandbox.config("rlimit/as:none")?;
        assert_eq!(sandbox.rlimit_as, None);
        sandbox.config("rlimit/as:off")?;
        assert_eq!(sandbox.rlimit_as, None);

        sandbox.config("rlimit/cpu:inf")?;
        assert_eq!(sandbox.rlimit_cpu, Some(RLIM_INFINITY));
        sandbox.config("rlimit/cpu:off")?;
        assert_eq!(sandbox.rlimit_cpu, None);

        sandbox.config("rlimit/nice:inf")?;
        assert_eq!(sandbox.rlimit_nice, Some(RLIM_INFINITY));
        sandbox.config("rlimit/nice:none")?;
        assert_eq!(sandbox.rlimit_nice, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_rlimit_3() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.config("rlimit/as:invalid"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("rlimit/cpu:invalid"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("rlimit/nice:invalid"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("rlimit/nice:100"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("rlimit/nice:-100"), Err(Errno::EINVAL));

        Ok(())
    }

    #[test]
    fn sandbox_config_passenv_1() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let pass = |sandbox: &Sandbox, var: &str| -> bool {
            sandbox
                .pass_env
                .as_ref()
                .map(|set| set.contains(OsStr::new(var)))
                .unwrap_or(false)
        };

        // passenv+
        sandbox.config("passenv+HOME")?;
        assert!(pass(&sandbox, "HOME"));

        // Comma separated.
        sandbox.config("passenv+USER,TERM")?;
        assert!(pass(&sandbox, "USER"));
        assert!(pass(&sandbox, "TERM"));

        Ok(())
    }

    #[test]
    fn sandbox_config_passenv_2() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        let pass = |sandbox: &Sandbox, var: &str| -> bool {
            sandbox
                .pass_env
                .as_ref()
                .map(|set| set.contains(OsStr::new(var)))
                .unwrap_or(false)
        };

        sandbox.config("passenv+HOME,USER,TERM")?;
        assert!(pass(&sandbox, "HOME"));
        assert!(pass(&sandbox, "USER"));
        assert!(pass(&sandbox, "TERM"));

        // passenv-
        sandbox.config("passenv-HOME")?;
        assert!(!pass(&sandbox, "HOME"));
        assert!(pass(&sandbox, "USER"));

        // passenv^
        sandbox.config("passenv^USER")?;
        assert!(!pass(&sandbox, "USER"));
        assert!(pass(&sandbox, "TERM"));

        Ok(())
    }

    #[test]
    fn sandbox_config_passenv_3() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        // Check SYD_ prefix denial.
        assert_eq!(sandbox.config("passenv+SYD_SECRET"), Err(Errno::EPERM));

        // Check empty variable.
        assert_eq!(sandbox.config("passenv+"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("passenv+,"), Err(Errno::EINVAL));

        // Check oversized variable.
        let var = "A".repeat(PATH_MAX + 1);
        assert_eq!(
            sandbox.config(&format!("passenv+{var}")),
            Err(Errno::ENAMETOOLONG)
        );

        Ok(())
    }
}
