//
// Syd: rock-solid application kernel
// src/sandbox.rs: Sandbox configuration
//
// Copyright (c) 2023, 2024, 2025 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
//
// SPDX-License-Identifier: GPL-3.0

use std::{
    borrow::Cow,
    clone::Clone,
    cmp::Ordering,
    collections::{HashMap, HashSet, VecDeque},
    env, fmt,
    fs::File,
    io::{BufRead, BufReader, Read},
    net::{IpAddr, Ipv4Addr, Ipv6Addr},
    ops::{Deref, DerefMut, RangeInclusive},
    os::{
        fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd},
        unix::process::CommandExt,
    },
    process::{Command, Stdio},
    str::FromStr,
    sync::{Arc, Once, RwLockReadGuard, RwLockWriteGuard},
    time::Duration,
};

use ahash::RandomState;
use bitflags::bitflags;
use btoi::btoi;
use constant_time_eq::constant_time_eq;
use expiringmap::ExpiringMap;
use hex::{DisplayHex, FromHex};
use indexmap::IndexSet;
use ipnet::{IpNet, Ipv4Net, Ipv6Net};
use iprange::IpRange;
use lexis::ToName;
use memchr::{
    arch::all::{is_equal, is_prefix, is_suffix},
    memmem,
};
use nix::{
    errno::Errno,
    fcntl::{openat2, OFlag, OpenHow, ResolveFlag},
    mount::MsFlags,
    sched::CloneFlags,
    sys::{
        signal::Signal,
        socket::UnixAddr,
        stat::{umask, Mode, SFlag},
    },
    unistd::{getgroups, getpid, setsid, ttyname, Gid, Pid, Uid},
    NixPath,
};
#[cfg(feature = "oci")]
use oci_spec::runtime::Spec;
use once_cell::sync::Lazy;
use regex::{Captures, Regex, RegexBuilder};
use serde::{
    ser::{SerializeMap, SerializeSeq, SerializeStruct},
    Serialize, Serializer,
};

use crate::{
    compat::{fstatx, statx, STATX_INO, STATX_MODE, STATX_UID},
    config::*,
    dns::resolve_rand,
    err::{err2no, SydError, SydResult},
    error, extend_ioctl,
    fs::{duprand, retry_on_eintr, safe_open, safe_open_abs, safe_open_path, FileInformation},
    hash::{HashAlgorithm, Key, Secret, KEY_SIZE},
    human_size, info, log_enabled, ns_enabled, parse_group, parse_user,
    path::{XPath, XPathBuf},
    pool::WorkerCache,
    proc::proc_unix_get_inodes,
    syslog::LogLevel,
    wildmatch::{get_prefix, globmatch, is_literal, litmatch, MatchMethod},
    wordexp::WordExp,
    ScmpNotifReq, SydMsFlags, CLONE_NEWTIME, NAMESPACE_FLAGS_ALL,
};

const LINE_MAX: usize = 4096;
const PORT_MIN: u16 = 0;
const PORT_MAX: u16 = 0xFFFF;

static RE_BIND: Lazy<Regex> = Lazy::new(|| {
    #[allow(clippy::disallowed_methods)]
    RegexBuilder::new(
        r"
        \A
        bind
        (?P<mod>[-+^])
        (?P<src>[^:]+)
        :
        (?P<dst>[^:]+)
        (?::
            (?P<opt>([^,]+)(,[^,]+)*)
        )?
        \z
    ",
    )
    .ignore_whitespace(true)
    .build()
    .expect("Invalid bind mount regex, please file a bug!")
});

static RE_FORCE: Lazy<Regex> = Lazy::new(|| {
    #[allow(clippy::disallowed_methods)]
    RegexBuilder::new(
        r"
        \A
        force
        (?P<mod>[-+^])
        (?P<src>/[^:]*)?
        (?:
            :
            (?P<key>([0-9a-fA-F]{8}|[0-9a-fA-F]{16}|[0-9a-fA-F]{32}|[0-9a-fA-F]{40}|[0-9a-fA-F]{64}|[0-9a-fA-F]{96}|[0-9a-fA-F]{128}))
            (:(?P<act>warn|filter|deny|panic|stop|abort|kill|exit))?
        )?
        \z
    ",
    )
    .ignore_whitespace(true)
    .build()
    .expect("Invalid integrity force regex, please file a bug!")
});

static RE_SETID_0: Lazy<Regex> = Lazy::new(|| {
    #[allow(clippy::disallowed_methods)]
    RegexBuilder::new(
        r"
        \A
        set(?P<id>[ug])id
        (?P<mod>[-+])
        (?P<src>[^:]+)
        :
        (?P<dst>[^:]+)
        \z
    ",
    )
    .ignore_whitespace(true)
    .build()
    .expect("Invalid integrity setid-0 regex, please file a bug!")
});

static RE_SETID_1: Lazy<Regex> = Lazy::new(|| {
    #[allow(clippy::disallowed_methods)]
    RegexBuilder::new(
        r"
        \A
        set(?P<id>[ug])id
        (?P<mod>\^)
        (?P<src>[^:]+)?
        \z
    ",
    )
    .ignore_whitespace(true)
    .build()
    .expect("Invalid integrity setid-1 regex, please file a bug!")
});

static RE_RULE: Lazy<Regex> = Lazy::new(|| {
    #[allow(clippy::disallowed_methods)]
    RegexBuilder::new(
        r"
        \A
        (
            # We have an action with a capability.
            (?P<act>
                allow |
                deny |
                filter |
                warn |
                stop |
                abort |
                kill |
                panic |
                exit
            )/
            (
                # Match combinations of read, write, exec, stat, ioctl, ...
                # Also match `all' as a placeholder for everything.
                (?P<cap_all>all) |
                (?P<cap_many>
                    (
                        stat |
                        read |
                        write |
                        exec |
                        ioctl |
                        create |
                        delete |
                        rename |
                        symlink |
                        truncate |
                        chdir |
                        readdir |
                        mkdir |
                        chown |
                        chgrp |
                        chmod |
                        chattr |
                        chroot |
                        utime |
                        mkdev |
                        mkfifo |
                        mktemp
                    )
                    (,
                        (
                            stat |
                            read |
                            write |
                            exec |
                            ioctl |
                            create |
                            delete |
                            rename |
                            symlink |
                            truncate |
                            chdir |
                            readdir |
                            mkdir |
                            chown |
                            chgrp |
                            chmod |
                            chattr |
                            chroot |
                            utime |
                            mkdev |
                            mkfifo |
                            mktemp
                        )
                    )*
                ) |
                # Other capabilities, not allowing combinations.
                (?P<cap_single>
                    lock/read |
                    lock/write |
                    lock/bind |
                    lock/connect |
                    net/bind |
                    net/connect |
                    net/sendfd
                )
            )
        )
        (?P<mod>[-+:^])
        (
            (?P<addr>[A-Fa-f0-9:\.]+(/[0-9]+)?[!@][0-9]+(-[0-9]+)?) |
            (?P<path>.+)
        )
        \z
    ",
    )
    .ignore_whitespace(true)
    .build()
    .expect("Invalid sandbox rule regex, please file a bug!")
});

static RE_NETALIAS: Lazy<Regex> = Lazy::new(|| {
    #[allow(clippy::disallowed_methods)]
    RegexBuilder::new(
        r"
        \A
        (?P<command>
            (
                allow |
                deny |
                filter |
                warn |
                stop |
                abort |
                kill |
                panic |
                exit
            )
            /net/
            (
                bind |
                connect |
                sendfd
            )
            [-+^]
            # SAFETY: Every item in the regex group `alias' below,
            # must have a corresponding item in the MAP_NETALIAS hash map!
            (?P<alias>
                ([aA][nN][yY][46]?) |
                ([lL][oO][cC][aA][lL][46]?) |
                ([lL][oO][oO][pP][bB][aA][cC][kK][46]?) |
                ([lL][iI][nN][kK][lL][oO][cC][aA][lL][46]?)
            )
            [!@]
            [0-9]+
            (-[0-9]+)?
        )
        \z
    ",
    )
    .ignore_whitespace(true)
    .build()
    .expect("Invalid network alias regex, please file a bug!")
});

type AliasMap<'a> = HashMap<&'a str, Vec<&'a str>, RandomState>;
static MAP_NETALIAS: Lazy<AliasMap> = Lazy::new(|| {
    let mut map = HashMap::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
});

static RE_RULE_NETLINK: Lazy<Regex> = Lazy::new(|| {
    #[allow(clippy::disallowed_methods)]
    RegexBuilder::new(
        r"
        \A
        allow/net/link
        (
            (?P<clr>^) |
            (
                ((?P<add>[+])|(?P<del>[-]))
                (?P<fml>
                    (
                        route |
                        usersock |
                        firewall |
                        inet_diag |
                        sock_diag |
                        nflog |
                        xfrm |
                        selinux |
                        iscsi |
                        audit |
                        fib_lookup |
                        connector |
                        netfilter |
                        ip6_fw |
                        dnrtmsg |
                        kobject_uevent |
                        generic |
                        scsitransport |
                        ecryptfs |
                        rdma |
                        crypto
                    )
                    (,
                        (
                            route |
                            usersock |
                            firewall |
                            inet_diag |
                            sock_diag |
                            nflog |
                            xfrm |
                            selinux |
                            iscsi |
                            audit |
                            fib_lookup |
                            connector |
                            netfilter |
                            ip6_fw |
                            dnrtmsg |
                            kobject_uevent |
                            generic |
                            scsitransport |
                            ecryptfs |
                            rdma |
                            crypto
                        )
                    )*
                )
            )
        )
        \z
    ",
    )
    .ignore_whitespace(true)
    .build()
    .expect("Invalid sandbox rule regex, please file a bug!")
});

const ROOT_UID: Uid = Uid::from_raw(0);
const ROOT_GID: Gid = Gid::from_raw(0);

#[inline]
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),
    }
}

type LandlockRules = (
    Vec<XPathBuf>,
    Vec<XPathBuf>,
    Vec<RangeInclusive<u16>>,
    Vec<RangeInclusive<u16>>,
);

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(',') {
            // Let's be as lax as possible but not more.
            let family = family.trim();
            if family.is_empty() {
                continue;
            }
            families |= match family.to_ascii_lowercase().as_str() {
                "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 {
        IntegrityError::Sys(errno)
    }
}

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

/// 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
    /// kernel is going to ignore other options.
    pub opt: MsFlags,
    /// Optional filesystem specific data, useful for tmpfs.
    pub dat: Option<XPathBuf>,
}

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 = SydMsFlags(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(XPath::from_bytes(b"none"))
        )
    }
}

impl TryFrom<&Captures<'_>> for BindMount {
    type Error = Errno;

    fn try_from(captures: &Captures) -> Result<Self, Self::Error> {
        let src = &captures["src"];
        let dst = &captures["dst"];

        let src = XPathBuf::from(src);
        let dst = XPathBuf::from(dst);
        let mut opt = MsFlags::empty();
        let mut dat = Vec::new();

        // SAFETY:
        // 1. Deny relative destination paths.
        // 2. Deny ../ traversal in bind paths.
        if dst.is_relative() || src.has_parent_dot() || dst.has_parent_dot() {
            return Err(Errno::EINVAL);
        }

        if let Some(opt_match) = captures.name("opt") {
            for flag in opt_match.as_str().split(',') {
                match SydMsFlags::from_name(flag) {
                    Some(flag) => opt |= flag.0,
                    None => {
                        if !dat.is_empty() {
                            // Separate unrecognized flags with a comma
                            dat.push(b',');
                        }
                        dat.extend_from_slice(flag.as_bytes());
                    }
                }
            }
        }

        let dat = if dat.is_empty() {
            None
        } else {
            Some(dat.into())
        };

        Ok(Self { src, dst, opt, dat })
    }
}

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 SydMsFlags
        let syd_flags = SydMsFlags(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
    #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
    pub struct Capability: u64 {
        /// List capability
        const CAP_STAT = 1 << 0;
        /// Read capability
        const CAP_READ = 1 << 1;
        /// Write capability
        const CAP_WRITE = 1 << 2;
        /// Execute capability
        const CAP_EXEC = 1 << 3;
        /// Ioctl capability
        const CAP_IOCTL = 1 << 4;
        /// Create capability
        const CAP_CREATE = 1 << 5;
        /// Delete capability
        const CAP_DELETE = 1 << 6;
        /// Rename capability
        const CAP_RENAME = 1 << 7;
        /// Symlink capability
        const CAP_SYMLINK = 1 << 8;
        /// Truncate capability
        const CAP_TRUNCATE = 1 << 9;
        /// Chdir capability
        const CAP_CHDIR = 1 << 10;
        /// List-directory capability
        const CAP_READDIR = 1 << 11;
        /// Make-directory capability
        const CAP_MKDIR = 1 << 12;
        /// Change owner capability
        const CAP_CHOWN = 1 << 13;
        /// Change group capability
        const CAP_CHGRP = 1 << 14;
        /// Change mode capability
        const CAP_CHMOD = 1 << 15;
        /// Change attribute capability
        const CAP_CHATTR = 1 << 16;
        /// Chroot capability
        const CAP_CHROOT = 1 << 17;
        /// Change file last access and modification time capability
        const CAP_UTIME = 1 << 18;
        /// Create character device capability
        const CAP_MKDEV = 1 << 19;
        /// Create named pipe capability
        const CAP_MKFIFO = 1 << 20;
        /// Temporary file capability
        const CAP_MKTEMP = 1 << 21;
        /// Network bind capability
        const CAP_NET_BIND = 1 << 22;
        /// Network connect capability
        const CAP_NET_CONNECT = 1 << 23;
        /// Network sendfd capability
        const CAP_NET_SENDFD = 1 << 24;
        /// Memory capability
        const CAP_MEM = 1 << 25;
        /// Pid capability
        const CAP_PID = 1 << 26;
        /// Force capability
        const CAP_FORCE = 1 << 27;
        /// Trusted Path Execution (TPE) capability
        const CAP_TPE = 1 << 28;
        /// Proxy sandboxing
        const CAP_PROXY = 1 << 29;
        /// Landlock read capability
        const CAP_LOCK_RO = 1 << 30;
        /// Landlock read-write capability
        const CAP_LOCK_RW = 1 << 31;
        /// Landlock bind capability
        const CAP_LOCK_BIND = 1 << 32;
        /// Landlock connect capability
        const CAP_LOCK_CONNECT = 1 << 33;
        /// Landlock filesystem capabilities.
        const CAP_LOCK_FS = Self::CAP_LOCK_RO.bits() | Self::CAP_LOCK_RW.bits();
        /// Landlock network capabilities.
        const CAP_LOCK_NET = Self::CAP_LOCK_BIND.bits() | Self::CAP_LOCK_CONNECT.bits();
        /// Landlock capabilities.
        const CAP_LOCK = Self::CAP_LOCK_RO.bits() | Self::CAP_LOCK_RW.bits() | Self::CAP_LOCK_BIND.bits() | Self::CAP_LOCK_CONNECT.bits();

        /// 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
        const CAP_GLOB =
            Self::CAP_STAT.bits() |
            Self::CAP_READ.bits() |
            Self::CAP_WRITE.bits() |
            Self::CAP_EXEC.bits() |
            Self::CAP_IOCTL.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_CHOWN.bits() |
            Self::CAP_CHGRP.bits() |
            Self::CAP_CHMOD.bits() |
            Self::CAP_CHATTR.bits() |
            Self::CAP_CHROOT.bits() |
            Self::CAP_UTIME.bits() |
            Self::CAP_MKDEV.bits() |
            Self::CAP_MKFIFO.bits() |
            Self::CAP_MKTEMP.bits() |
            Self::CAP_NET_CONNECT.bits() |
            Self::CAP_NET_BIND.bits() |
            Self::CAP_NET_SENDFD.bits();

        /// All capabilities with path rules
        const CAP_RULE =
            Self::CAP_GLOB.bits() |
            Self::CAP_LOCK.bits();

        /// All capabilities with path check,
        /// except CAP_STAT which is treated differently
        /// because of Path Hiding.
        const CAP_PATH =
            Self::CAP_READ.bits() |
            Self::CAP_WRITE.bits() |
            Self::CAP_EXEC.bits() |
            Self::CAP_IOCTL.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_CHOWN.bits() |
            Self::CAP_CHGRP.bits() |
            Self::CAP_CHMOD.bits() |
            Self::CAP_CHATTR.bits() |
            Self::CAP_CHROOT.bits() |
            Self::CAP_UTIME.bits() |
            Self::CAP_MKDEV.bits() |
            Self::CAP_MKFIFO.bits() |
            Self::CAP_MKTEMP.bits() |
            Self::CAP_NET_CONNECT.bits() |
            Self::CAP_NET_BIND.bits() |
            Self::CAP_NET_SENDFD.bits();

        /// All capabilities that may write.
        /// Used by append-only checker.
        const CAP_WRSET =
            Self::CAP_WRITE.bits() |
            Self::CAP_IOCTL.bits() |
            Self::CAP_CREATE.bits() |
            Self::CAP_DELETE.bits() |
            Self::CAP_RENAME.bits() |
            Self::CAP_SYMLINK.bits() |
            Self::CAP_TRUNCATE.bits() |
            Self::CAP_MKDIR.bits() |
            Self::CAP_CHOWN.bits() |
            Self::CAP_CHGRP.bits() |
            Self::CAP_CHMOD.bits() |
            Self::CAP_CHATTR.bits() |
            Self::CAP_UTIME.bits() |
            Self::CAP_MKDEV.bits() |
            Self::CAP_MKFIFO.bits() |
            Self::CAP_MKTEMP.bits() |
            Self::CAP_NET_BIND.bits();
    }
}

