libseccomp/
arch.rs

1// SPDX-License-Identifier: Apache-2.0 or MIT
2//
3// Copyright 2021 Sony Group Corporation
4//
5
6use crate::error::ErrorKind::*;
7use crate::error::{Result, SeccompError};
8use libseccomp_sys::*;
9use std::str::FromStr;
10
11/// Represents a CPU architecture.
12/// Seccomp can restrict syscalls on a per-architecture basis.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
14#[non_exhaustive]
15pub enum ScmpArch {
16    /// The native architecture token
17    Native,
18    /// The x86 (32-bit) architecture token
19    X86,
20    /// The x86-64 (64-bit) architecture token
21    X8664,
22    /// The x32 (32-bit x86_64) architecture token
23    X32,
24    /// The ARM architecture token
25    Arm,
26    /// The AARCH64 architecture token
27    Aarch64,
28    /// The LoongArch architecture token
29    Loongarch64,
30    /// The Motorola 68000 architecture token
31    M68k,
32    /// The MIPS architecture token
33    Mips,
34    /// The MIPS (64-bit) architecture token
35    Mips64,
36    /// The MIPS64N32 architecture token
37    Mips64N32,
38    /// The MIPSEL architecture token
39    Mipsel,
40    /// The MIPSEL (64-bit) architecture token
41    Mipsel64,
42    /// The MIPSEL64N32 architecture token
43    Mipsel64N32,
44    /// The PowerPC architecture token
45    Ppc,
46    /// The PowerPC (64-bit) architecture token
47    Ppc64,
48    /// The PowerPC64LE architecture token
49    Ppc64Le,
50    /// The S390 architecture token
51    S390,
52    /// The S390X architecture token
53    S390X,
54    /// The PA-RISC hppa architecture token
55    Parisc,
56    /// The PA-RISC (64-bit) hppa architecture token
57    Parisc64,
58    /// The RISC-V architecture token
59    Riscv64,
60    /// The SuperH (big-endian) architecture token
61    Sheb,
62    /// The SuperH (little-endian) architecture token
63    Sh,
64}
65
66impl ScmpArch {
67    pub(crate) fn to_sys(self) -> u32 {
68        match self {
69            Self::Native => SCMP_ARCH_NATIVE,
70            Self::X86 => SCMP_ARCH_X86,
71            Self::X8664 => SCMP_ARCH_X86_64,
72            Self::X32 => SCMP_ARCH_X32,
73            Self::Arm => SCMP_ARCH_ARM,
74            Self::Aarch64 => SCMP_ARCH_AARCH64,
75            Self::Loongarch64 => SCMP_ARCH_LOONGARCH64,
76            Self::M68k => SCMP_ARCH_M68K,
77            Self::Mips => SCMP_ARCH_MIPS,
78            Self::Mips64 => SCMP_ARCH_MIPS64,
79            Self::Mips64N32 => SCMP_ARCH_MIPS64N32,
80            Self::Mipsel => SCMP_ARCH_MIPSEL,
81            Self::Mipsel64 => SCMP_ARCH_MIPSEL64,
82            Self::Mipsel64N32 => SCMP_ARCH_MIPSEL64N32,
83            Self::Ppc => SCMP_ARCH_PPC,
84            Self::Ppc64 => SCMP_ARCH_PPC64,
85            Self::Ppc64Le => SCMP_ARCH_PPC64LE,
86            Self::S390 => SCMP_ARCH_S390,
87            Self::S390X => SCMP_ARCH_S390X,
88            Self::Parisc => SCMP_ARCH_PARISC,
89            Self::Parisc64 => SCMP_ARCH_PARISC64,
90            Self::Riscv64 => SCMP_ARCH_RISCV64,
91            Self::Sheb => SCMP_ARCH_SHEB,
92            Self::Sh => SCMP_ARCH_SH,
93        }
94    }
95
96    pub(crate) fn from_sys(arch: u32) -> Result<Self> {
97        match arch {
98            SCMP_ARCH_NATIVE => Ok(Self::Native),
99            SCMP_ARCH_X86 => Ok(Self::X86),
100            SCMP_ARCH_X86_64 => Ok(Self::X8664),
101            SCMP_ARCH_X32 => Ok(Self::X32),
102            SCMP_ARCH_ARM => Ok(Self::Arm),
103            SCMP_ARCH_AARCH64 => Ok(Self::Aarch64),
104            SCMP_ARCH_LOONGARCH64 => Ok(Self::Loongarch64),
105            SCMP_ARCH_M68K => Ok(Self::M68k),
106            SCMP_ARCH_MIPS => Ok(Self::Mips),
107            SCMP_ARCH_MIPS64 => Ok(Self::Mips64),
108            SCMP_ARCH_MIPS64N32 => Ok(Self::Mips64N32),
109            SCMP_ARCH_MIPSEL => Ok(Self::Mipsel),
110            SCMP_ARCH_MIPSEL64 => Ok(Self::Mipsel64),
111            SCMP_ARCH_MIPSEL64N32 => Ok(Self::Mipsel64N32),
112            SCMP_ARCH_PPC => Ok(Self::Ppc),
113            SCMP_ARCH_PPC64 => Ok(Self::Ppc64),
114            SCMP_ARCH_PPC64LE => Ok(Self::Ppc64Le),
115            SCMP_ARCH_S390 => Ok(Self::S390),
116            SCMP_ARCH_S390X => Ok(Self::S390X),
117            SCMP_ARCH_PARISC => Ok(Self::Parisc),
118            SCMP_ARCH_PARISC64 => Ok(Self::Parisc64),
119            SCMP_ARCH_RISCV64 => Ok(Self::Riscv64),
120            SCMP_ARCH_SHEB => Ok(Self::Sheb),
121            SCMP_ARCH_SH => Ok(Self::Sh),
122            _ => Err(SeccompError::new(InvalidArch(arch))),
123        }
124    }
125
126    /// Returns the system's native architecture.
127    ///
128    /// This function corresponds to
129    /// [`seccomp_arch_native`](https://man7.org/linux/man-pages/man3/seccomp_arch_native.3.html).
130    ///
131    /// # Panics
132    ///
133    /// This function panics if it can not get the native architecture.
134    pub fn native() -> Self {
135        Self::from_sys(unsafe { seccomp_arch_native() }).expect("Could not get native architecture")
136    }
137}
138
139impl FromStr for ScmpArch {
140    type Err = SeccompError;
141
142    /// Converts string seccomp architecture to `ScmpArch`.
143    ///
144    /// # Arguments
145    ///
146    /// * `arch` - A string architecture, e.g. `SCMP_ARCH_*`.
147    ///
148    /// See the [`seccomp_arch_add(3)`] man page for details on valid architecture values.
149    ///
150    /// [`seccomp_arch_add(3)`]: https://www.man7.org/linux/man-pages/man3/seccomp_arch_add.3.html
151    ///
152    /// # Errors
153    ///
154    /// If an invalid architecture is specified, an error will be returned.
155    fn from_str(arch: &str) -> Result<Self> {
156        match arch {
157            "SCMP_ARCH_NATIVE" => Ok(Self::Native),
158            "SCMP_ARCH_X86" => Ok(Self::X86),
159            "SCMP_ARCH_X86_64" => Ok(Self::X8664),
160            "SCMP_ARCH_X32" => Ok(Self::X32),
161            "SCMP_ARCH_ARM" => Ok(Self::Arm),
162            "SCMP_ARCH_AARCH64" => Ok(Self::Aarch64),
163            "SCMP_ARCH_LOONGARCH64" => Ok(Self::Loongarch64),
164            "SCMP_ARCH_M68K" => Ok(Self::M68k),
165            "SCMP_ARCH_MIPS" => Ok(Self::Mips),
166            "SCMP_ARCH_MIPS64" => Ok(Self::Mips64),
167            "SCMP_ARCH_MIPS64N32" => Ok(Self::Mips64N32),
168            "SCMP_ARCH_MIPSEL" => Ok(Self::Mipsel),
169            "SCMP_ARCH_MIPSEL64" => Ok(Self::Mipsel64),
170            "SCMP_ARCH_MIPSEL64N32" => Ok(Self::Mipsel64N32),
171            "SCMP_ARCH_PPC" => Ok(Self::Ppc),
172            "SCMP_ARCH_PPC64" => Ok(Self::Ppc64),
173            "SCMP_ARCH_PPC64LE" => Ok(Self::Ppc64Le),
174            "SCMP_ARCH_S390" => Ok(Self::S390),
175            "SCMP_ARCH_S390X" => Ok(Self::S390X),
176            "SCMP_ARCH_PARISC" => Ok(Self::Parisc),
177            "SCMP_ARCH_PARISC64" => Ok(Self::Parisc64),
178            "SCMP_ARCH_RISCV64" => Ok(Self::Riscv64),
179            "SCMP_ARCH_SHEB" => Ok(Self::Sheb),
180            "SCMP_ARCH_SH" => Ok(Self::Sh),
181            _ => Err(SeccompError::new(FromStr(arch.to_string()))),
182        }
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use super::*;
189
190    #[test]
191    fn test_parse_arch() {
192        let test_data = &[
193            ("SCMP_ARCH_NATIVE", ScmpArch::Native),
194            ("SCMP_ARCH_X86", ScmpArch::X86),
195            ("SCMP_ARCH_X86_64", ScmpArch::X8664),
196            ("SCMP_ARCH_X32", ScmpArch::X32),
197            ("SCMP_ARCH_ARM", ScmpArch::Arm),
198            ("SCMP_ARCH_AARCH64", ScmpArch::Aarch64),
199            ("SCMP_ARCH_LOONGARCH64", ScmpArch::Loongarch64),
200            ("SCMP_ARCH_M68K", ScmpArch::M68k),
201            ("SCMP_ARCH_MIPS", ScmpArch::Mips),
202            ("SCMP_ARCH_MIPS64", ScmpArch::Mips64),
203            ("SCMP_ARCH_MIPS64N32", ScmpArch::Mips64N32),
204            ("SCMP_ARCH_MIPSEL", ScmpArch::Mipsel),
205            ("SCMP_ARCH_MIPSEL64", ScmpArch::Mipsel64),
206            ("SCMP_ARCH_MIPSEL64N32", ScmpArch::Mipsel64N32),
207            ("SCMP_ARCH_PPC", ScmpArch::Ppc),
208            ("SCMP_ARCH_PPC64", ScmpArch::Ppc64),
209            ("SCMP_ARCH_PPC64LE", ScmpArch::Ppc64Le),
210            ("SCMP_ARCH_S390", ScmpArch::S390),
211            ("SCMP_ARCH_S390X", ScmpArch::S390X),
212            ("SCMP_ARCH_PARISC", ScmpArch::Parisc),
213            ("SCMP_ARCH_PARISC64", ScmpArch::Parisc64),
214            ("SCMP_ARCH_RISCV64", ScmpArch::Riscv64),
215            ("SCMP_ARCH_SHEB", ScmpArch::Sheb),
216            ("SCMP_ARCH_SH", ScmpArch::Sh),
217        ];
218
219        for data in test_data {
220            assert_eq!(
221                ScmpArch::from_sys(ScmpArch::from_str(data.0).unwrap().to_sys()).unwrap(),
222                data.1
223            );
224        }
225        assert!(ScmpArch::from_str("SCMP_INVALID_FLAG").is_err());
226        assert!(ScmpArch::from_sys(1).is_err());
227    }
228}