// Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
//! Provides easy-to-use Linux seccomp-bpf jailing.
//!
//! Seccomp is a Linux kernel security feature which enables a tight control over what kernel-level
//! mechanisms a process has access to. This is typically used to reduce the attack surface and
//! exposed resources when running untrusted code. This works by allowing users to write and set a
//! BPF (Berkeley Packet Filter) program for each process or thread, that intercepts syscalls and
//! decides whether the syscall is safe to execute.
//!
//! Writing BPF programs by hand is difficult and error-prone. This crate provides high-level
//! wrappers for working with system call filtering.
//!
//! The core concept of the library is the filter. It is an abstraction that
//! models a collection of syscall-mapped rules, coupled with on-match and
//! default actions, that logically describes a policy for dispatching actions
//! (e.g. Allow, Trap, Errno) for incoming system calls.
//!
//! Seccompiler provides constructs for defining filters, compiling them into
//! loadable BPF programs and installing them in the kernel.
//!
//! Filters are defined either with a JSON file or using Rust code, with
//! library-defined structures. Both representations are semantically equivalent
//! and model the rules of the filter. Choosing one or the other depends on the use
//! case and preference.
//!
//! # Supported platforms
//!
//! Due to the fact that seccomp is a Linux-specific feature, this crate is
//! supported only on Linux systems.
//!
//! Supported host architectures:
//! - Little-endian x86_64
//! - Little-endian aarch64
//!
//! # Terminology
//!
//! The smallest unit of the [`SeccompFilter`] is the [`SeccompCondition`], which is a
//! comparison operation applied to the current system call. It’s parametrised by
//! the argument index, the length of the argument, the operator and the actual
//! expected value.
//!
//! Going one step further, a [`SeccompRule`] is a vector of [`SeccompCondition`]s,
//! that must all match for the rule to be considered matched. In other words, a
//! rule is a collection of **and-bound** conditions for a system call.
//!
//! Finally, at the top level, there’s the [`SeccompFilter`]. The filter can be
//! viewed as a collection of syscall-associated rules, with a predefined on-match
//! [`SeccompAction`] and a default [`SeccompAction`] that is returned if none of the rules match.
//!
//! In a filter, each system call number maps to a vector of **or-bound** rules.
//! In order for the filter to match, it is enough that one rule associated to the
//! system call matches. A system call may also map to an empty rule vector, which
//! means that the system call will match, regardless of the actual arguments.
//!
//! # Examples
//!
//! The following example defines and installs a simple Rust filter, that sends SIGSYS for
//! `accept4`, `fcntl(any, F_SETFD, FD_CLOEXEC, ..)` and `fcntl(any, F_GETFD, ...)`.
//! It allows any other syscalls.
//!
//! ```
//! use seccompiler::{
//! BpfProgram, SeccompAction, SeccompCmpArgLen, SeccompCmpOp, SeccompCondition, SeccompFilter,
//! SeccompRule,
//! };
//! use std::convert::TryInto;
//!
//! let filter: BpfProgram = SeccompFilter::new(
//! vec![
//! (libc::SYS_accept4, vec![]),
//! (
//! libc::SYS_fcntl,
//! vec![
//! SeccompRule::new(vec![
//! SeccompCondition::new(
//! 1,
//! SeccompCmpArgLen::Dword,
//! SeccompCmpOp::Eq,
//! libc::F_SETFD as u64,
//! )
//! .unwrap(),
//! SeccompCondition::new(
//! 2,
//! SeccompCmpArgLen::Dword,
//! SeccompCmpOp::Eq,
//! libc::FD_CLOEXEC as u64,
//! )
//! .unwrap(),
//! ])
//! .unwrap(),
//! SeccompRule::new(vec![SeccompCondition::new(
//! 1,
//! SeccompCmpArgLen::Dword,
//! SeccompCmpOp::Eq,
//! libc::F_GETFD as u64,
//! )
//! .unwrap()])
//! .unwrap(),
//! ],
//! ),
//! ]
//! .into_iter()
//! .collect(),
//! SeccompAction::Allow,
//! SeccompAction::Trap,
//! std::env::consts::ARCH.try_into().unwrap(),
//! )
//! .unwrap()
//! .try_into()
//! .unwrap();
//!
//! seccompiler::apply_filter(&filter).unwrap();
//! ```
//!
//!
//! This second example defines and installs an equivalent JSON filter (uses the `json` feature):
//!
//! ```
//! # #[cfg(feature = "json")]
//! # {
//! use seccompiler::BpfMap;
//! use std::convert::TryInto;
//!
//! let json_input = r#"{
//! "main_thread": {
//! "mismatch_action": "allow",
//! "match_action": "trap",
//! "filter": [
//! {
//! "syscall": "accept4"
//! },
//! {
//! "syscall": "fcntl",
//! "args": [
//! {
//! "index": 1,
//! "type": "dword",
//! "op": "eq",
//! "val": 2,
//! "comment": "F_SETFD"
//! },
//! {
//! "index": 2,
//! "type": "dword",
//! "op": "eq",
//! "val": 1,
//! "comment": "FD_CLOEXEC"
//! }
//! ]
//! },
//! {
//! "syscall": "fcntl",
//! "args": [
//! {
//! "index": 1,
//! "type": "dword",
//! "op": "eq",
//! "val": 1,
//! "comment": "F_GETFD"
//! }
//! ]
//! }
//! ]
//! }
//! }"#;
//!
//! let filter_map: BpfMap = seccompiler::compile_from_json(
//! json_input.as_bytes(),
//! std::env::consts::ARCH.try_into().unwrap(),
//! )
//! .unwrap();
//! let filter = filter_map.get("main_thread").unwrap();
//!
//! seccompiler::apply_filter(&filter).unwrap();
//!
//! # }
//! ```
//!
//! [`SeccompFilter`]: struct.SeccompFilter.html
//! [`SeccompCondition`]: struct.SeccompCondition.html
//! [`SeccompRule`]: struct.SeccompRule.html
//! [`SeccompAction`]: enum.SeccompAction.html
use TryInto;
use Read;
use HashMap;
use ;
use io;
use ;
// Re-export the IR public types.
pub use ;
// Until https://github.com/rust-lang/libc/issues/3342 is fixed, define locally
// From <linux/seccomp.h>
const SECCOMP_SET_MODE_FILTER: c_int = 1;
// BPF structure definition for filter array.
// See /usr/include/linux/filter.h .
/// Library Result type.
pub type Result<T> = Result;
///`BpfMap` is another type exposed by the library, which maps thread categories to BPF programs.
pub type BpfMap = ;
/// Library errors.
/// Apply a BPF filter to the calling thread.
///
/// # Arguments
///
/// * `bpf_filter` - A reference to the [`BpfProgram`] to be installed.
///
/// [`BpfProgram`]: type.BpfProgram.html
/// Apply a BPF filter to the all threads in the process via the TSYNC feature. Please read the
/// man page for seccomp (`man 2 seccomp`) for more information.
///
/// # Arguments
///
/// * `bpf_filter` - A reference to the [`BpfProgram`] to be installed.
///
/// [`BpfProgram`]: type.BpfProgram.html
/// Apply a BPF filter to the calling thread.
///
/// # Arguments
///
/// * `bpf_filter` - A reference to the [`BpfProgram`] to be installed.
/// * `flags` - A u64 representing a bitset of seccomp's flags parameter.
///
/// [`BpfProgram`]: type.BpfProgram.html
/// Compile [`BpfProgram`]s from JSON.
///
/// # Arguments
///
/// * `reader` - [`std::io::Read`] object containing the JSON data conforming to the
/// [JSON file format](https://github.com/rust-vmm/seccompiler/blob/master/docs/json_format.md).
/// * `arch` - target architecture of the filter.
///
/// [`BpfProgram`]: type.BpfProgram.html