impl Capability {
    /// Returns true if the Capability must be set at startup.
    pub fn is_startup(self) -> bool {
        self.intersects(Self::CAP_CRYPT | Self::CAP_PROXY | Self::CAP_LOCK)
    }

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

impl FromStr for Capability {
    type Err = Errno;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        let mut caps = Self::empty();
        for cap in value.split(',') {
            // Let's be as lax as possible but not more.
            let cap = cap.trim();
            if cap.is_empty() {
                continue;
            }
            caps |= match cap.to_ascii_lowercase().as_str() {
                "all" => Self::CAP_GLOB,
                "stat" => Self::CAP_STAT,
                "read" => Self::CAP_READ,
                "write" => Self::CAP_WRITE,
                "exec" => Self::CAP_EXEC,
                "ioctl" => Self::CAP_IOCTL,
                "create" => Self::CAP_CREATE,
                "delete" => Self::CAP_DELETE,
                "rename" => Self::CAP_RENAME,
                "symlink" => Self::CAP_SYMLINK,
                "truncate" => Self::CAP_TRUNCATE,
                "chdir" => Self::CAP_CHDIR,
                "readdir" => Self::CAP_READDIR,
                "mkdir" => Self::CAP_MKDIR,
                "chown" => Self::CAP_CHOWN,
                "chgrp" => Self::CAP_CHGRP,
                "chmod" => Self::CAP_CHMOD,
                "chattr" => Self::CAP_CHATTR,
                "chroot" => Self::CAP_CHROOT,
                "utime" => Self::CAP_UTIME,
                "mkdev" => Self::CAP_MKDEV,
                "mkfifo" => Self::CAP_MKFIFO,
                "mktemp" => Self::CAP_MKTEMP,
                "crypt" => Self::CAP_CRYPT,
                "force" => Self::CAP_FORCE,
                "lock" => Self::CAP_LOCK,
                "mem" => Self::CAP_MEM,
                "pid" => Self::CAP_PID,
                "proxy" => Self::CAP_PROXY,
                "tpe" => Self::CAP_TPE,
                "net" => Self::CAP_NET_BIND | Self::CAP_NET_CONNECT | Self::CAP_NET_SENDFD,
                /* Network sandboxing but only for one of Bind, Connect, SendFd */
                "net/bind" => Self::CAP_NET_BIND,
                "net/connect" => Self::CAP_NET_CONNECT,
                "net/sendfd" => Self::CAP_NET_SENDFD,
                _ => return Err(Errno::EINVAL),
            };
        }

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

#[allow(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_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_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_MKDEV) {
            capabilities.push("Mkdev");
        }
        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_MEM) {
            capabilities.push("Memory");
        }
        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("Landlock");
        }

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

impl Serialize for Capability {
    #[allow(clippy::cognitive_complexity)]
    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().to_ascii_lowercase()),
            n => serializer.serialize_seq(Some(n))?,
        };

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

        seq.end()
    }
}

impl From<&Captures<'_>> for Capability {
    fn from(captures: &Captures) -> Self {
        // Note, we do not use CAP_FORCE here.
        // Force rules are defined elsewhere.
        // We do not use CAP_PROXY here either,
        // it's irrelevant (has no rules).
        // We do not use CAP_MEM, CAP_PID, or
        // CAP_TPE either as they only have a
        // single default Action.
        if captures.name("cap_all").is_some() {
            // nice-to-have: deny/all+${HOME}/.ssh/***
            Self::CAP_GLOB
        } else if let Some(cap) = captures.name("cap_single") {
            match cap.as_str() {
                "lock/read" => Self::CAP_LOCK_RO,
                "lock/write" => Self::CAP_LOCK_RW,
                "lock/bind" => Self::CAP_LOCK_BIND,
                "lock/connect" => Self::CAP_LOCK_CONNECT,
                "net/bind" => Self::CAP_NET_BIND,
                "net/connect" => Self::CAP_NET_CONNECT,
                "net/sendfd" => Self::CAP_NET_SENDFD,
                _ => unreachable!(),
            }
        } else if let Some(caps) = captures.name("cap_many") {
            caps.as_str()
                .split(',')
                .map(|cap| match cap {
                    "stat" => Self::CAP_STAT,
                    "read" => Self::CAP_READ,
                    "write" => Self::CAP_WRITE,
                    "exec" => Self::CAP_EXEC,
                    "ioctl" => Self::CAP_IOCTL,
                    "create" => Self::CAP_CREATE,
                    "delete" => Self::CAP_DELETE,
                    "rename" => Self::CAP_RENAME,
                    "symlink" => Self::CAP_SYMLINK,
                    "truncate" => Self::CAP_TRUNCATE,
                    "chdir" => Self::CAP_CHDIR,
                    "readdir" => Self::CAP_READDIR,
                    "mkdir" => Self::CAP_MKDIR,
                    "chown" => Self::CAP_CHOWN,
                    "chgrp" => Self::CAP_CHGRP,
                    "chmod" => Self::CAP_CHMOD,
                    "chattr" => Self::CAP_CHATTR,
                    "chroot" => Self::CAP_CHROOT,
                    "utime" => Self::CAP_UTIME,
                    "mkdev" => Self::CAP_MKDEV,
                    "mkfifo" => Self::CAP_MKFIFO,
                    "mktemp" => Self::CAP_MKTEMP,
                    _ => unreachable!(),
                })
                .fold(Self::empty(), |acc, cap| acc | cap)
        } else {
            unreachable!("Invalid rule regex!");
        }
    }
}

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

    // Find out capabilities of the system call using the system call name and seccomp request.
    #[allow(clippy::cognitive_complexity)]
    #[inline]
    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),
            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_iter(name.as_bytes(), b"utime")
                .next()
                .is_some() =>
            {
                Ok(Self::CAP_UTIME)
            }
            name if memmem::find_iter(name.as_bytes(), b"chown")
                .next()
                .is_some() =>
            {
                Ok(Self::chown(syscall_name, req))
            }
            "open" | "openat" | "openat2" => unreachable!(),
            _ => Ok(Self::CAP_WRITE),
        }
    }
}

impl Capability {
    #[inline]
    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
    }

    #[inline]
    fn chmod(syscall_name: &str) -> bool {
        // chmod, fchmod, fchmodat or fchmodat2.
        memmem::find_iter(syscall_name.as_bytes(), b"chmod")
            .next()
            .is_some()
    }

    #[inline]
    fn chattr(syscall_name: &str) -> bool {
        // setxattr, setxattrat, fsetxattr, lsetxattr, removexattr,
        // removexattrat, fremovexattr, or lremovexattr.
        memmem::find_iter(syscall_name.as_bytes(), b"setxattr")
            .next()
            .is_some()
            || memmem::find_iter(syscall_name.as_bytes(), b"removexattr")
                .next()
                .is_some()
    }

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

    #[inline]
    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
        };
        #[allow(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 => {
                // SAFETY: Do not allow block-device creation.
                Err(Errno::EACCES)
            }
            SFlag::S_IFCHR => {
                // Character device.
                Ok(Self::CAP_MKDEV)
            }
            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),
        }
    }

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

    #[inline]
    fn stat(syscall_name: &str) -> bool {
        let name_bytes = syscall_name.as_bytes();

        STAT_SYSCALLS
            .binary_search_by(|probe| {
                let probe_bytes = probe.as_bytes();

                if is_equal(probe_bytes, name_bytes) {
                    Ordering::Equal
                } else {
                    probe_bytes.cmp(name_bytes)
                }
            })
            .is_ok()
    }

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

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

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

    #[inline]
    fn delete(syscall_name: &str) -> bool {
        let name_bytes = syscall_name.as_bytes();

        DELETE_SYSCALLS
            .binary_search_by(|probe| {
                let probe_bytes = probe.as_bytes();

                if is_equal(probe_bytes, name_bytes) {
                    Ordering::Equal
                } else {
                    probe_bytes.cmp(name_bytes)
                }
            })
            .is_ok()
    }

    #[inline]
    fn rename(syscall_name: &str) -> bool {
        let name_bytes = syscall_name.as_bytes();

        RENAME_SYSCALLS
            .binary_search_by(|probe| {
                let probe_bytes = probe.as_bytes();

                if is_equal(probe_bytes, name_bytes) {
                    Ordering::Equal
                } else {
                    probe_bytes.cmp(name_bytes)
                }
            })
            .is_ok()
    }

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

    #[inline]
    fn truncate(syscall_name: &str) -> bool {
        let name_bytes = syscall_name.as_bytes();

        TRUNCATE_SYSCALLS
            .binary_search_by(|probe| {
                let probe_bytes = probe.as_bytes();

                if is_equal(probe_bytes, name_bytes) {
                    Ordering::Equal
                } else {
                    probe_bytes.cmp(name_bytes)
                }
            })
            .is_ok()
    }

    #[inline]
    fn connect(syscall_name: &str) -> bool {
        let name_bytes = syscall_name.as_bytes();

        CONNECT_SYSCALLS
            .binary_search_by(|probe| {
                let probe_bytes = probe.as_bytes();

                if is_equal(probe_bytes, name_bytes) {
                    Ordering::Equal
                } else {
                    probe_bytes.cmp(name_bytes)
                }
            })
            .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;
        /// Apply CONTINUE on character devices rather than opening
        /// them in the Syd emulator thread and sending the file
        /// descriptor. This can be used as a workaround for character
        /// devices whose handling is per-process, e.g. /dev/kfd for
        /// AMD GPUs. Note, 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_CDEV = 1 << 2;
        /// 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 << 3;
        /// Allow execution of non-PIE binaries.
        const FL_ALLOW_UNSAFE_NOPIE = 1 << 4;
        /// Allow executable stack for ELF binaries.
        const FL_ALLOW_UNSAFE_STACK = 1 << 5;
        /// Disable SROP mitigations for {rt_,}sigreturn
        const FL_ALLOW_UNSAFE_SIGRETURN = 1 << 6;
        /// Deny execution of 32-bit ELF binaries.
        const FL_DENY_ELF32 = 1 << 7;
        /// Deny execution of dynamically linked binaries.
        const FL_DENY_ELF_DYNAMIC = 1 << 8;
        /// Deny execution of statically linked binaries.
        const FL_DENY_ELF_STATIC = 1 << 9;
        /// Deny execution of scripts using an interpreter via #!<path>.
        const FL_DENY_SCRIPT = 1 << 10;
        /// 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 << 11;
        /// Allow access to the Linux kernel crypto API
        const FL_ALLOW_SAFE_KCAPI = 1 << 12;
        /// Allow socket families which are unsupported
        const FL_ALLOW_UNSUPP_SOCKET = 1 << 13;
        /// Allow filenames with control characters in them.
        const FL_ALLOW_UNSAFE_FILENAME = 1 << 14;
        /// Allow secret memfds and executable memfds.
        const FL_ALLOW_UNSAFE_MEMFD = 1 << 15;
        /// Negate TPE GID logic.
        const FL_TPE_NEGATE = 1 << 16;
        /// Ensure TPE directory is root owned.
        const FL_TPE_ROOT_OWNED = 1 << 17;
        /// Ensure TPE directory is user owned.
        const FL_TPE_USER_OWNED = 1 << 18;
        /// Wait for all processes before exiting.
        const FL_EXIT_WAIT_ALL = 1 << 19;

        /// If set at startup, sets synchronous mode for seccomp-notify.
        const FL_SYNC_SCMP = 1 << 77;
        /// If set at startup, all id system calls return 0 in the sandbox.
        const FL_FAKE_ROOT = 1 << 78;
        /// If set at startup, root is mapped to current user in the user namespace.
        const FL_MAP_ROOT = 1 << 79;
        /// Lock personality(2) changes.
        const FL_LOCK_PERSONALITY = 1 << 80;
        /// Allow seccomp-bpf filters inside the sandbox.
        const FL_ALLOW_UNSAFE_CBPF = 1 << 81;
        /// Allow EBPF programs inside the sandbox.
        const FL_ALLOW_UNSAFE_EBPF = 1 << 82;
        /// Allow perf calls inside the sandbox.
        const FL_ALLOW_UNSAFE_PERF = 1 << 83;
        /// Allows unsafe exec calls with NULL as argv and envp arguments.
        const FL_ALLOW_UNSAFE_EXEC = 1 << 84;
        /// Allows unsafe ptrace calls.
        /// Disables {chdir,exec}-TOCTOU mitigator.
        /// Keeps the capability CAP_SYS_PTRACE.
        const FL_ALLOW_UNSAFE_PTRACE = 1 << 85;
        /// 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 << 86;
        /// Retain capability CAP_SETUID
        const FL_ALLOW_SAFE_SETUID = 1 << 87;
        /// Retain capability CAP_SETGID
        const FL_ALLOW_SAFE_SETGID = 1 << 88;
        /// Allow successful bind calls for subsequent connect calls
        const FL_ALLOW_SAFE_BIND = 1 << 89;
        /// Retain capability CAP_NET_BIND_SERVICE
        const FL_ALLOW_UNSAFE_BIND = 1 << 90;
        /// Retain capability CAP_CHOWN
        const FL_ALLOW_UNSAFE_CHOWN = 1 << 91;
        /// Make chroot(2) a no-op like pivot_root(2).
        const FL_ALLOW_UNSAFE_CHROOT = 1 << 92;
        /// Allow system calls for CPU emulation functionality
        const FL_ALLOW_UNSAFE_CPU = 1 << 93;
        /// Disable setting AT_SECURE at PTRACE_EVENT_EXEC boundary.
        const FL_ALLOW_UNSAFE_LIBC = 1 << 94;
        /// Allow Kernel keyring access.
        const FL_ALLOW_UNSAFE_KEYRING = 1 << 95;
        /// Allow unsafe memory manipulation.
        const FL_ALLOW_UNSAFE_MEMORY = 1 << 96;
        /// Allow system calls used for memory protection keys.
        const FL_ALLOW_UNSAFE_PKEY = 1 << 97;
        /// Retain _all_ Linux capabilities.
        const FL_ALLOW_UNSAFE_CAPS = 1 << 98;
        /// Allow unsafe environment variables.
        const FL_ALLOW_UNSAFE_ENV = 1 << 99;
        /// Allow unsafe socket families (RAW and PACKET).
        const FL_ALLOW_UNSAFE_SOCKET = 1 << 100;
        /// Allow unsafe syslog calls (reading /proc/kmsg etc.)
        const FL_ALLOW_UNSAFE_SYSLOG = 1 << 101;
        /// Allow unsafe msgsnd calls.
        const FL_ALLOW_UNSAFE_MSGSND = 1 << 102;
        /// Allow unsafe nice(2) calls.
        const FL_ALLOW_UNSAFE_NICE = 1 << 103;
        /// Allow unsafe prctl calls
        const FL_ALLOW_UNSAFE_PRCTL = 1 << 104;
        /// Allow unsafe prlimit calls
        const FL_ALLOW_UNSAFE_PRLIMIT = 1 << 105;
        /// Allow unsafe adjtimex and clock_adjtime calls,
        /// and keep the CAP_SYS_TIME capability.
        const FL_ALLOW_UNSAFE_TIME = 1 << 106;
        /// Allow the unsafe io-uring interface
        const FL_ALLOW_UNSAFE_IOURING = 1 << 107;
        /// Do not force specutlative execution mitigations
        const FL_ALLOW_UNSAFE_SPEC_EXEC = 1 << 108;
        /// Allow the unsafe sync(2) and syncfs(2) system calls.
        const FL_ALLOW_UNSAFE_SYNC = 1 << 109;
        /// Allow the unsafe sysinfo(2) system call.
        const FL_ALLOW_UNSAFE_SYSINFO = 1 << 110;
        /// Deny reading the timestamp counter (x86 only)
        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(CloneFlags::from_bits_retain(crate::CLONE_NEWTIME));
        }

        cflags
    }
}

impl fmt::Display for Flags {
    #[allow(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_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_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_EXEC) {
            flags.push("Allow Unsafe Exec");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_LIBC) {
            flags.push("Allow Unsafe Libc");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_KEYRING) {
            flags.push("Allow Unsafe Kernel keyring");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MEMORY) {
            flags.push("Allow Unsafe Memory");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PKEY) {
            flags.push("Allow Unsafe Memory Protection Keys");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CAPS) {
            flags.push("Allow Unsafe Capabilities");
        }
        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_MSGSND) {
            flags.push("Allow Unsafe MsgSnd");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NICE) {
            flags.push("Allow Unsafe Nice");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PRCTL) {
            flags.push("Allow Unsafe PRctl");
        }
        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_EXEC) {
            flags.push("Allow Unsafe Exec");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOPIE) {
            flags.push("Allow Unsafe No-PIE");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_STACK) {
            flags.push("Allow Unsafe Stack");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SIGRETURN) {
            flags.push("Allow Unsafe Signal Return");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_OPEN_PATH) {
            flags.push("Allow Unsafe O_PATH Open");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_OPEN_CDEV) {
            flags.push("Allow Unsafe Character Device Open");
        }
        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_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_MAGICLINKS) {
            flags.push("Allow Unsafe Magic Links");
        }
        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_SPEC_EXEC) {
            flags.push("Allow Unsafe Speculative Execution");
        }
        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_MEMFD) {
            flags.push("Allow Unsafe MemFD");
        }
        if self.contains(Flags::FL_DENY_DOTDOT) {
            flags.push("Deny DotDot");
        }
        if self.contains(Flags::FL_DENY_ELF32) {
            flags.push("Deny Elf32");
        }
        if self.contains(Flags::FL_DENY_ELF_DYNAMIC) {
            flags.push("Deny Dynamically Linked Elf");
        }
        if self.contains(Flags::FL_DENY_ELF_STATIC) {
            flags.push("Deny Statically Linked Elf");
        }
        if self.contains(Flags::FL_DENY_SCRIPT) {
            flags.push("Deny Script");
        }
        if self.contains(Flags::FL_DENY_TSC) {
            flags.push("Deny TSC");
        }
        if self.contains(Flags::FL_LOCK_PERSONALITY) {
            flags.push("Lock Personality");
        }

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

impl Serialize for Flags {
    #[allow(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(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_TIME) {
            flags.push("unshare-time");
        }
        if self.contains(Flags::FL_SYNC_SCMP) {
            flags.push("sync-scmp");
        }
        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_EXIT_WAIT_ALL) {
            flags.push("exit-wait-all");
        }
        if self.contains(Flags::FL_TPE_NEGATE) {
            flags.push("tpe-negate");
        }
        if self.contains(Flags::FL_TPE_ROOT_OWNED) {
            flags.push("tpe-root-owned");
        }
        if self.contains(Flags::FL_TPE_USER_OWNED) {
            flags.push("tpe-user-owned");
        }
        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_CPU) {
            flags.push("allow-unsafe-cpu");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_DUMPABLE) {
            flags.push("allow-unsafe-dumpable");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC) {
            flags.push("allow-unsafe-exec");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_LIBC) {
            flags.push("allow-unsafe-libc");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_KEYRING) {
            flags.push("allow-unsafe-keyring");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MEMORY) {
            flags.push("allow-unsafe-memory");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PKEY) {
            flags.push("allow-unsafe-pkey");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_CAPS) {
            flags.push("allow-unsafe-caps");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_ENV) {
            flags.push("allow-unsafe-env");
        }
        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-kcapi");
        }
        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-unsupp-socket");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SOCKET) {
            flags.push("allow-unsafe-socket");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SYSLOG) {
            flags.push("allow-unsafe-syslog");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_MSGSND) {
            flags.push("allow-unsafe-msgsnd");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NICE) {
            flags.push("allow-unsafe-nice");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PRCTL) {
            flags.push("allow-unsafe-prctl");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_PRLIMIT) {
            flags.push("allow-unsafe-prlimit");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_EXEC) {
            flags.push("allow-unsafe-exec");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_NOPIE) {
            flags.push("allow-unsafe-nopie");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_STACK) {
            flags.push("allow-unsafe-stack");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SIGRETURN) {
            flags.push("allow-unsafe-sigreturn");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_TIME) {
            flags.push("allow-unsafe-time");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_OPEN_PATH) {
            flags.push("allow-unsafe-open-path");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_OPEN_CDEV) {
            flags.push("allow-unsafe-open-cdev");
        }
        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_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_MAGICLINKS) {
            flags.push("allow-unsafe-magiclinks");
        }
        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-uring");
        }
        if self.contains(Flags::FL_ALLOW_UNSAFE_SPEC_EXEC) {
            flags.push("allow-unsafe-spec-exec");
        }
        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_MEMFD) {
            flags.push("allow-unsafe-memfd");
        }
        if self.contains(Flags::FL_DENY_DOTDOT) {
            flags.push("deny-dotdot");
        }
        if self.contains(Flags::FL_DENY_ELF32) {
            flags.push("deny-elf32");
        }
        if self.contains(Flags::FL_DENY_ELF_DYNAMIC) {
            flags.push("deny-elf-dynamic");
        }
        if self.contains(Flags::FL_DENY_ELF_STATIC) {
            flags.push("deny-elf-static");
        }
        if self.contains(Flags::FL_DENY_SCRIPT) {
            flags.push("deny-script");
        }
        if self.contains(Flags::FL_DENY_TSC) {
            flags.push("deny-tsc");
        }
        if self.contains(Flags::FL_LOCK_PERSONALITY) {
            flags.push("lock-personality");
        }

        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_UNSAFE_BIND
                | Self::FL_ALLOW_UNSAFE_CPU
                | Self::FL_ALLOW_UNSAFE_DUMPABLE
                | Self::FL_ALLOW_UNSAFE_EXEC
                | Self::FL_ALLOW_UNSAFE_LIBC
                | Self::FL_ALLOW_UNSAFE_KEYRING
                | Self::FL_ALLOW_UNSAFE_MEMORY
                | Self::FL_ALLOW_UNSAFE_PKEY
                | Self::FL_ALLOW_UNSAFE_CAPS
                | Self::FL_ALLOW_UNSAFE_CHOWN
                | Self::FL_ALLOW_UNSAFE_CHROOT
                | Self::FL_ALLOW_UNSAFE_ENV
                | Self::FL_ALLOW_SAFE_BIND
                | Self::FL_ALLOW_SAFE_SETUID
                | Self::FL_ALLOW_SAFE_SETGID
                | Self::FL_ALLOW_SAFE_SYSLOG
                | Self::FL_ALLOW_UNSAFE_MSGSND
                | Self::FL_ALLOW_UNSAFE_NICE
                | Self::FL_ALLOW_UNSAFE_SIGRETURN
                | Self::FL_ALLOW_UNSAFE_SOCKET
                | Self::FL_ALLOW_UNSAFE_SYSLOG
                | Self::FL_ALLOW_UNSAFE_PRCTL
                | Self::FL_ALLOW_UNSAFE_PRLIMIT
                | Self::FL_ALLOW_UNSAFE_EXEC
                | Self::FL_ALLOW_UNSAFE_CBPF
                | Self::FL_ALLOW_UNSAFE_EBPF
                | Self::FL_ALLOW_UNSAFE_PTRACE
                | Self::FL_ALLOW_UNSAFE_PERF
                | Self::FL_ALLOW_UNSAFE_TIME
                | Self::FL_ALLOW_UNSAFE_IOURING
                | Self::FL_ALLOW_UNSAFE_SPEC_EXEC
                | Self::FL_ALLOW_UNSAFE_SYNC
                | Self::FL_ALLOW_UNSAFE_SYSINFO
                | Self::FL_DENY_TSC
                | Self::FL_LOCK_PERSONALITY,
        )
    }

    #[allow(clippy::cognitive_complexity)]
    fn ns_from_str(value: &str, unsafe_: bool) -> Result<Self, Errno> {
        let mut flags = Flags::empty();
        for flag in value.split(',') {
            // Let's be as lax as possible but not more.
            let flag = flag.trim();
            if flag.is_empty() {
                continue;
            }
            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)
        }
    }
}

#[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, Eq, PartialEq)]
pub struct AddressPattern {
    addr: IpNet,
    port: Option<[u16; 2]>,
}

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[0] == ports[1] => write!(f, "{}!{}", self.addr, ports[0]),
            Some(ports) => write!(f, "{}!{}-{}", self.addr, ports[0], ports[1]),
        }
    }
}

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[0] == ports[1] => map.serialize_entry("port", &ports[0])?,
            Some(ports) => map.serialize_entry("port", &ports)?,
        };
        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, 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.
    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,
}

impl FromStr for Action {
    type Err = Errno;

    fn from_str(value: &str) -> Result<Self, Self::Err> {
        Ok(match value.to_ascii_lowercase().as_str() {
            "allow" => Action::Allow,
            "warn" => Action::Warn,
            "filter" => Action::Filter,
            "deny" => Action::Deny,
            "panic" => Action::Panic,
            "stop" => Action::Stop,
            "abort" => Action::Abort,
            "kill" => Action::Kill,
            "exit" => Action::Exit,
            _ => return Err(Errno::EINVAL),
        })
    }
}

impl fmt::Display for Action {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Action::Allow => write!(f, "Allow"),
            Action::Warn => write!(f, "Warn"),
            Action::Filter => write!(f, "Filter"),
            Action::Deny => write!(f, "Deny"),
            Action::Panic => write!(f, "Panic"),
            Action::Stop => write!(f, "Stop"),
            Action::Abort => write!(f, "Abort"),
            Action::Kill => write!(f, "Kill"),
            Action::Exit => write!(f, "Exit"),
        }
    }
}

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

impl From<&Captures<'_>> for Action {
    fn from(captures: &Captures) -> Self {
        if let Some(act) = captures.name("act") {
            Action::from_str(act.as_str()).unwrap_or(Action::default())
        } else {
            Action::default()
        }
    }
}

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, Eq, PartialEq)]
pub struct CidrRule {
    act: Action,
    cap: Capability,
    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: [u16; 2]) -> Self {
        let port = if port[0] == PORT_MIN && port[1] == 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: serde::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: serde::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: serde::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,
    /// Lock is set, sandbox commands are not allowed.
    Set,
}

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

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

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

/// Sandbox
#[allow(clippy::type_complexity)]
pub struct Sandbox {
    /// Sandbox options represented using a set of `Flag` flags.
    pub flags: Flags,

    /// Sandbox state represented using a set of `Capability` flags.
    pub state: 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(crate) verbose: bool,

    /// State of chroot.
    chroot: bool,

    // Estimated item capacities for path, address and fd caches.
    pub(crate) cache_path_cap: usize,
    pub(crate) cache_addr_cap: usize,

    // [inode,path] map of unix binds
    bind_map: HashMap<u64, UnixAddr, RandomState>,

    /// 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.
    fpid: RawFd,

    /// Change root to this directory on startup.
    pub root: Option<XPathBuf>,

    /// Mountpoint for the proc filesystem.
    pub proc: Option<XPathBuf>,

    /// Mount propagation flags.
    pub propagation: Option<MsFlags>,

    /// Hostname in UTS namespace.
    pub hostname: String,

    /// Domainname in UTS namespace.
    pub domainname: String,

    /// Timestamp for BOOTTIME in Time namespace.
    pub time: 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,

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

    /// 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,

    /// Default action for Read sandboxing.
    read_act: Action,

    /// Default action for Write sandboxing.
    write_act: Action,

    /// Default action for Stat sandboxing.
    stat_act: Action,

    /// Default action for Create sandboxing.
    create_act: Action,

    /// Default action for Delete sandboxing.
    delete_act: Action,

    /// Default action for Truncate sandboxing.
    truncate_act: Action,

    /// Default action for Rename sandboxing.
    rename_act: Action,

    /// Default action for Symlink sandboxing.
    symlink_act: Action,

    /// Default action for Chdir sandboxing.
    chdir_act: Action,

    /// Default action for Readdir sandboxing.
    readdir_act: Action,

    /// Default action for Mkdir sandboxing.
    mkdir_act: Action,

    /// Default action for Chown sandboxing.
    chown_act: Action,

    /// Default action for Chgrp sandboxing.
    chgrp_act: Action,

    /// Default action for Chmod sandboxing.
    chmod_act: Action,

    /// Default action for Chattr sandboxing.
    chattr_act: Action,

    /// Default action for Chroot sandboxing.
    chroot_act: Action,

    /// Default action for Utime sandboxing.
    utime_act: Action,

    /// Default action for Mkdev sandboxing.
    mkdev_act: Action,

    /// Default action for Mkfifo sandboxing.
    mkfifo_act: Action,

    /// Default action for Mktemp sandboxing.
    mktemp_act: Action,

    /// Default action for Ioctl sandboxing.
    ioctl_act: Action,

    /// Default action for Exec sandboxing.
    exec_act: Action,

    /// Default action for Net/Bind sandboxing.
    net_bind_act: Action,

    /// Default action for Net/Connect sandboxing.
    net_connect_act: Action,

    /// Default action for Net/SendFd sandboxing.
    net_sendfd_act: Action,

    /// Default action for Memory sandboxing.
    mem_act: Action,

    /// Default action for PID sandboxing.
    pid_act: Action,

    /// Default action for TPE sandboxing.
    tpe_act: Action,

    /// Integrity force defalt mode.
    force_act: Action,

    /// SegvGuard default mode.
    segvguard_act: Action,

    /// IP block default mode.
    net_block_act: Action,

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

    // Set of allowlisted/denylisted ioctl(2) requests.
    // true: deny, false: allow.
    ioctl_set: HashMap<u64, bool, RandomState>,

    // 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)>,

    // 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<OwnedFd>,
    pub(crate) crypt_kdf_salt: Option<Vec<u8>>,
    pub(crate) crypt_kdf_info_enc: String,
    pub(crate) crypt_kdf_info_mac: String,

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

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

    // List of allowlisted Netlink families.
    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.
    cidr_rules: VecDeque<CidrRule>,
    // Set of Landlock read rules.
    lock_rules_ro: Option<Vec<XPathBuf>>,
    // Set of Landlock write rules.
    lock_rules_rw: Option<Vec<XPathBuf>>,
    // Set of Landlock bind ports.
    lock_rules_bind: Option<Vec<RangeInclusive<u16>>>,
    // Set of Landlock connect ports.
    lock_rules_conn: Option<Vec<RangeInclusive<u16>>>,

    // Access control lists and filters:
    stat_acl: Acl,
    stat_arr: Arr,

    read_acl: Acl,
    read_arr: Arr,

    write_acl: Acl,
    write_arr: Arr,

    exec_acl: Acl,
    exec_arr: Arr,

    ioctl_acl: Acl,
    ioctl_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,

    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,

    mkdev_acl: Acl,
    mkdev_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: Arr,

    // A reference to the worker cache.
    //
    // This is only used by Serialize to display cache statistics.
    pub(crate) cache: Option<Arc<WorkerCache<'static>>>,
}

/// 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 Action {
    fn default() -> Self {
        Self::Deny
    }
}

impl Default for Flags {
    fn default() -> Self {
        let mut flags = if cfg!(any(
            target_arch = "mips",
            target_arch = "mips32r6",
            target_arch = "mips64",
            target_arch = "mips64r6",
        )) {
            // MIPS requires executable stack.
            Self::FL_ALLOW_UNSAFE_MEMORY | Self::FL_ALLOW_UNSAFE_STACK
        } else {
            Self::empty()
        };

        if env::var_os(ENV_SYNC_SCMP).is_some() {
            flags |= Self::FL_SYNC_SCMP;
        };

        flags
    }
}

impl Default for Capability {
    fn default() -> Self {
        // Note, GLOB includes network sandboxing.
        let mut caps = Self::CAP_GLOB | Self::CAP_TPE;

        // `ioctl` is part of GLOB and is not enabled by default.
        caps.remove(Self::CAP_IOCTL);

        caps
    }
}

impl Default for LockState {
    fn default() -> Self {
        Self::Exec
    }
}

impl FromStr for LockState {
    type Err = Errno;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        match s {
            "off" => Ok(Self::Off),
            "on" => Ok(Self::Set),
            "exec" => Ok(Self::Exec),
            _ => 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 {
    #[allow(clippy::disallowed_methods)]
    fn default() -> Self {
        #[allow(clippy::cast_sign_loss)]
        #[allow(clippy::decimal_literal_representation)]
        let mut sbox = Sandbox {
            flags: Flags::default(),
            state: Capability::default(),
            lock: None,
            cache: None,
            chroot: false,
            verbose: true,
            cpid: 0,
            fpid: libc::AT_FDCWD,
            config_expand_timeout: Duration::ZERO,
            bind_map: HashMap::default(),
            cache_path_cap: 1024,
            cache_addr_cap: 128,
            proc: Some(XPathBuf::from("/proc")),
            root: None,
            propagation: Some(MsFlags::MS_PRIVATE | MsFlags::MS_REC),
            hostname: (getpid().as_raw() as u64).to_name(),
            domainname: format!("syd-{API_VERSION}"),
            time: None,
            stat_act: Action::default(),
            read_act: Action::default(),
            write_act: Action::default(),
            exec_act: Action::default(),
            ioctl_act: Action::default(),
            chdir_act: Action::default(),
            readdir_act: Action::default(),
            mkdir_act: Action::default(),
            create_act: Action::default(),
            delete_act: Action::default(),
            rename_act: Action::default(),
            symlink_act: Action::default(),
            truncate_act: Action::default(),
            chown_act: Action::default(),
            chgrp_act: Action::default(),
            chmod_act: Action::default(),
            chattr_act: Action::default(),
            chroot_act: Action::default(),
            utime_act: Action::default(),
            mkdev_act: Action::default(),
            mkfifo_act: Action::default(),
            mktemp_act: Action::default(),
            net_bind_act: Action::default(),
            net_connect_act: Action::default(),
            net_sendfd_act: Action::default(),
            mem_act: Action::default(),
            mem_max: 128_u64 * 1024 * 1024,
            mem_vm_max: 0,
            pid_act: Action::Kill,
            pid_max: 1,
            net_block_act: Action::default(),
            net_block_lst: (IpRange::new(), IpRange::new()),
            umask: None,
            ioctl_set: HashMap::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)),
            tpe_act: Action::default(),
            tpe_gid: None,
            transit_uids: Vec::new(),
            transit_gids: Vec::new(),
            segvguard_act: Action::default(),
            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,
            crypt_kdf_salt: None,
            crypt_kdf_info_enc: "SYD-ENC".to_string(),
            crypt_kdf_info_mac: "SYD-MAC".to_string(),
            force_act: Action::default(),
            force_map: HashMap::default(),
            bind_mounts: None,
            netlink_families: NetlinkFamily::empty(),
            cidr_rules: VecDeque::new(),
            lock_rules_ro: None,
            lock_rules_rw: None,
            lock_rules_bind: None,
            lock_rules_conn: None,
            stat_acl: Acl::new(),
            stat_arr: Arr::new(),
            read_acl: Acl::new(),
            read_arr: Arr::new(),
            write_acl: Acl::new(),
            write_arr: Arr::new(),
            exec_acl: Acl::new(),
            exec_arr: Arr::new(),
            ioctl_acl: Acl::new(),
            ioctl_arr: Arr::new(),
            create_acl: Acl::new(),
            create_arr: Arr::new(),
            delete_acl: Acl::new(),
            delete_arr: Arr::new(),
            rename_acl: Acl::new(),
            rename_arr: Arr::new(),
            symlink_acl: Acl::new(),
            symlink_arr: Arr::new(),
            truncate_acl: Acl::new(),
            truncate_arr: Arr::new(),
            chdir_acl: Acl::new(),
            chdir_arr: Arr::new(),
            readdir_acl: Acl::new(),
            readdir_arr: Arr::new(),
            mkdir_acl: Acl::new(),
            mkdir_arr: Arr::new(),
            chown_acl: Acl::new(),
            chown_arr: Arr::new(),
            chgrp_acl: Acl::new(),
            chgrp_arr: Arr::new(),
            chmod_acl: Acl::new(),
            chmod_arr: Arr::new(),
            chattr_acl: Acl::new(),
            chattr_arr: Arr::new(),
            chroot_acl: Acl::new(),
            chroot_arr: Arr::new(),
            utime_acl: Acl::new(),
            utime_arr: Arr::new(),
            mkdev_acl: Acl::new(),
            mkdev_arr: Arr::new(),
            mkfifo_acl: Acl::new(),
            mkfifo_arr: Arr::new(),
            mktemp_acl: Acl::new(),
            mktemp_arr: Arr::new(),
            net_bind_acl: Acl::new(),
            net_bind_arr: Arr::new(),
            net_conn_acl: Acl::new(),
            net_conn_arr: Arr::new(),
            net_sendfd_acl: Acl::new(),
            net_sendfd_arr: Arr::new(),
            append_acl: VecDeque::new(),
            crypt_acl: VecDeque::new(),
            mask_acl: VecDeque::new(),
        };

        // Populate ioctl allow & denylists.
        for (request, deny) in DEFAULT_IOCTL {
            if *deny {
                sbox.add_ioctl_deny(*request);
            } else {
                sbox.add_ioctl_allow(*request);
            }
        }

        // SAFETY: We allow /dev/null for write and /proc for read by
        // default in the Landlock sandbox, because Syd is included in
        // the Landlock sandbox and Syd requires access to these paths to
        // function correctly.
        sbox.rule_add_lock_fs(Capability::CAP_LOCK_RO, "/proc")
            .expect("allow/lock/read+/proc");
        sbox.rule_add_lock_fs(Capability::CAP_LOCK_RW, "/dev/null")
            .expect("allow/lock/write+/dev/null");

        sbox
    }
}

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

        writeln!(f, "  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)?;

        write!(f, "  Default Action:")?;
        let act = self
            .state
            .iter()
            .map(|cap| self.default_action(cap))
            .collect::<HashSet<Action, RandomState>>();
        #[allow(clippy::disallowed_methods)]
        if act.len() == 1 {
            // All capabilities set to the same default action.
            writeln!(f, " {}", act.into_iter().next().unwrap())?;
        } else {
            writeln!(f)?;
            for cap in self.state.iter() {
                let action = self.default_action(cap);
                writeln!(f, "    {cap}:\t\t{action}")?;
            }
        }

        if let Some(ref cache) = self.cache {
            let c = &cache.path_cache.0;
            writeln!(
                f,
                "  Path Cache: {} hits, {} misses with size {} and capacity {}",
                c.hits(),
                c.misses(),
                c.len(),
                c.capacity()
            )?;

            let c = &cache.addr_cache.0;
            writeln!(
                f,
                "  Address Cache: {} hits, {} misses with size {} and capacity {}",
                c.hits(),
                c.misses(),
                c.len(),
                c.capacity()
            )?;
        }

        #[allow(clippy::cast_possible_truncation)]
        let mem_max = human_size(self.mem_max as usize);
        #[allow(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,
            "  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 size = self
            .cidr_rules
            .capacity()
            .saturating_mul(std::mem::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(std::mem::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(std::mem::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(std::mem::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(std::mem::size_of::<AclRule>());
        writeln!(
            f,
            "  Mask Rules: ({}, total {})",
            human_size(size),
            self.mask_acl.len()
        )?;
        for (idx, (rule, _)) in self.mask_acl.iter().enumerate() {
            let idx = idx.saturating_add(1);
            writeln!(f, "    {idx}. {rule}")?;
        }

        let mut force_rules: Vec<_> = self.force_map.iter().collect();
        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.force_act,
        )?;
        for (idx, (path, v)) in force_rules.iter().enumerate() {
            let (force, bytes) = v;
            let idx = idx.saturating_add(1);
            let hash = bytes.to_lower_hex_string();
            writeln!(
                f,
                "    {idx}. Action: {force}, Checksum: {hash}, Path: {path}"
            )?;
        }

        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("cache", &self.cache)
            .field("cpid", &self.cpid)
            .field("fpid", &self.fpid)
            .field("root", &self.root)
            .field("proc", &self.proc)
            .field("default_stat", &self.stat_act)
            .field("default_read", &self.read_act)
            .field("default_write", &self.write_act)
            .field("default_exec", &self.exec_act)
            .field("default_ioctl", &self.ioctl_act)
            .field("default_create", &self.create_act)
            .field("default_delete", &self.delete_act)
            .field("default_rename", &self.rename_act)
            .field("default_symlink", &self.symlink_act)
            .field("default_truncate", &self.truncate_act)
            .field("default_chdir", &self.chdir_act)
            .field("default_readdir", &self.readdir_act)
            .field("default_mkdir", &self.mkdir_act)
            .field("default_chown", &self.chown_act)
            .field("default_chgrp", &self.chgrp_act)
            .field("default_chmod", &self.chmod_act)
            .field("default_chattr", &self.chattr_act)
            .field("default_chroot", &self.chroot_act)
            .field("default_utime", &self.utime_act)
            .field("default_mkdev", &self.mkdev_act)
            .field("default_mkfifo", &self.mkfifo_act)
            .field("default_mktemp", &self.mktemp_act)
            .field("default_net_bind", &self.net_bind_act)
            .field("default_net_connect", &self.net_connect_act)
            .field("default_net_sendfd", &self.net_sendfd_act)
            .field("default_block", &self.net_block_act)
            .field("default_mem", &self.mem_act)
            .field("default_pid", &self.pid_act)
            .field("default_force", &self.force_act)
            .field("default_segvguard", &self.segvguard_act)
            .field("default_tpe", &self.tpe_act)
            .field("propagation", &self.propagation)
            .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("umask", &self.umask)
            .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())
            .finish()
    }
}

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

        map.serialize_entry("flags", &self.flags)?;
        map.serialize_entry("state", &self.state)?;
        map.serialize_entry("lock", &self.lock)?;
        map.serialize_entry("cache", &self.cache.as_deref())?;
        map.serialize_entry("cpid", &self.cpid)?;

        map.serialize_entry("default_stat", &self.stat_act)?;
        map.serialize_entry("default_read", &self.read_act)?;
        map.serialize_entry("default_write", &self.write_act)?;
        map.serialize_entry("default_exec", &self.exec_act)?;
        map.serialize_entry("default_ioctl", &self.ioctl_act)?;
        map.serialize_entry("default_create", &self.create_act)?;
        map.serialize_entry("default_delete", &self.delete_act)?;
        map.serialize_entry("default_rename", &self.rename_act)?;
        map.serialize_entry("default_symlink", &self.symlink_act)?;
        map.serialize_entry("default_truncate", &self.truncate_act)?;
        map.serialize_entry("default_chdir", &self.chdir_act)?;
        map.serialize_entry("default_readdir", &self.readdir_act)?;
        map.serialize_entry("default_mkdir", &self.mkdir_act)?;
        map.serialize_entry("default_chown", &self.chown_act)?;
        map.serialize_entry("default_chgrp", &self.chgrp_act)?;
        map.serialize_entry("default_chmod", &self.chmod_act)?;
        map.serialize_entry("default_chattr", &self.chattr_act)?;
        map.serialize_entry("default_chroot", &self.chroot_act)?;
        map.serialize_entry("default_utime", &self.utime_act)?;
        map.serialize_entry("default_mkdev", &self.mkdev_act)?;
        map.serialize_entry("default_mkfifo", &self.mkfifo_act)?;
        map.serialize_entry("default_mktemp", &self.mktemp_act)?;
        map.serialize_entry("default_net_bind", &self.net_bind_act)?;
        map.serialize_entry("default_net_connect", &self.net_connect_act)?;
        map.serialize_entry("default_net_sendfd", &self.net_sendfd_act)?;
        map.serialize_entry("default_block", &self.net_block_act)?;
        map.serialize_entry("default_mem", &self.mem_act)?;
        map.serialize_entry("default_pid", &self.pid_act)?;
        map.serialize_entry("default_force", &self.force_act)?;
        map.serialize_entry("default_segvguard", &self.segvguard_act)?;
        map.serialize_entry("default_tpe", &self.tpe_act)?;

        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("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("cidr_rules", &self.cidr_rules)?;
        map.serialize_entry("glob_rules", &self.glob_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
                .iter()
                .map(|(p, _)| p)
                .collect::<Vec<&XPathBuf>>(),
        )?;

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

        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.
    fn try_from(_spec: &Spec) -> Result<Self, Self::Error> {
        // Initialize sandbox to default state.
        let mut sandbox = Self::default();

        // SAFETY: Let the container engine declare capabilities.
        sandbox.flags.insert(Flags::FL_ALLOW_UNSAFE_CAPS);

        // 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");
        }

        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.
    #[allow(clippy::cognitive_complexity)]
    pub fn parse_config<F: Read + BufRead>(
        &mut self,
        mut file: F,
        path: &XPath,
        imap: &mut HashSet<FileInformation, RandomState>,
    ) -> 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_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::<BorrowedFd, XPath>(None, &inc, 0, STATX_INO | STATX_MODE)?;
                    let info = FileInformation::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_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.
                        #[allow(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.
                        #[allow(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.
    #[allow(clippy::disallowed_methods)]
    pub fn parse_config_file(&mut self, path: &XPath) -> SydResult<()> {
        // SAFETY: Do not resolve symbolic links!
        let how = OpenHow::new()
            .flags(OFlag::O_RDONLY | OFlag::O_CLOEXEC | OFlag::O_NOCTTY | OFlag::O_NOFOLLOW)
            .resolve(ResolveFlag::RESOLVE_NO_MAGICLINKS | ResolveFlag::RESOLVE_NO_SYMLINKS);

        let file = retry_on_eintr(|| openat2(libc::AT_FDCWD, path, how))
            .map(|fd| {
                // SAFETY: openat2 returns a valid FD on success.
                unsafe { OwnedFd::from_raw_fd(fd) }
            })
            .map(File::from)
            .map(BufReader::new)?;

        let mut imap = HashSet::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.
    #[allow(clippy::cognitive_complexity)]
    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),
            "kvm" => apply_config(self, PROFILE_KVM),
            "kvm_native" => apply_config(self, PROFILE_KVM_NATIVE),
            "paludis" => apply_config(self, PROFILE_PALUDIS),
            "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),
            "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),
            "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_VERSION}").as_bytes()),
                    home.join(format!(".user.syd-{API_VERSION}").as_bytes()),
                ];

                for path in &rc {
                    if !path.exists(true) {
                        continue;
                    } else if self.locked() {
                        error!("ctx": "configure_user",
                            "path": path,
                            "err": 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",
                        'i' => "immutable",
                        'l' => "landlock",
                        'p' => "privileged",
                        'q' => "quiet",
                        'u' => "user",
                        _ => 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");
    /// ```
    #[allow(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::Info) && !cmd.starts_with("crypt/") {
                    let cmd = XPathBuf::from(cmd);
                    let sbq = cmd.ends_with(b"?");
                    info!("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::Info) {
                    let cmd = XPathBuf::from(cmd);
                    info!("ctx": "query_sandbox",
                        "err": "sandbox query returned false",
                        "cfg": cmd);
                }
                Err(Errno::ENOENT)
            }
            Err(errno) => {
                let cmd = XPathBuf::from(cmd);
                error!("ctx": "configure_sandbox",
                    "err": format!("sandbox configure error: {errno}"),
                    "cfg": cmd);
                Err(errno)
            }
        }
    }

    #[allow(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_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");
            }
        }
    }

    #[allow(clippy::cognitive_complexity)]
    fn config_unchecked(&mut self, command: &str) -> Result<(), Errno> {
        if command.is_empty() || command == API_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 == "stat" {
            eprint!("{self}");
            Ok(())
        } 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(state) = command.strip_prefix("lock:") {
            self.lock(LockState::from_str(&self.expand_env(state)?)?)
        } else if let Some(value) = command.strip_prefix("time:") {
            self.time = Some(value.parse::<i64>().or(Err(Errno::EINVAL))?);
            Ok(())
        } else if let Some(command) = command.strip_prefix("cache/") {
            self.handle_cache_config(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("ioctl/") {
            self.handle_ioctl_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("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("name/") {
            self.handle_name_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 Some(captures) = RE_BIND.captures(command) {
            self.handle_bind_config(&captures)
        } 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 Some(captures) = RE_FORCE.captures(command) {
            self.handle_force_rule_config(&captures)
        } else if let Some(captures) = RE_SETID_0.captures(command) {
            self.handle_setid_rule_config(&captures)
        } else if let Some(captures) = RE_SETID_1.captures(command) {
            self.handle_setid_rule_config(&captures)
        } else if let Some(captures) = RE_NETALIAS.captures(command) {
            let alias = captures["alias"].to_ascii_lowercase();
            let command = captures["command"].to_ascii_lowercase();
            self.handle_netalias_config(&command, &alias)
        } else if let Some(captures) = RE_RULE_NETLINK.captures(command) {
            self.handle_netlink_config(&captures)
        } else if let Some(captures) = RE_RULE.captures(command) {
            self.handle_rule_config(&captures)
        } else {
            Err(Errno::EINVAL)
        }
    }

    pub(crate) fn add_bind<F: AsRawFd>(&mut self, fd: &F, path: &XPath) -> Result<(), Errno> {
        // Convert path to unix address.
        let addr = UnixAddr::new(path)?;

        // Get socket inode.
        let inode = fstatx(fd, STATX_INO).map(|statx| statx.stx_ino)?;

        // Record bind address.
        self.bind_map.insert(inode, addr);

        // Cleanup bind map from unused inodes as necessary.
        if self.bind_map.len() > 128 {
            let inodes = proc_unix_get_inodes()?;
            self.bind_map.retain(|inode, _| inodes.contains(inode));
        }

        Ok(())
    }

    pub(crate) fn get_bind(&self, inode: u64) -> Option<UnixAddr> {
        self.bind_map.get(&inode).copied()
    }

    fn handle_cache_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("capacity/path:") {
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            self.cache_path_cap = value.parse::<usize>().or(Err(Errno::EINVAL))?;
        } else if let Some(value) = command.strip_prefix("capacity/addr:") {
            if self.is_running() {
                return Err(Errno::EBUSY);
            }
            self.cache_addr_cap = value.parse::<usize>().or(Err(Errno::EINVAL))?;
        } else {
            return Err(Errno::EINVAL);
        }

        Ok(())
    }

    fn handle_netalias_config(&mut self, command: &str, alias: &str) -> Result<(), Errno> {
        let alias = self.expand_env(alias)?;
        if let Some(addr_vec) = MAP_NETALIAS.get(alias.as_ref()) {
            for addr in addr_vec {
                let c = command.replacen(alias.as_ref(), addr, 1);
                self.config(&c)?;
            }
            Ok(())
        } else {
            // This should never happen,
            // but let's handle it safely anyway.
            Err(Errno::EAFNOSUPPORT)
        }
    }

    fn handle_name_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("host:") {
            self.set_hostname(value)?;
        } else if let Some(value) = command.strip_prefix("domain:") {
            self.set_domainname(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 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_mask(&command[1..]),
            Some('-') => self.rule_del_mask(&command[1..]),
            Some('^') => self.rule_rem_mask(&command[1..]),
            _ => 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)?);
            if 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.is_running() {
                return Err(Errno::EBUSY);
            }
            self.proc = Some(root.join(b"proc"));
            self.root = Some(root);
        } else if let Some(value) = command.strip_prefix("/map:") {
            self.set_flag(Flags::FL_MAP_ROOT, value)?;
        } else if let Some(value) = command.strip_prefix("/fake:") {
            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);
            }
            self.config_expand_timeout = self
                .expand_env(value)?
                .parse::<u64>()
                .map(Duration::from_secs)
                .or(Err(Errno::EINVAL))?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    #[allow(clippy::cognitive_complexity)]
    fn handle_sandbox_config(&mut self, command: &str) -> Result<(), Errno> {
        #[allow(clippy::arithmetic_side_effects)]
        let (caps, state) = match command.chars().last() {
            Some('?') => (Capability::from_str(&command[..command.len() - 1])?, None),
            _ => {
                let mut splits = command.splitn(2, ':');
                (
                    Capability::from_str(splits.next().unwrap_or(""))?,
                    Some(strbool(
                        &self.expand_env(splits.next().ok_or(Errno::EINVAL)?)?,
                    )?),
                )
            }
        };

        if let Some(state) = state {
            // Setting Capability with :{on,off}.
            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.
    }

    #[allow(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",
                    "err": "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 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));
                    Ok(Errno::result(libc::syscall(
                        libc::SYS_close_range,
                        libc::STDERR_FILENO + 1,
                        libc::c_int::MAX,
                        libc::CLOSE_RANGE_CLOEXEC,
                    ))
                    .map(drop)?)
                })
            };

            match command.spawn() {
                Ok(_) => Ok(()),
                Err(error) => {
                    let errno = err2no(&error);
                    error!("ctx": "spawn_sandbox_program",
                        "cmd": program, "args": args,
                        "err": format!("cmd/exec program spawn error: {errno}"));
                    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 parts = command.splitn(2, ':');

        let items = parts.next().ok_or(Errno::EINVAL)?;
        let action = Action::from_str(&self.expand_env(parts.next().ok_or(Errno::EINVAL)?)?)?;

        for item in items.split(',') {
            match item.trim() {
                "all" => {
                    // nice-to-have: `default/all:filter'
                    // Here we do not add CAP_CHROOT to `all' for convenience.
                    let act = action.to_string().to_ascii_lowercase();
                    for cap in Capability::CAP_GLOB & !Capability::CAP_CHROOT {
                        let cap = cap.to_string().to_ascii_lowercase();
                        self.config(&format!("default/{cap}:{act}"))?;
                    }
                }
                "stat" => self.stat_act = action,
                "read" => self.read_act = action,
                "write" => self.write_act = action,
                "exec" => self.exec_act = action,
                "ioctl" => self.ioctl_act = action,
                "create" => self.create_act = action,
                "delete" => self.delete_act = action,
                "rename" => self.rename_act = action,
                "symlink" => self.symlink_act = action,
                "truncate" => self.truncate_act = action,
                "chdir" => self.chdir_act = action,
                "readdir" => self.readdir_act = action,
                "mkdir" => self.mkdir_act = action,
                "chown" => self.chown_act = action,
                "chgrp" => self.chgrp_act = action,
                "chmod" => self.chmod_act = action,
                "chattr" => self.chattr_act = action,
                "chroot" => self.chroot_act = action,
                "utime" => self.utime_act = action,
                "mkdev" => self.mkdev_act = action,
                "mkfifo" => self.mkfifo_act = action,
                "mktemp" => self.mktemp_act = action,
                "net/bind" => self.net_bind_act = action,
                "net/connect" => self.net_connect_act = action,
                "net/sendfd" => self.net_sendfd_act = action,
                "net" => {
                    self.net_bind_act = action;
                    self.net_connect_act = action;
                    self.net_sendfd_act = action;
                }
                "block" => {
                    if action == Action::Allow {
                        return Err(Errno::EINVAL);
                    }
                    self.net_block_act = action;
                }
                "mem" => {
                    if action == Action::Allow {
                        return Err(Errno::EINVAL);
                    }
                    self.mem_act = action;
                }
                "pid" => {
                    if matches!(action, Action::Allow | Action::Deny | Action::Panic) {
                        return Err(Errno::EINVAL);
                    }
                    self.pid_act = action;
                }
                "force" => {
                    if action == Action::Allow {
                        return Err(Errno::EINVAL);
                    }
                    self.force_act = action;
                }
                "segvguard" => {
                    if action == Action::Allow {
                        return Err(Errno::EINVAL);
                    }
                    self.segvguard_act = action;
                }
                "tpe" => {
                    if action == Action::Allow {
                        return Err(Errno::EINVAL);
                    }
                    self.tpe_act = action;
                }
                _ => return Err(Errno::EINVAL),
            }
        }

        Ok(())
    }

    #[allow(clippy::cognitive_complexity)]
    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("syslog:") {
            let state = strbool(&self.expand_env(value)?)?;
            if state {
                env::remove_var(ENV_NO_SYSLOG);
            } else {
                env::set_var(ENV_NO_SYSLOG, "1");
            }
            #[cfg(feature = "log")]
            if let Some(sys) = crate::syslog::global_syslog() {
                sys.set_host_syslog(state);
            }
        } else if let Some(value) = command.strip_prefix("verbose:") {
            self.verbose = strbool(&self.expand_env(value)?)?;
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_ioctl_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("deny+") {
            let request = str2u64(&self.expand_env(value)?)?;
            self.add_ioctl_deny(request);
        } else if let Some(value) = command.strip_prefix("deny-") {
            let request = str2u64(&self.expand_env(value)?)?;
            self.del_ioctl(request);
        } else if let Some(value) = command.strip_prefix("allow+") {
            let request = str2u64(&self.expand_env(value)?)?;
            self.add_ioctl_allow(request);
        } else if let Some(value) = command.strip_prefix("allow-") {
            let request = str2u64(&self.expand_env(value)?)?;
            self.del_ioctl(request);
        } 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 {
            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 {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    #[allow(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_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_exec:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_EXEC, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_libc:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_LIBC, 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_memory:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MEMORY, 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_caps:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_CAPS, 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_syslog:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SYSLOG, value)?
        } else if let Some(value) = command.strip_prefix("allow_unsafe_msgsnd:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MSGSND, 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_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_nopie:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_NOPIE, 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_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_perf:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_PERF, 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_stack:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_STACK, 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_cdev:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_OPEN_CDEV, 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_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_spec_exec:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_SPEC_EXEC, 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_memfd:") {
            self.set_flag(Flags::FL_ALLOW_UNSAFE_MEMFD, 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_script:") {
            self.set_flag(Flags::FL_DENY_SCRIPT, 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("lock_personality:") {
            self.set_flag(Flags::FL_LOCK_PERSONALITY, value)?
        } else if let Some(value) = command.strip_prefix("deny_elf32:") {
            self.set_flag(Flags::FL_DENY_ELF32, value)?
        } else if let Some(value) = command.strip_prefix("deny_elf_dynamic:") {
            self.set_flag(Flags::FL_DENY_ELF_DYNAMIC, value)?
        } else if let Some(value) = command.strip_prefix("deny_elf_static:") {
            self.set_flag(Flags::FL_DENY_ELF_STATIC, 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);
            }
            if value == 1 {
                // mode:1 -> use proc_pid_mem(5) unconditionally.
                env::set_var(ENV_NO_CROSS_MEMORY_ATTACH, "1");
            } else {
                // mode:0 -> use cross memory fallback to proc_pid_mem(5).
                // mode:2 -> use cross memory unconditionally (default).
                env::remove_var(ENV_NO_CROSS_MEMORY_ATTACH);
            }
            if value == 0 {
                // mode:0 -> use cross memory fallback to proc_pid_mem(5).
                env::set_var(ENV_PROC_PID_MEM_FALLBACK, "1");
            } else {
                // mode:1 -> use proc_pid_mem(5) unconditionally.
                // mode:2 -> use cross memory unconditionally (default).
                env::remove_var(ENV_PROC_PID_MEM_FALLBACK);
            }
        } else {
            return Err(Errno::EINVAL);
        }
        Ok(())
    }

    fn handle_unshare_config(&mut self, command: &str) -> Result<(), Errno> {
        #[allow(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,try}.
                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 = if is_equal(state.as_bytes(), b"try") {
                    None
                } else {
                    Some(strbool(&state)?)
                };
                if self.is_running() {
                    return Err(Errno::EBUSY);
                }
                (flags, state)
            }
        };

        let state = if let Some(state) = state {
            state
        } else {
            // auto-detect state.
            ns_enabled(flags.into())?
        };

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

        Ok(()) // set successful.
    }

    fn handle_bind_config(&mut self, captures: &Captures) -> Result<(), Errno> {
        let op = &captures["mod"];
        let mount = BindMount::try_from(captures)?;

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

        match op {
            "+" => self.add_bind_mount(mount),
            "-" => self.del_bind_mount(mount),
            "^" => self.rem_bind_mount(mount),
            _ => 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 = value
                .parse::<u64>()
                .map(Duration::from_secs)
                .or(Err(Errno::EINVAL))?;
        } else if let Some(value) = command.strip_prefix("suspension:") {
            let value = self.expand_env(value)?;
            self.segvguard_suspension = value
                .parse::<u64>()
                .map(Duration::from_secs)
                .or(Err(Errno::EINVAL))?;
        } 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(())
    }

    #[allow(clippy::cognitive_complexity)]
    fn handle_crypt_config(&mut self, command: &str) -> Result<(), Errno> {
        if let Some(value) = command.strip_prefix("key:") {
            let value = self.expand_env(value)?;
            let value = <[u8; KEY_SIZE]>::from_hex(&value).or(Err(Errno::EINVAL))?;
            if self.is_running() {
                // SAFETY: Do not allow changing at runtime.
                return Err(Errno::EBUSY);
            }
            self.crypt_id = Some(Secret::Key(Key::new(value)));
        } else if let Some(value) = command.strip_prefix("kdf/salt:") {
            let value = if value.is_empty() {
                None
            } else {
                Some(self.expand_env(value)?.as_bytes().to_vec())
            };
            if self.is_running() {
                // SAFETY: Do not allow changing at runtime.
                return Err(Errno::EBUSY);
            }
            self.crypt_kdf_salt = value;
        } else if let Some(value) = command.strip_prefix("kdf/info/enc:") {
            let value = if value.is_empty() {
                Cow::Borrowed(value)
            } else {
                self.expand_env(value)?
            };
            if self.is_running() {
                // SAFETY: Do not allow changing at runtime.
                return Err(Errno::EBUSY);
            }
            self.crypt_kdf_info_enc = value.to_string();
        } else if let Some(value) = command.strip_prefix("kdf/info/mac:") {
            let value = if value.is_empty() {
                Cow::Borrowed(value)
            } else {
                self.expand_env(value)?
            };
            if self.is_running() {
                // SAFETY: Do not allow changing at runtime.
                return Err(Errno::EBUSY);
            }
            self.crypt_kdf_info_mac = value.to_string();
        } 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" {
                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)?;

                // 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()).map(|fd| {
                    // SAFETY: duprand returns a valid FD on succcess.
                    unsafe { OwnedFd::from_raw_fd(fd) }
                })?;
                info!("ctx": "run", "op": "opendir_crypt_tmp",
                    "msg": "opened backing directory for crypt sandboxing",
                    "fd": fd.as_raw_fd());

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

        Ok(())
    }

    fn handle_force_rule_config(&mut self, captures: &Captures) -> Result<(), Errno> {
        let op = &captures["mod"];

        // Handle remove-all operator.
        if op == "^" {
            if ["src", "key", "act"]
                .iter()
                .any(|&name| captures.name(name).is_some())
            {
                return Err(Errno::EINVAL);
            }
            self.force_map.clear();
            return Ok(());
        }

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

        // Addition requires key and action.
        let key = if let Some(key) = captures.name("key") {
            Vec::from_hex(&self.expand_env(key.as_str())?).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 = if let Some(act) = captures.name("act") {
            Action::from_str(&self.expand_env(act.as_str())?)?
        } else {
            Action::default()
        };

        self.force_map.insert(src, (act, key));
        Ok(())
    }

    fn handle_setid_rule_config(&mut self, captures: &Captures) -> Result<(), Errno> {
        let id = captures["id"].chars().nth(0);
        let op = captures["mod"].chars().nth(0);

        match id {
            Some('u') => {
                match (op, captures.name("src")) {
                    (Some('+'), Some(src)) => {
                        let source_uid = self.expand_env(src.as_str())?;
                        let target_uid = self.expand_env(&captures["dst"])?;
                        let source_uid = parse_user(&source_uid)?;
                        let target_uid = parse_user(&target_uid)?;
                        self.add_uid_transit(source_uid, target_uid)?;
                    }
                    (Some('-'), Some(src)) => {
                        let source_uid = self.expand_env(src.as_str())?;
                        let target_uid = self.expand_env(&captures["dst"])?;
                        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('^'), Some(src)) => {
                        let source_uid = self.expand_env(src.as_str())?;
                        let source_uid = parse_user(&source_uid)?;
                        self.del_uid_transit(Some(source_uid), None);
                    }
                    (Some('^'), None) => {
                        self.del_uid_transit(None, None);
                    }
                    _ => return Err(Errno::EINVAL),
                };
            }
            Some('g') => {
                match (op, captures.name("src")) {
                    (Some('+'), Some(src)) => {
                        let source_gid = self.expand_env(src.as_str())?;
                        let target_gid = self.expand_env(&captures["dst"])?;
                        let source_gid = parse_group(&source_gid)?;
                        let target_gid = parse_group(&target_gid)?;
                        self.add_gid_transit(source_gid, target_gid)?;
                    }
                    (Some('-'), Some(src)) => {
                        let source_gid = self.expand_env(src.as_str())?;
                        let target_gid = self.expand_env(&captures["dst"])?;
                        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('^'), Some(src)) => {
                        let source_gid = self.expand_env(src.as_str())?;
                        let source_gid = parse_group(&source_gid)?;
                        self.del_gid_transit(Some(source_gid), None);
                    }
                    (Some('^'), None) => {
                        self.del_gid_transit(None, None);
                    }
                    _ => return Err(Errno::EINVAL),
                };
            }
            _ => return Err(Errno::EINVAL),
        };

        Ok(())
    }

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

        if captures.name("clr").is_some() {
            self.netlink_families = NetlinkFamily::empty();
        } else if captures.name("add").is_some() {
            self.netlink_families.insert(NetlinkFamily::from_str(
                &self.expand_env(&captures["fml"])?,
            )?);
        } else if captures.name("del").is_some() {
            self.netlink_families.remove(NetlinkFamily::from_str(
                &self.expand_env(&captures["fml"])?,
            )?);
        } else {
            unreachable!();
        };

        Ok(())
    }

    fn handle_rule_config(&mut self, captures: &Captures) -> Result<(), Errno> {
        let act = Action::from(captures);
        let cap = Capability::from(captures) & Capability::CAP_RULE;
        let op = &captures["mod"];
        let (pat, ip) = if let Some(addr) = captures.name("addr") {
            // Note: CAP_NET_SENDFD is for UNIX sockets only so we use `path'.
            (
                addr.as_str(),
                cap.intersects(Capability::CAP_NET_BIND | Capability::CAP_NET_CONNECT),
            )
        } else if let Some(path) = captures.name("path") {
            (path.as_str(), false)
        } else {
            unreachable!("Invalid rule regex!");
        };

        // Handle Landlock rules which are path beneath rules, not glob rules.
        if cap.intersects(Capability::CAP_LOCK) {
            if act != Action::Allow {
                return Err(Errno::EINVAL);
            } else if self.is_running() {
                // Landlock rules are applied at startup.
                return Err(Errno::EBUSY);
            }
            if cap.intersects(Capability::CAP_LOCK_FS) {
                return match op {
                    "+" => self.rule_add_lock_fs(cap, pat.as_ref()),
                    "-" => self.rule_del_lock_fs(cap, pat.as_ref()),
                    "^" => self.rule_rem_lock_fs(cap, pat.as_ref()),
                    _ => Err(Errno::EINVAL),
                };
            } else if cap.intersects(Capability::CAP_LOCK_NET) {
                return match op {
                    "+" => self.rule_add_lock_net(cap, pat.as_ref()),
                    "-" => self.rule_del_lock_net(cap, pat.as_ref()),
                    "^" => self.rule_rem_lock_net(cap, pat.as_ref()),
                    _ => Err(Errno::EINVAL),
                };
            } else {
                unreachable!("BUG: Landlock capabilities are inconsistent!");
            };
        }

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

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

    /// Remove CIDR with port range, removes all matching instances.
    pub fn rule_rem_cidr(&mut self, act: Action, cap: Capability, pat: &str) -> Result<(), Errno> {
        let pat = self.expand_env(pat)?;
        let pat = pat.parse::<AddressPattern>()?;
        let rem = CidrRule { act, cap, pat };
        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, cap: Capability, pat: &str) -> Result<(), Errno> {
        let pat = self.expand_env(pat)?;
        let pat = pat.parse::<AddressPattern>()?;
        let del = CidrRule { act, cap, pat };
        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, cap: Capability, pat: &str) -> Result<(), Errno> {
        let pat = self.expand_env(pat)?;
        let pat = pat.parse::<AddressPattern>()?;
        self.cidr_rules.push_front(CidrRule { act, cap, pat });
        Ok(())
    }

    /// Remove Landlock network rule, removes all matching patterns.
    pub fn rule_rem_lock_net(&mut self, cap: Capability, pat: &str) -> Result<(), Errno> {
        // Expand environment variables and decode hex.
        let pat = self.decode_hex(&self.expand_env(pat)?);
        let pat = pat.to_string();

        // Argument is either a single port or a closed range in format "port1-port2".
        let pat = {
            let parts: Vec<&str> = pat.splitn(2, '-').collect();
            if parts.len() == 2 {
                let start = parts[0].parse::<u16>().or(Err(Errno::EINVAL))?;
                let end = parts[1].parse::<u16>().or(Err(Errno::EINVAL))?;
                start..=end
            } else {
                let port = parts[0].parse::<u16>().or(Err(Errno::EINVAL))?;
                port..=port
            }
        };

        match cap {
            Capability::CAP_LOCK_BIND => {
                if let Some(ref mut rules) = self.lock_rules_bind {
                    rules.retain(|p| *p != pat);
                    if rules.is_empty() {
                        self.lock_rules_bind = None;
                    }
                }
                Ok(())
            }
            Capability::CAP_LOCK_CONNECT => {
                if let Some(ref mut rules) = self.lock_rules_conn {
                    rules.retain(|p| *p != pat);
                    if rules.is_empty() {
                        self.lock_rules_conn = None;
                    }
                }
                Ok(())
            }
            _ => Err(Errno::EINVAL),
        }
    }

    /// Remove Landlock network rule, removes the first instance from the end for predicatibility.
    pub fn rule_del_lock_net(&mut self, cap: Capability, pat: &str) -> Result<(), Errno> {
        // Expand environment variables and decode hex.
        let pat = self.decode_hex(&self.expand_env(pat)?);
        let pat = pat.to_string();

        // Argument is either a single port or a closed range in format "port1-port2".
        let pat = {
            let parts: Vec<&str> = pat.splitn(2, '-').collect();
            if parts.len() == 2 {
                let start = parts[0].parse::<u16>().or(Err(Errno::EINVAL))?;
                let end = parts[1].parse::<u16>().or(Err(Errno::EINVAL))?;
                start..=end
            } else {
                let port = parts[0].parse::<u16>().or(Err(Errno::EINVAL))?;
                port..=port
            }
        };

        match cap {
            Capability::CAP_LOCK_BIND => {
                if let Some(ref mut rules) = self.lock_rules_bind {
                    if let Some((index, _)) =
                        rules.iter().enumerate().rev().find(|(_, p)| **p == pat)
                    {
                        rules.remove(index);
                        if rules.is_empty() {
                            self.lock_rules_bind = None;
                        }
                    }
                }
                Ok(())
            }
            Capability::CAP_LOCK_CONNECT => {
                if let Some(ref mut rules) = self.lock_rules_conn {
                    if let Some((index, _)) =
                        rules.iter().enumerate().rev().find(|(_, p)| **p == pat)
                    {
                        rules.remove(index);
                        if rules.is_empty() {
                            self.lock_rules_conn = None;
                        }
                    }
                }
                Ok(())
            }
            _ => Err(Errno::EINVAL),
        }
    }

    /// Add Landlock network rule.
    pub fn rule_add_lock_net(&mut self, cap: Capability, pat: &str) -> Result<(), Errno> {
        // Expand environment variables.
        let pat = self.expand_env(pat)?.to_string();

        // Argument is either a single port or a closed range in format "port1-port2".
        let pat = {
            let parts: Vec<&str> = pat.splitn(2, '-').collect();
            if parts.len() == 2 {
                let start = parts[0].parse::<u16>().or(Err(Errno::EINVAL))?;
                let end = parts[1].parse::<u16>().or(Err(Errno::EINVAL))?;
                start..=end
            } else {
                let port = parts[0].parse::<u16>().or(Err(Errno::EINVAL))?;
                port..=port
            }
        };

        match cap {
            Capability::CAP_LOCK_BIND => {
                if let Some(ref mut rules) = self.lock_rules_bind {
                    rules.push(pat);
                } else {
                    let rules = vec![pat];
                    self.lock_rules_bind = Some(rules);
                }
                Ok(())
            }
            Capability::CAP_LOCK_CONNECT => {
                if let Some(ref mut rules) = self.lock_rules_conn {
                    rules.push(pat);
                } else {
                    let rules = vec![pat];
                    self.lock_rules_conn = Some(rules);
                }
                Ok(())
            }
            _ => Err(Errno::EINVAL),
        }
    }

    /// Remove Landlock filesystem rule, removes all matching patterns.
    pub fn rule_rem_lock_fs(&mut self, cap: Capability, pat: &str) -> Result<(), Errno> {
        // Expand environment variables and decode hex.
        let pat = self.decode_hex(&self.expand_env(pat)?);

        match cap {
            Capability::CAP_LOCK_RO => {
                if matches!(pat.as_bytes(), b"/proc" | b"/proc/") {
                    // SAFETY: Removing this rule will prevent Syd from functioning correctly.
                    return Err(Errno::EACCES);
                }
                if let Some(ref mut rules) = self.lock_rules_ro {
                    rules.retain(|p| *p != pat);
                    if rules.is_empty() {
                        self.lock_rules_ro = None;
                    }
                }
                Ok(())
            }
            Capability::CAP_LOCK_RW => {
                if matches!(pat.as_bytes(), b"/dev/null" | b"/dev/null/") {
                    // SAFETY: Removing this rule will prevent Syd from functioning correctly.
                    return Err(Errno::EACCES);
                }
                if let Some(ref mut rules) = self.lock_rules_rw {
                    rules.retain(|p| *p != pat);
                    if rules.is_empty() {
                        self.lock_rules_rw = None;
                    }
                }
                Ok(())
            }
            _ => Err(Errno::EINVAL),
        }
    }

    /// Remove Landlock filesystem rule, removes the first instance from the end for predicatibility.
    pub fn rule_del_lock_fs(&mut self, cap: Capability, pat: &str) -> Result<(), Errno> {
        // Expand environment variables and decode hex.
        let pat = self.decode_hex(&self.expand_env(pat)?);

        match cap {
            Capability::CAP_LOCK_RO => {
                if matches!(pat.as_bytes(), b"/proc" | b"/proc/") {
                    // SAFETY: Removing this rule will prevent Syd from functioning correctly.
                    return Err(Errno::EACCES);
                }
                if let Some(ref mut rules) = self.lock_rules_ro {
                    if let Some((index, _)) =
                        rules.iter().enumerate().rev().find(|(_, p)| **p == pat)
                    {
                        rules.remove(index);
                        if rules.is_empty() {
                            self.lock_rules_ro = None;
                        }
                    }
                }
                Ok(())
            }
            Capability::CAP_LOCK_RW => {
                if matches!(pat.as_bytes(), b"/dev/null" | b"/dev/null/") {
                    // SAFETY: Removing this rule will prevent Syd from functioning correctly.
                    return Err(Errno::EACCES);
                }
                if let Some(ref mut rules) = self.lock_rules_rw {
                    if let Some((index, _)) =
                        rules.iter().enumerate().rev().find(|(_, p)| **p == pat)
                    {
                        rules.remove(index);
                        if rules.is_empty() {
                            self.lock_rules_rw = None;
                        }
                    }
                }
                Ok(())
            }
            _ => Err(Errno::EINVAL),
        }
    }

    /// Add Landlock filesystem rule.
    pub fn rule_add_lock_fs(&mut self, cap: Capability, pat: &str) -> Result<(), Errno> {
        // Expand environment variables and decode hex.
        let pat = self.decode_hex(&self.expand_env(pat)?);

        // SAFETY: Landlock rules are not glob patterns but path beneath
        // rules. Hence, we do not require absolute pathnames for them
        // unlike glob rules.
        match cap {
            Capability::CAP_LOCK_RO => {
                if let Some(ref mut rules) = self.lock_rules_ro {
                    rules.push(pat);
                } else {
                    let rules = vec![pat];
                    self.lock_rules_ro = Some(rules);
                }
                Ok(())
            }
            Capability::CAP_LOCK_RW => {
                if let Some(ref mut rules) = self.lock_rules_rw {
                    rules.push(pat);
                } else {
                    let rules = vec![pat];
                    self.lock_rules_rw = Some(rules);
                }
                Ok(())
            }
            _ => Err(Errno::EINVAL),
        }
    }

    /// 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. Process title logging may be turned off with
                //    `filter/read+!proc/name`.
                // 2. Sending file descriptors to unnamed sockets may be
                //    allowed with `allow/net/sendfd+!unnamed`.
                // 3. Binding/Connecting to unnamed UNIX sockets may be
                //    allowed with e.g. `allow/net/bind+!unnamed`.
                //
                // We do no further procesing on these strings,
                // and match them literally.
                for cap in caps {
                    if act == Action::Filter {
                        let arr = self.get_arr_mut(cap);
                        arr.push_front((pat.clone(), MatchMethod::Literal));
                    } else {
                        let acl = self.get_acl_mut(cap);
                        acl.push_front((pat.clone(), MatchMethod::Literal, 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);
            }
        }

        #[allow(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();

        #[allow(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();

        #[allow(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();

        #[allow(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();

        #[allow(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 path.
        if pat.first() != Some(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);
        }

        #[allow(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();

        #[allow(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();

        #[allow(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 path.
        if pat.first() != Some(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);
        }

        #[allow(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(())
    }

    /// Remove Unix shell style pattern from mask acl, removes all matching instances.
    pub fn rule_rem_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();

        #[allow(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_mask(&pat, MatchMethod::Glob);
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.rem_mask(&pat, meth);

        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();

        #[allow(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);

        Ok(())
    }

    /// Add Unix shell style pattern to mask acl.
    pub fn rule_add_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();

        // Ensure absolute path.
        if pat.first() != Some(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);
        }

        #[allow(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);
            pat.truncate(len - b"/***".len()); // foo/*** -> foo
            (pat, MatchMethod::Glob)
        } else {
            (pat, MatchMethod::Glob)
        };
        self.add_mask(pat, meth);

        Ok(())
    }

    /// Extract the Landlock read-only and read-write path lists.
    /// Returns None if Landlock sandboxing is disabled.
    pub fn collect_landlock(&mut self) -> Option<LandlockRules> {
        if !self.landlocked() {
            return None;
        }

        let path_ro: Vec<XPathBuf> = if let Some(rules) = self.lock_rules_ro.take() {
            let set: IndexSet<XPathBuf> = IndexSet::from_iter(rules);
            set.iter().cloned().collect()
        } else {
            vec![]
        };

        let path_rw: Vec<XPathBuf> = if let Some(rules) = self.lock_rules_rw.take() {
            let set: IndexSet<XPathBuf> = IndexSet::from_iter(rules);
            set.iter().cloned().collect()
        } else {
            vec![]
        };

        let port_bind: Vec<RangeInclusive<u16>> = self.lock_rules_bind.take().unwrap_or_default();
        let port_conn: Vec<RangeInclusive<u16>> = self.lock_rules_conn.take().unwrap_or_default();

        Some((path_ro, path_rw, port_bind, port_conn))
    }

    /// 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 necesary.
    pub fn decode_hex(&self, pat: &str) -> XPathBuf {
        if let Ok(pat) = Vec::from_hex(pat) {
            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.
    #[allow(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));
        } else 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::Info) && input != env {
                        info!("ctx": "configure_expand",
                            "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",
                        "err": format!("error during variable expansion: {err}"),
                        "var": XPathBuf::from(input));
                    Err(Errno::EINVAL)
                }
            };
        }

        // Perform environment expansion at startup only.
        // SAFETY:
        // 1. Empty expansion generate an error.
        // 2. Setting config/expand to 0 disables expansion.
        match WordExp::expand_full(input, self.config_expand_timeout) {
            Ok(env) => {
                if log_enabled!(LogLevel::Info) && input != env {
                    info!("ctx": "configure_expand",
                        "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",
                    "err": format!("error during variable expansion: {err}"),
                    "var": XPathBuf::from(input));
                Err(Errno::EINVAL)
            }
        }
    }

    /// Check IPv{4,6} address against the IP blocklist.
    pub(crate) fn check_block(&self, addr: IpAddr) -> (Action, bool) {
        if self.net_block_act == Action::Allow {
            (Action::Allow, true)
        } else if self.net_block_act == Action::Warn {
            (Action::Warn, false)
        } else if match addr {
            IpAddr::V4(addr) => self.net_block_lst.0.contains(&addr),
            IpAddr::V6(addr) => self.net_block_lst.1.contains(&addr),
        } {
            (
                self.net_block_act,
                matches!(self.net_block_act, Action::Allow | Action::Filter),
            )
        } else {
            (Action::Allow, true)
        }
    }

    /// Check IPv{4,6} address for access.
    #[allow(clippy::cognitive_complexity)]
    pub(crate) fn check_ip(&self, cap: Capability, addr: IpAddr, port: u16) -> (Action, bool) {
        // Check for IP blocklist first.
        if cap == Capability::CAP_NET_CONNECT {
            let ok = match addr {
                IpAddr::V4(addr) => self.net_block_lst.0.contains(&addr),
                IpAddr::V6(addr) => self.net_block_lst.1.contains(&addr),
            };

            if ok {
                if self.net_block_act == Action::Filter {
                    // Filter is only checked for !(Allow|Filter).
                    // net_block_act can never be Allow.
                    return (Action::Filter, true);
                } else {
                    return (
                        self.net_block_act,
                        self.filter_ip(Capability::CAP_NET_CONNECT, &addr, port),
                    );
                }
            }
        }

        // 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 = match rule.pat.port {
                None => true,
                Some(ports) if ports[0] == ports[1] => port == ports[0],
                Some(ports) => port >= ports[0] && port <= ports[1],
            };
            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(&self, path: &XPath) -> Action {
        if !self.apply_tpe() {
            return Action::Allow;
        }

        // Get the parent directory.
        let (parent, _) = path.split();

        // SAFETY:
        // 1. Do not resolve symbolic links.
        // 2. Fail if the parent is not a directory.
        // Both of these are necessary to avoid TOCTOU.
        let fd = match safe_open_path::<BorrowedFd>(None, parent, OFlag::O_DIRECTORY) {
            Ok(fd) => fd,
            Err(_) => return self.tpe_act,
        };

        let root_owned = self.tpe_root_owned();
        let user_owned = self.tpe_user_owned();
        let mut sflags = STATX_MODE;
        if root_owned || user_owned {
            // File owner check required, request UID.
            sflags |= STATX_UID;
        }
        let statx = match fstatx(&fd, sflags) {
            Ok(statx) => statx,
            Err(_) => return self.tpe_act,
        };

        // Check if the parent directory is root/user owned.
        // Check if the parent directory is writable only by the owner.
        let is0 = statx.stx_uid == 0;
        if (u32::from(statx.stx_mode) & (libc::S_IWGRP | libc::S_IWOTH) != 0)
            || (user_owned && !is0 && statx.stx_uid != Uid::current().as_raw())
            || (root_owned && !is0)
        {
            self.tpe_act
        } else {
            Action::Allow
        }
    }

    /// Check if TPE should be applied.
    fn apply_tpe(&self) -> bool {
        // Check if TPE should be applied.
        if let Some(tpe_gid) = self.tpe_gid {
            let egid = Gid::effective();
            let apply = if egid == tpe_gid {
                !self.tpe_negate()
            } else {
                match getgroups() {
                    Ok(gids) => {
                        if self.tpe_negate() {
                            !gids.contains(&tpe_gid)
                        } else {
                            gids.contains(&tpe_gid)
                        }
                    }
                    Err(_) => return true,
                }
            };

            if !apply {
                return false;
            }
        } // TPE is applied if tpe_gid=None.

        true
    }

    /// 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.
        #[allow(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
    }

    /// 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.
    pub fn is_masked(&self, path: &XPath) -> bool {
        for (pattern, method) in &self.mask_acl {
            if globmatch(pattern.as_bytes(), path.as_bytes(), *method) {
                return true;
            }
        }
        false
    }

    /// 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 = match filter.pat.port {
                    None => true,
                    Some(ports) if ports[0] == ports[1] => port == ports[0],
                    Some(ports) => port >= ports[0] && port <= ports[1],
                };
                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 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
    }

    #[inline]
    fn get_acl(&self, cap: Capability) -> &Acl {
        match cap {
            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_IOCTL => &self.ioctl_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_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_MKDEV => &self.mkdev_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!(),
        }
    }

    #[inline]
    fn get_acl_mut(&mut self, cap: Capability) -> &mut Acl {
        match cap {
            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_IOCTL => &mut self.ioctl_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_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_MKDEV => &mut self.mkdev_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!(),
        }
    }

    #[inline]
    fn get_arr(&self, cap: Capability) -> &Arr {
        match cap {
            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_IOCTL => &self.ioctl_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_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_MKDEV => &self.mkdev_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!(),
        }
    }

    #[inline]
    fn get_arr_mut(&mut self, cap: Capability) -> &mut Arr {
        match cap {
            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_IOCTL => &mut self.ioctl_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_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_MKDEV => &mut self.mkdev_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.
    #[inline]
    pub fn default_action(&self, cap: Capability) -> Action {
        match cap {
            Capability::CAP_STAT => self.stat_act,
            Capability::CAP_READ => self.read_act,
            Capability::CAP_WRITE => self.write_act,
            Capability::CAP_EXEC => self.exec_act,
            Capability::CAP_IOCTL => self.ioctl_act,
            Capability::CAP_CREATE => self.create_act,
            Capability::CAP_DELETE => self.delete_act,
            Capability::CAP_RENAME => self.rename_act,
            Capability::CAP_SYMLINK => self.symlink_act,
            Capability::CAP_TRUNCATE => self.truncate_act,
            Capability::CAP_CHDIR => self.chdir_act,
            Capability::CAP_READDIR => self.readdir_act,
            Capability::CAP_MKDIR => self.mkdir_act,
            Capability::CAP_CHOWN => self.chown_act,
            Capability::CAP_CHGRP => self.chgrp_act,
            Capability::CAP_CHMOD => self.chmod_act,
            Capability::CAP_CHATTR => self.chattr_act,
            Capability::CAP_CHROOT => self.chroot_act,
            Capability::CAP_UTIME => self.utime_act,
            Capability::CAP_MKDEV => self.mkdev_act,
            Capability::CAP_MKFIFO => self.mkfifo_act,
            Capability::CAP_MKTEMP => self.mktemp_act,
            Capability::CAP_NET_BIND => self.net_bind_act,
            Capability::CAP_NET_CONNECT => self.net_connect_act,
            Capability::CAP_NET_SENDFD => self.net_sendfd_act,
            Capability::CAP_MEM => self.mem_act,
            Capability::CAP_PID => self.pid_act,
            Capability::CAP_FORCE => self.force_act,
            Capability::CAP_TPE => self.tpe_act,
            _ => Action::default(),
        }
    }

    /// 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 Proxy is configured.
    pub fn has_proxy(&self) -> bool {
        self.enabled(Capability::CAP_PROXY)
    }

    /// 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 {
                crypt_id.init(
                    self.crypt_kdf_salt.as_deref(),
                    self.crypt_kdf_info_enc.as_bytes(),
                    self.crypt_kdf_info_mac.as_bytes(),
                )
            } else {
                Err(Errno::ENOKEY)
            }
        } else {
            // Crypt sandboxing not enabled,
            // nothing to do.
            Ok(())
        }
    }

    /// Return a list of denylisted ioctl requests.
    pub(crate) fn get_ioctl_deny(&self) -> Vec<u64> {
        let mut vec = Vec::with_capacity(self.ioctl_set.len());
        for (req, deny) in &self.ioctl_set {
            if *deny {
                vec.push(*req);
            }
        }
        vec
    }

    /// Check if request belongs to the ioctl allowlist/denylist.
    pub(crate) fn has_ioctl(&self, request: &u64) -> Option<bool> {
        self.ioctl_set.get(request).copied()
    }

    /// Add an ioctl request to the allowlist.
    fn add_ioctl_allow(&mut self, request: u64) {
        self.ioctl_set.insert(request, false);
        if let Some(request) = extend_ioctl(request) {
            // musl compat, see documentation of extend_ioctl().
            self.ioctl_set.insert(request, false);
        }
    }

    /// Add an ioctl request to the denylist.
    fn add_ioctl_deny(&mut self, request: u64) {
        self.ioctl_set.insert(request, true);
        if let Some(request) = extend_ioctl(request) {
            // musl compat, see documentation of extend_ioctl().
            self.ioctl_set.insert(request, true);
        }
    }

    /// Remove an ioctl request to the allowlist/denylist.
    fn del_ioctl(&mut self, request: u64) {
        self.ioctl_set.remove(&request);
        if let Some(request) = extend_ioctl(request) {
            // musl compat, see documentation of extend_ioctl().
            self.ioctl_set.remove(&request);
        }
    }

    fn add_append(&mut self, pat: XPathBuf, meth: MatchMethod) {
        self.append_acl.push_front((pat, meth));
    }

    fn rem_append(&mut self, pat: &XPath, meth: MatchMethod) {
        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) {
        self.mask_acl.push_front((pat, meth));
    }

    fn rem_mask(&mut self, pat: &XPath, meth: MatchMethod) {
        self.mask_acl
            .retain(|(p, m)| meth != *m || !litmatch(pat.as_bytes(), p.as_bytes()));
    }

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

    fn add_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);
                arr.push_front((pat.to_owned(), meth));
            } else {
                let acl = self.get_acl_mut(cap);
                acl.push_front((pat.to_owned(), meth, act));
            }
        }
    }

    fn rem_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);
                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);
            }
        }
    }

    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) {
        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) {
        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) {
        // SAFETY: Set the sandbox lock if the state is unspecified.
        // This is safer than the previous default LockState::Exec.
        // We set this post-exec to ensure the initial configuration
        // passes through (ie config file and CLI options).
        if self.lock.is_none() {
            // !self.is_running -> lock returns no errors.
            let _ = self.lock(LockState::Set);
        }

        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 env::var_os(ENV_NO_CROSS_MEMORY_ATTACH).is_some() {
            // mode:1 -> use proc_pid_mem(5) unconditionally.
            1
        } else if env::var_os(ENV_PROC_PID_MEM_FALLBACK).is_some() {
            // mode:0 -> use cross memory fallback to proc_pid_mem(5).
            0
        } else {
            // mode:2 -> use cross memory unconditionally (default).
            2
        }
    }

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

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

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

    /// 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) {
        if !self.chroot {
            self.chroot = true;

            info!("ctx": "chroot_sandbox",
                "msg": "change root approved");
        }
    }

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

    /// Lock sandbox.
    pub fn lock(&mut self, state: LockState) -> Result<(), Errno> {
        if self.lock == Some(LockState::Set) {
            if state == LockState::Set {
                // Locking again when already locked is no-op.
                Ok(())
            } else {
                // No going back once locked.
                Err(Errno::EBUSY)
            }
        } else if state == LockState::Set {
            // Locked for the first and last time.
            self.lock = Some(LockState::Set);
            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.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 self.is_running() { "after" } else { "before" }),
                "run": self.is_running());

            Ok(())
        } else {
            self.lock = Some(state);
            Ok(())
        }
    }

    /// Returns true if the sandbox is locked.
    pub fn locked(&self) -> bool {
        self.lock == Some(LockState::Set)
    }

    /// 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 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)
    }

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

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

        namespaces
    }

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

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

        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
    }

    /// Set domainname, error if sandboxing is running.
    pub fn set_domainname(&mut self, value: &str) -> Result<(), Errno> {
        if self.is_running() {
            Err(Errno::EBUSY)
        } else {
            self.domainname = self.expand_env(value)?.to_string();
            Ok(())
        }
    }

    /// Set hostname, error if sandboxing is running.
    pub fn set_hostname(&mut self, value: &str) -> Result<(), Errno> {
        if self.is_running() {
            Err(Errno::EBUSY)
        } else {
            self.hostname = self.expand_env(value)?.to_string();
            Ok(())
        }
    }

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

    /// 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);
        }
    }

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

    /// 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);
        }
    }

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

    /// 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);
        }
    }

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

    /// 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);
        }
    }

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

    /// 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);
        }
    }

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

    /// 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);
        }
    }

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

    /// 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);
        }
    }

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

    /// 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 true if exit wait flag is set.
    pub fn exit_wait_all(&self) -> bool {
        self.flags.contains(Flags::FL_EXIT_WAIT_ALL)
    }

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

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

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

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

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

    /// Returns true if deny elf32 flag is set.
    pub fn deny_elf32(&self) -> bool {
        self.flags.contains(Flags::FL_DENY_ELF32)
    }

    /// Returns true if deny elf-dynamic flag is set.
    pub fn deny_elf_dynamic(&self) -> bool {
        self.flags.contains(Flags::FL_DENY_ELF_DYNAMIC)
    }

    /// Returns true if deny elf-static flag is set.
    pub fn deny_elf_static(&self) -> bool {
        self.flags.contains(Flags::FL_DENY_ELF_STATIC)
    }

    /// Returns true if deny script flag is set.
    pub fn deny_script(&self) -> bool {
        self.flags.contains(Flags::FL_DENY_SCRIPT)
    }

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

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

    /// Make chroot(2) a no-op like pivot_root(2).
    pub fn allow_unsafe_chroot(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_CHROOT)
    }

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

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

    /// Returns true if execve NULL arguments mitigation is disabled.
    pub fn allow_unsafe_exec(&self) -> bool {
        self.flags.intersects(Flags::FL_ALLOW_UNSAFE_EXEC)
    }

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

    /// Returns true if unsafe memory flag is set.
    pub fn allow_unsafe_memory(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_MEMORY)
    }

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

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

    /// Returns true if unsafe environment flag is set.
    pub fn allow_unsafe_env(&self) -> bool {
        self.flags.contains(Flags::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.flags.contains(Flags::FL_ALLOW_SAFE_BIND)
    }

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

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

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

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

    /// Returns true if execution of non-PIE binaries is allowed.
    pub fn allow_unsafe_nopie(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_NOPIE)
    }

    /// Returns true if execution of ELF binaries with executable stack is allowed.
    pub fn allow_unsafe_stack(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_STACK)
    }

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

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

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

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

    /// Returns true if unsafe msgsnd calls are allowed.
    pub fn allow_unsafe_msgsnd(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_MSGSND)
    }

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

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

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

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

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

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

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

    /// Returns true if setting AT_SECURE at PTRACE_EVENT_EXEC boundary is disabled.
    pub fn allow_unsafe_libc(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_LIBC)
    }

    /// 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.flags.contains(Flags::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.flags.contains(Flags::FL_ALLOW_UNSAFE_OPEN_PATH)
    }

    /// Returns true if CONTINUE should be applied on character devices
    /// rather than opening them in the Syd emulator thread and sending
    /// the file descriptor. This can be used as a workaround for
    /// character devices whose handling is per-process, e.g. /dev/kfd
    /// for AMD GPUs. Note, this setting may be changed at runtime, and
    /// it is highly advised to turn it back off once the respective
    /// resources are open.
    pub fn allow_unsafe_open_cdev(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_OPEN_CDEV)
    }

    /// 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.flags.contains(Flags::FL_ALLOW_UNSAFE_MAGICLINKS)
    }

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

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

    /// Returns true if unsafe speculative execution is allowed.
    pub fn allow_unsafe_spec_exec(&self) -> bool {
        self.flags.contains(Flags::FL_ALLOW_UNSAFE_SPEC_EXEC)
    }

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

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

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

    /// Returns true if personality(2) changes are locked.
    pub fn lock_personality(&self) -> bool {
        self.flags.contains(Flags::FL_LOCK_PERSONALITY)
    }

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

    /// 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)
                        .is_none(),
                )
            } else {
                (false, false)
            };
            (was_suspended, is_suspended, *value)
        } else {
            self.segvguard_map_expiry
                .insert(path.to_owned(), 1, self.segvguard_expiry);
            let (was_suspended, is_suspended) = if self.segvguard_maxcrashes <= 1 {
                (
                    true,
                    self.segvguard_map_suspension
                        .insert(path.to_owned(), (), self.segvguard_suspension)
                        .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.
        if self.segvguard_act == Action::Allow
            || self.segvguard_expiry.is_zero()
            || !self.segvguard_map_suspension.contains_key(path)
        {
            None
        } else {
            Some(self.segvguard_act)
        }
    }

    /// Return true if there're any SegvGuard suspended paths.
    pub fn has_segvguard(&self) -> bool {
        !self.segvguard_map_suspension.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 target_uid == ROOT_UID || 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 == ROOT_UID || 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
    }

    /// 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 target_gid == ROOT_GID || 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 == ROOT_GID || 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 matchign 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()
            .map_or(true, |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::<BorrowedFd>(None, path, OFlag::O_RDONLY) {
                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!
            if !constant_time_eq(&hash, key) {
                return Err(IntegrityError::Hash {
                    action: *action,
                    expected: key.to_lower_hex_string(),
                    found: hash.to_lower_hex_string(),
                });
            } else {
                return Ok(Action::Allow);
            }
        }
        Ok(self.force_act)
    }

    /// 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!
            if !constant_time_eq(&hash, key) {
                return Err(IntegrityError::Hash {
                    action: *action,
                    expected: key.to_lower_hex_string(),
                    found: hash.to_lower_hex_string(),
                });
            } else {
                return Ok(Action::Allow);
            }
        }
        Ok(self.force_act)
    }

    /// Returns the AF_ALG encryption & authentication setup socket FDs.
    pub fn crypt_setup(&self) -> Result<(RawFd, RawFd), Errno> {
        match &self.crypt_id {
            Some(Secret::Alg(aes_fd, mac_fd)) => Ok((aes_fd.as_raw_fd(), mac_fd.as_raw_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 panicing!
        if self.enabled(Capability::CAP_CRYPT) {
            return Err(Errno::EBUSY);
        }
        #[allow(clippy::disallowed_methods)]
        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()
    }
}

/// Converts a string representation of a number into a `u64` value.
///
/// The string can be in hexadecimal (prefixed with "0x"), octal
/// (prefixed with "0o"), or decimal format. If the conversion fails, it
/// returns an `Errno::EINVAL` error.
///
/// # Arguments
///
/// * `value` - A string slice that holds the number to be converted.
///
/// # Returns
///
/// * `Result<u64, Errno>` - On success, returns the converted `u64`
///   value. On failure, returns an `Errno::EINVAL` error.
fn str2u64(value: &str) -> Result<u64, Errno> {
    let value = value.to_ascii_lowercase();
    if let Some(value) = value.strip_prefix("0x") {
        u64::from_str_radix(value, 16)
    } else if let Some(value) = value.strip_prefix("0o") {
        u64::from_str_radix(value, 8)
    } else {
        value.parse::<u64>()
    }
    .or(Err(Errno::EINVAL))
}

// 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_stat() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        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());
        sandbox.config("sandbox/stat:on")?;
        assert!(sandbox.state.contains(Capability::CAP_STAT));
        assert!(sandbox.config("sandbox/stat?").is_ok());

        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_err());
        sandbox.config("sandbox/ioctl:on")?;
        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());
        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_ok());
        sandbox.config("sandbox/chdir:off")?;
        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());
        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_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_mkdev() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.state.contains(Capability::CAP_MKDEV));
        assert!(sandbox.config("sandbox/mkdev?").is_ok());
        sandbox.config("sandbox/mkdev:off")?;
        assert!(!sandbox.state.contains(Capability::CAP_MKDEV));
        assert!(sandbox.config("sandbox/mkdev?").is_err());
        sandbox.config("sandbox/mkdev:on")?;
        assert!(sandbox.state.contains(Capability::CAP_MKDEV));
        assert!(sandbox.config("sandbox/mkdev?").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_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(()));

        // Test setting crypt_key
        let good_key = "00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff";
        assert!(sandbox.crypt_id.is_none());
        sandbox.config(&format!("crypt/key:{good_key}"))?;
        assert!(sandbox.crypt_id.is_some());
        if let Some(Secret::Key(key)) = &sandbox.crypt_id {
            assert_eq!(
                key.as_ref(),
                &<[u8; KEY_SIZE]>::from_hex(good_key)
                    .unwrap()
                    .as_slice()
                    .try_into()
                    .unwrap() as &[u8; crate::hash::KEY_SIZE]
            );
        } else {
            panic!("Invalid key");
        }

        // Test invalid crypt_key length
        let bad_key = "00112233445566778899aabbccddeeff00112233445566778899aabbccddeef";
        assert_eq!(
            sandbox.config(&format!("crypt/key:{bad_key}")),
            Err(Errno::EINVAL)
        );

        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());
        assert_eq!(sandbox.config(&format!("crypt/key:{good_key}")), 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_CONNECT));
        assert!(!sandbox.state.contains(Capability::CAP_NET_BIND));
        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_SENDFD));
        assert!(!sandbox.state.contains(Capability::CAP_NET_BIND));
        assert!(!sandbox.state.contains(Capability::CAP_NET_CONNECT));
        assert!(sandbox.config("sandbox/net?").is_err());
        assert!(sandbox.config("sandbox/net/bind?").is_err());
        assert!(sandbox.config("sandbox/net/sendfd?").is_ok());
        assert!(sandbox.config("sandbox/net/connect?").is_err());
        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 = Capability::empty();
        sandbox.config("sandbox/read,stat:on")?;
        sandbox.config("sandbox/read,write,lock:off")?;
        sandbox.config("sandbox/lock,pid,mem,force,proxy,ioctl:on")?;
        sandbox.config("sandbox/force,mem,tpe,proxy:off")?;
        sandbox.config("sandbox/net,exec:on")?;
        sandbox.config("sandbox/net/bind,net/bind: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_NET_BIND));
        assert!(!sandbox.state.contains(Capability::CAP_FORCE));
        assert!(!sandbox.state.contains(Capability::CAP_TPE));
        assert!(!sandbox.state.contains(Capability::CAP_PROXY));
        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_sandbox_many_lax() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.state = Capability::empty();
        sandbox.config("sandbox/\treAd ,\t,\t\t,\t\t ,\t \t,  STaT :on")?;
        sandbox.config("sandbox/  ReaD\t\t, write   , lock\t\t:OFF")?;
        sandbox.config("sandbox/   Lock  , pID, MeM,  ForcE,MeM,LOCK,IoCtL:on")?;
        sandbox.config("sandbox/ Force ,  ,\t,  MeM  , PROXY, TPe\t,  :off")?;
        sandbox.config("sandbox/   Net ,   , ,  ,   ,    ,    \t,eXEc    :on")?;
        sandbox.config("sandbox/\t Net/BInd , net/bInd :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_NET_BIND));
        assert!(!sandbox.state.contains(Capability::CAP_FORCE));
        assert!(!sandbox.state.contains(Capability::CAP_TPE));
        assert!(!sandbox.state.contains(Capability::CAP_PROXY));
        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());

        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());

        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());

        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());

        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());

        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());

        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());

        Ok(())
    }

    #[test]
    fn sandbox_config_unshare_flags_many() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.flags = 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_unshare_flags_many_lax() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.flags = Flags::empty();
        sandbox.config("unshare/\tmOunt ,\tuTS,\t\t,\t\t ,\t \t,   :on")?;
        sandbox.config("unshare/  moUnT\t\t, UTS   ,  \t\tIPc    ,,,,,,:off")?;
        sandbox.config("unshare/  MoUnT\t , ,  ,,,,,,\tUtS  ,\t, IPC  \t,  USer:on")?;
        sandbox.config("unshare/     user,  , , , , , , pId:off")?;
        sandbox.config("unshare/\t\t,,,,net,,,,,,cgroup:on")?;
        sandbox.config("unshare/,,,,,CGROUP,\t: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() -> 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:on")?;
        assert_eq!(sandbox.lock, Some(LockState::Set));
        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_01() -> TestResult<()> {
        let mut sandbox = Sandbox::default();
        assert!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.collect_landlock().is_none());

        sandbox.config("sandbox/lock:on")?;
        let (rules_ro, rules_rw, _, _) = sandbox.collect_landlock().unwrap();
        assert_eq!(rules_ro.len(), 1);
        assert_eq!(rules_rw.len(), 1);
        assert_eq!(rules_ro[0], XPath::from_bytes(b"/proc").to_owned());
        assert_eq!(rules_rw[0], XPath::from_bytes(b"/dev/null").to_owned());

        sandbox.config("sandbox/lock:off")?;
        assert!(sandbox.lock_rules_ro.is_none());
        assert!(sandbox.lock_rules_rw.is_none());
        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_02() -> TestResult<()> {
        for sig_action in [Action::Kill, Action::Abort, Action::Stop] {
            let mut sandbox = Sandbox::default();
            assert_eq!(
                sandbox.rule_add_glob(sig_action, Capability::CAP_READ, "/"),
                Ok(())
            );
            assert_eq!(
                sandbox.rule_add_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_WRITE,
                    "/"
                ),
                Ok(())
            );
            assert_eq!(
                sandbox.rule_add_glob(sig_action, Capability::empty(), "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(sig_action, Capability::empty(), "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(sig_action, Capability::empty(), "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_add_glob(sig_action, Capability::CAP_LOCK_RO, "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(sig_action, Capability::CAP_LOCK_RO, "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(sig_action, Capability::CAP_LOCK_RO, "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_add_glob(sig_action, Capability::CAP_LOCK_RW, "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(sig_action, Capability::CAP_LOCK_RW, "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(sig_action, Capability::CAP_LOCK_RW, "/"),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_add_glob(
                    sig_action,
                    Capability::CAP_LOCK_RO | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(
                    sig_action,
                    Capability::CAP_LOCK_RO | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(
                    sig_action,
                    Capability::CAP_LOCK_RO | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_add_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RO,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RO,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RO,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_add_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_add_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RO | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RO | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(
                    sig_action,
                    Capability::CAP_READ | Capability::CAP_LOCK_RO | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_add_glob(
                    sig_action,
                    Capability::CAP_READ
                        | Capability::CAP_WRITE
                        | Capability::CAP_LOCK_RO
                        | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_del_glob(
                    sig_action,
                    Capability::CAP_READ
                        | Capability::CAP_WRITE
                        | Capability::CAP_LOCK_RO
                        | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
            assert_eq!(
                sandbox.rule_rem_glob(
                    sig_action,
                    Capability::CAP_READ
                        | Capability::CAP_WRITE
                        | Capability::CAP_LOCK_RO
                        | Capability::CAP_LOCK_RW,
                    "/"
                ),
                Err(Errno::EINVAL)
            );
        }
        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_03() -> 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)
        );
        assert_eq!(
            sandbox.config("allow/lock/write^/dev/null"),
            Err(Errno::EACCES)
        );
        assert_eq!(
            sandbox.config("allow/lock/write^/dev/null/"),
            Err(Errno::EACCES)
        );
        assert_eq!(sandbox.config("allow/lock/read+/proc"), Ok(()));
        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/read-/proc"), Err(Errno::EACCES));
        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/read^/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(()));
        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_04() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.lock_rules_ro = None; // Default = Some([/proc])
        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.lock_rules_ro, None);

        sandbox.lock_rules_rw = None; // Default = Some([/dev/null])
        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.lock_rules_rw, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_05() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.lock_rules_ro = None; // Default = Some([/proc])
        assert!(sandbox.config("allow/lock/read+/abspath").is_ok());
        assert!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read-/abspath").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        assert_eq!(sandbox.lock_rules_ro, None);
        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!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read^/abspath").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        sandbox.lock_rules_rw = None; // Default = Some([/dev/null])
        assert!(sandbox.config("allow/lock/write+/abspath").is_ok());
        assert!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write-/abspath").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        assert_eq!(sandbox.lock_rules_rw, None);
        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!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write^/abspath").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_06() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.lock_rules_ro = None; // Default = Some([/proc])
        assert!(sandbox.config("allow/lock/read+foo").is_ok());
        assert!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read-foo").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        assert_eq!(sandbox.lock_rules_ro, None);
        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.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read^foo").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        sandbox.lock_rules_rw = None; // Default = Some([/dev/null])
        assert!(sandbox.config("allow/lock/write+foo").is_ok());
        assert!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write-foo").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        assert_eq!(sandbox.lock_rules_rw, None);
        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.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write^foo").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_07() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.lock_rules_ro = None; // Default = Some([/proc])
        assert!(sandbox.config("allow/lock/read+foo/bar").is_ok());
        assert!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read-foo/bar").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        assert_eq!(sandbox.lock_rules_ro, None);
        assert!(sandbox.config("allow/lock/read+foo/bar").is_ok());
        assert!(sandbox.config("allow/lock/read+foo/bar").is_ok());
        assert!(sandbox.config("allow/lock/read+foo/bar").is_ok());
        assert!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read^foo/bar").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        sandbox.lock_rules_rw = None; // Default = Some([/dev/null])
        assert!(sandbox.config("allow/lock/write+foo/bar").is_ok());
        assert!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write-foo/bar").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        assert_eq!(sandbox.lock_rules_rw, None);
        assert!(sandbox.config("allow/lock/write+foo/bar").is_ok());
        assert!(sandbox.config("allow/lock/write+foo/bar").is_ok());
        assert!(sandbox.config("allow/lock/write+foo/bar").is_ok());
        assert!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write^foo/bar").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_08() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.lock_rules_ro = None; // Default = Some([/proc])
        assert!(sandbox.config("allow/lock/read+./foo").is_ok());
        assert!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read-./foo").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        assert_eq!(sandbox.lock_rules_ro, None);
        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.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read^./foo").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        sandbox.lock_rules_rw = None; // Default = Some([/dev/null])
        assert!(sandbox.config("allow/lock/write+./foo").is_ok());
        assert!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write-./foo").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        assert_eq!(sandbox.lock_rules_rw, None);
        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.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write^./foo").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_09() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        sandbox.lock_rules_ro = None; // Default = Some([/proc])
        assert!(sandbox.config("allow/lock/read+~/foo").is_ok());
        assert!(sandbox.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read-~/foo").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        assert_eq!(sandbox.lock_rules_ro, None);
        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.lock_rules_ro.is_some());
        assert!(sandbox.config("allow/lock/read^~/foo").is_ok());
        assert_eq!(sandbox.lock_rules_ro, None);

        sandbox.lock_rules_rw = None; // Default = Some([/dev/null])
        assert!(sandbox.config("allow/lock/write+~/foo").is_ok());
        assert!(sandbox.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write-~/foo").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        assert_eq!(sandbox.lock_rules_rw, None);
        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.lock_rules_rw.is_some());
        assert!(sandbox.config("allow/lock/write^~/foo").is_ok());
        assert_eq!(sandbox.lock_rules_rw, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_10() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.lock_rules_bind, None);

        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+1-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind+-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind+a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind+a-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind+1-a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind+65542"), 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-1-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind--1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind-a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind-a-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind-1-a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind-65542"), 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^1-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind^-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind^a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind^a-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind^1-a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/bind^65542"), Err(Errno::EINVAL));

        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_conn, None);

        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+1-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect+-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect+a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect+a-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect+1-a"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/connect+65542"),
            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-1-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect--1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect-a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect-a-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect-1-a"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/connect-65542"),
            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^1-"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect^-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect^a"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect^a-1"), Err(Errno::EINVAL));
        assert_eq!(sandbox.config("allow/lock/connect^1-a"), Err(Errno::EINVAL));
        assert_eq!(
            sandbox.config("allow/lock/connect^65542"),
            Err(Errno::EINVAL)
        );

        assert_eq!(sandbox.lock_rules_conn, None);

        Ok(())
    }

    #[test]
    fn sandbox_config_lock_rules_11() -> TestResult<()> {
        let mut sandbox = Sandbox::default();

        assert_eq!(sandbox.lock_rules_bind, None);
        assert!(sandbox.config("allow/lock/bind+0").is_ok());
        assert!(sandbox.lock_rules_bind.is_some());
        assert!(sandbox.config("allow/lock/bind-0").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_bind, 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_bind.is_some());
        assert!(sandbox.config("allow/lock/bind^0").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_bind, None);
        assert!(sandbox.config("allow/lock/bind+0-65535").is_ok());
        assert!(sandbox.lock_rules_bind.is_some());
        assert!(sandbox.config("allow/lock/bind-0-65535").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_bind, 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_bind.is_some());
        assert!(sandbox.config("allow/lock/bind^0-65535").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_bind, None);
        assert!(sandbox.config("allow/lock/bind+1").is_ok());
        assert!(sandbox.lock_rules_bind.is_some());
        assert!(sandbox.config("allow/lock/bind-1").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_bind, 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_bind.is_some());
        assert!(sandbox.config("allow/lock/bind^1").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_bind, None);
        assert!(sandbox.config("allow/lock/bind+1-42").is_ok());
        assert!(sandbox.lock_rules_bind.is_some());
        assert!(sandbox.config("allow/lock/bind-1-42").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_bind, 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_bind.is_some());
        assert!(sandbox.config("allow/lock/bind^1-42").is_ok());
        assert_eq!(sandbox.lock_rules_bind, None);

        assert_eq!(sandbox.lock_rules_conn, None);
        assert!(sandbox.config("allow/lock/connect+0").is_ok());
        assert!(sandbox.lock_rules_conn.is_some());
        assert!(sandbox.config("allow/lock/connect-0").is_ok());
        assert_eq!(sandbox.lock_rules_conn, None);

        assert_eq!(sandbox.lock_rules_conn, 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_conn.is_some());
        assert!(sandbox.config("allow/lock/connect^0").is_ok());
        assert_eq!(sandbox.lock_rules_conn, None);

        assert_eq!(sandbox.lock_rules_conn, None);
        assert!(sandbox.config("allow/lock/connect+0-65535").is_ok());
        assert!(sandbox.lock_rules_conn.is_some());
        assert!(sandbox.config("allow/lock/connect-0-65535").is_ok());
        assert_eq!(sandbox.lock_rules_conn, None);

        assert_eq!(sandbox.lock_rules_conn, 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_conn.is_some());
        assert!(sandbox.config("allow/lock/connect^0-65535").is_ok());
        assert_eq!(sandbox.lock_rules_conn, None);

        assert_eq!(sandbox.lock_rules_conn, None);
        assert!(sandbox.config("allow/lock/connect+1").is_ok());
        assert!(sandbox.lock_rules_conn.is_some());
        assert!(sandbox.config("allow/lock/connect-1").is_ok());
        assert_eq!(sandbox.lock_rules_conn, None);

        assert_eq!(sandbox.lock_rules_conn, 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_conn.is_some());
        assert!(sandbox.config("allow/lock/connect^1").is_ok());
        assert_eq!(sandbox.lock_rules_conn, None);

        assert_eq!(sandbox.lock_rules_conn, None);
        assert!(sandbox.config("allow/lock/connect+1-42").is_ok());
        assert!(sandbox.lock_rules_conn.is_some());
        assert!(sandbox.config("allow/lock/connect-1-42").is_ok());
        assert_eq!(sandbox.lock_rules_conn, None);

        assert_eq!(sandbox.lock_rules_conn, 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_conn.is_some());
        assert!(sandbox.config("allow/lock/connect^1-42").is_ok());
        assert_eq!(sandbox.lock_rules_conn, 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::EACCES));
        assert_eq!(sandbox.config("setgid+0:0"), Err(Errno::EACCES));
        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::EACCES));
        assert_eq!(sandbox.config("setgid+1:1"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("setuid+65534:65534"), Err(Errno::EACCES));
        assert_eq!(sandbox.config("setgid+65534:65534"), Err(Errno::EACCES));

        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:1"), Err(Errno::EEXIST));
        // Removing the transition and then readding 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:1"), 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(1), "{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:1"), Err(Errno::EEXIST));
        // Removing the transition and then readding 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:1"), 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(1), "{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:1"), Ok(()));
        assert_eq!(sandbox.config("setuid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setuid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, Uid::from_raw(3), "{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}");

        assert_eq!(sandbox.config("setgid+0:1"), Ok(()));
        assert_eq!(sandbox.config("setgid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setgid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, Gid::from_raw(3), "{sandbox}");
        assert_eq!(sandbox.config("setgid^"), Ok(()));
        assert_eq!(sandbox.transit_gids.len(), 0, "{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}");

        assert_eq!(sandbox.config("setuid+0:1"), Ok(()));
        assert_eq!(sandbox.config("setuid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setuid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, Uid::from_raw(3), "{sandbox}");
        assert_eq!(sandbox.config("setuid^0:1"), 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::from_raw(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}");

        assert_eq!(sandbox.config("setgid+0:1"), Ok(()));
        assert_eq!(sandbox.config("setgid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setgid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, Gid::from_raw(3), "{sandbox}");
        assert_eq!(sandbox.config("setgid^0:1"), 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::from_raw(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::EACCES));
        assert_eq!(sandbox.config("setgid+root:root"), Err(Errno::EACCES));
        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::EACCES));
        if let Ok((_, nogroup)) = get_nogroup() {
            assert_eq!(
                sandbox.config(&format!("setgid+{nogroup}:{nogroup}")),
                Err(Errno::EACCES)
            );
        }

        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:1"), Err(Errno::EEXIST));
        // Removing the transition and then readding 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:1"), 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(1), "{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:1"), Err(Errno::EEXIST));
        // Removing the transition and then readding 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:1"), 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(1), "{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:1"), Ok(()));
        assert_eq!(sandbox.config("setuid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setuid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, Uid::from_raw(3), "{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:1"), Ok(()));
        assert_eq!(sandbox.config("setgid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setgid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, Gid::from_raw(3), "{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:1"), Ok(()));
        assert_eq!(sandbox.config("setuid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setuid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].0, Uid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_uids[1].1, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].0, Uid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_uids[2].1, Uid::from_raw(3), "{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(2), "{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:1"), Ok(()));
        assert_eq!(sandbox.config("setgid+1:2"), Ok(()));
        assert_eq!(sandbox.config("setgid+2:3"), 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(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].0, Gid::from_raw(1), "{sandbox}");
        assert_eq!(sandbox.transit_gids[1].1, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].0, Gid::from_raw(2), "{sandbox}");
        assert_eq!(sandbox.transit_gids[2].1, Gid::from_raw(3), "{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(2), "{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}");

        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}");

        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}");

        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}");

        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}");

        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!"), 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")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/loadavg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/meminfo")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/version")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/config.gz")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/cpuinfo")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/diskstats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/filesystems")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kallsyms")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kcore")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/latency_stats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/stat")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/uptime")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/vmstat")));

        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")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/loadavg")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/meminfo")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/version")));

        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")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/loadavg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/meminfo")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/version")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/filesystems")));

        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")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/loadavg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/meminfo")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/version")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/filesystems")));

        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")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/loadavg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/meminfo")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/version")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/config.gz")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/cpuinfo")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/diskstats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/filesystems")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kallsyms")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kcore")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/latency_stats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/stat")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/uptime")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/vmstat")));

        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}");
        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")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/loadavg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/meminfo")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/version")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/config.gz")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/cpuinfo")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/diskstats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/filesystems")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kallsyms")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kcore")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/latency_stats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/stat")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/uptime")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/vmstat")));

        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}");

        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/cmdline")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/dev/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/kmsg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/loadavg")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/meminfo")));
        assert!(sandbox.is_masked(&XPath::from_bytes(b"/proc/version")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/config.gz")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/cpuinfo")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/diskstats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/filesystems")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kallsyms")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/kcore")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/latency_stats")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/stat")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/uptime")));
        assert!(!sandbox.is_masked(&XPath::from_bytes(b"/proc/vmstat")));

        Ok(())
    }

    #[test]
    fn sandbox_config_rules_356() -> 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!(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_357() -> 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_358() -> 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_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}");
        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_360() -> 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_361() -> 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_362() -> 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_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_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(())
    }
}
