oci_spec/runtime/
features.rs

1use std::collections::HashMap;
2
3use crate::{
4    error::OciSpecError,
5    runtime::{Arch, LinuxNamespaceType, LinuxSeccompAction},
6};
7use derive_builder::Builder;
8use getset::{Getters, MutGetters, Setters};
9use serde::{Deserialize, Serialize};
10
11/// Features represents supported features of the runtime.
12///
13/// This structure is used to report the supported features of the runtime to runtime callers.
14///
15#[derive(
16    Builder,
17    Clone,
18    Debug,
19    Default,
20    Deserialize,
21    Eq,
22    MutGetters,
23    Getters,
24    Setters,
25    PartialEq,
26    Serialize,
27)]
28#[serde(rename_all = "camelCase")]
29#[builder(
30    default,
31    pattern = "owned",
32    setter(into, strip_option),
33    build_fn(error = "OciSpecError")
34)]
35#[getset(get_mut = "pub", get = "pub", set = "pub")]
36pub struct Features {
37    /// The minimum OCI Runtime Spec version recognized by the runtime, e.g., "1.0.0".
38    oci_version_min: String,
39    /// The maximum OCI Runtime Spec version recognized by the runtime, e.g., "1.0.2-dev".
40    oci_version_max: String,
41    /// The list of the recognized hook names, e.g., "createRuntime".
42    /// "None" means "unknown", not "no support for any hook".
43    hooks: Option<Vec<String>>,
44    /// The list of the recognized mount options, e.g., "ro".
45    /// "None" means "unknown", not "no support for any mount option".
46    /// This list does not contain filesystem-specific options passed to mount(2) syscall as (const void *).
47    mount_options: Option<Vec<String>>,
48    /// Information specific to Linux
49    linux: Option<LinuxFeature>,
50    /// Implementation-specific annotation strings,
51    /// such as the implementation version, and third-party extensions.
52    annotations: Option<HashMap<String, String>>,
53    /// The list of the potential unsafe annotations
54    /// that may appear in `config.json`.
55    /// A value that ends with "." is interpreted as a prefix of annotations.
56    potentially_unsafe_config_annotations: Option<Vec<String>>,
57}
58
59/// Linux specific features.
60#[derive(
61    Builder,
62    Clone,
63    Debug,
64    Default,
65    Deserialize,
66    Eq,
67    MutGetters,
68    Getters,
69    Setters,
70    PartialEq,
71    Serialize,
72)]
73#[serde(rename_all = "camelCase")]
74#[builder(
75    default,
76    pattern = "owned",
77    setter(into, strip_option),
78    build_fn(error = "OciSpecError")
79)]
80#[getset(get_mut = "pub", get = "pub", set = "pub")]
81pub struct LinuxFeature {
82    /// The list of the recognized namespaces, e.g., "mount".
83    /// "None" means "unknown", not "no support for any namespace".
84    namespaces: Option<Vec<LinuxNamespaceType>>,
85    /// The list of the recognized capabilities , e.g., "CAP_SYS_ADMIN".
86    /// "None" means "unknown", not "no support for any capability".
87    capabilities: Option<Vec<String>>,
88    /// The available features related to cgroup.
89    cgroup: Option<Cgroup>,
90    /// The available features related to seccomp.
91    seccomp: Option<Seccomp>,
92    /// The available features related to apparmor.
93    apparmor: Option<Apparmor>,
94    /// The available features related to selinux.
95    selinux: Option<Selinux>,
96    /// The available features related to Intel RDT.
97    intel_rdt: Option<IntelRdt>,
98    /// The available features related to memory policy.
99    memory_policy: Option<MemoryPolicy>,
100    /// The available features related to mount extensions.
101    mount_extensions: Option<MountExtensions>,
102    /// The available features related to net devices.
103    net_devices: Option<NetDevices>,
104}
105
106/// Cgroup represents the "cgroup" field.
107#[derive(
108    Builder,
109    Clone,
110    Debug,
111    Default,
112    Deserialize,
113    Eq,
114    MutGetters,
115    Getters,
116    Setters,
117    PartialEq,
118    Serialize,
119)]
120#[serde(rename_all = "camelCase")]
121#[builder(
122    default,
123    pattern = "owned",
124    setter(into, strip_option),
125    build_fn(error = "OciSpecError")
126)]
127#[getset(get_mut = "pub", get = "pub", set = "pub")]
128pub struct Cgroup {
129    /// "v1" field represents whether Cgroup v1 support is compiled in.
130    /// Unrelated to whether the host uses cgroup v1 or not.
131    /// "None" means "unknown", not "false".
132    v1: Option<bool>,
133    /// "v2" field represents whether Cgroup v2 support is compiled in.
134    /// Unrelated to whether the host uses cgroup v2 or not.
135    /// "None" means "unknown", not "false".
136    v2: Option<bool>,
137    /// "systemd" field represents whether systemd-cgroup support is compiled in.
138    /// Unrelated to whether the host uses systemd or not.
139    /// "None" means "unknown", not "false".
140    systemd: Option<bool>,
141    /// "systemdUser" field represents whether user-scoped systemd-cgroup support is compiled in.
142    /// Unrelated to whether the host uses systemd or not.
143    /// "None" means "unknown", not "false".
144    systemd_user: Option<bool>,
145    /// "rdma" field represents whether RDMA cgroup support is compiled in.
146    /// Unrelated to whether the host supports it or not.
147    /// "None" means "unknown", not "false".
148    rdma: Option<bool>,
149}
150
151/// Seccomp represents the "seccomp" field.
152#[derive(
153    Builder,
154    Clone,
155    Debug,
156    Default,
157    Deserialize,
158    Eq,
159    MutGetters,
160    Getters,
161    Setters,
162    PartialEq,
163    Serialize,
164)]
165#[serde(rename_all = "camelCase")]
166#[builder(
167    default,
168    pattern = "owned",
169    setter(into, strip_option),
170    build_fn(error = "OciSpecError")
171)]
172#[getset(get_mut = "pub", get = "pub", set = "pub")]
173pub struct Seccomp {
174    /// "enabled" field represents whether seccomp support is compiled in.
175    /// "None" means "unknown", not "false".
176    enabled: Option<bool>,
177    /// "actions" field represents the list of the recognized actions.
178    /// "None" means "unknown", not "no support for any action".
179    actions: Option<Vec<LinuxSeccompAction>>,
180    /// "operators" field represents the list of the recognized operators.
181    /// "None" means "unknown", not "no support for any operator".
182    operators: Option<Vec<String>>,
183    /// "archs" field represents the list of the recognized architectures.
184    /// "None" means "unknown", not "no support for any architecture".
185    archs: Option<Vec<Arch>>,
186    /// "knownFlags" field represents the list of the recognized filter flags.
187    /// "None" means "unknown", not "no flags are recognized".
188    known_flags: Option<Vec<String>>,
189    /// "supportedFlags" field represents the list of the supported filter flags.
190    /// This list may be a subset of the "knownFlags" due to some of unsupported flags
191    /// by the current kernel and/or libseccomp.
192    /// "None" means "unknown", not "no flags are supported".
193    supported_flags: Option<Vec<String>>,
194}
195
196/// Apparmor represents the "apparmor" field.
197#[derive(
198    Builder,
199    Clone,
200    Debug,
201    Default,
202    Deserialize,
203    Eq,
204    MutGetters,
205    Getters,
206    Setters,
207    PartialEq,
208    Serialize,
209)]
210#[serde(rename_all = "camelCase")]
211#[builder(
212    default,
213    pattern = "owned",
214    setter(into, strip_option),
215    build_fn(error = "OciSpecError")
216)]
217#[getset(get_mut = "pub", get = "pub", set = "pub")]
218pub struct Apparmor {
219    /// "enabled" field represents whether AppArmor support is compiled in.
220    /// Unrelated to whether the host supports AppArmor or not.
221    /// "None" means "unknown", not "false".
222    enabled: Option<bool>,
223}
224
225/// Selinux represents the "selinux" field.
226#[derive(
227    Builder,
228    Clone,
229    Debug,
230    Default,
231    Deserialize,
232    Eq,
233    MutGetters,
234    Getters,
235    Setters,
236    PartialEq,
237    Serialize,
238)]
239#[serde(rename_all = "camelCase")]
240#[builder(
241    default,
242    pattern = "owned",
243    setter(into, strip_option),
244    build_fn(error = "OciSpecError")
245)]
246#[getset(get_mut = "pub", get = "pub", set = "pub")]
247pub struct Selinux {
248    /// "enabled" field represents whether SELinux support is compiled in.
249    /// Unrelated to whether the host supports SELinux or not.
250    /// "None" means "unknown", not "false".
251    enabled: Option<bool>,
252}
253
254/// IntelRdt represents the "intelRdt" field.
255#[derive(
256    Builder,
257    Clone,
258    Debug,
259    Default,
260    Deserialize,
261    Eq,
262    MutGetters,
263    Getters,
264    Setters,
265    PartialEq,
266    Serialize,
267)]
268#[serde(rename_all = "camelCase")]
269#[builder(
270    default,
271    pattern = "owned",
272    setter(into, strip_option),
273    build_fn(error = "OciSpecError")
274)]
275#[getset(get_mut = "pub", get = "pub", set = "pub")]
276pub struct IntelRdt {
277    /// "enabled" field represents whether Intel RDT support is compiled in.
278    /// Unrelated to whether the host supports Intel RDT or not.
279    enabled: Option<bool>,
280}
281
282/// MemoryPolicy represents the "memoryPolicy" field.
283#[derive(
284    Builder,
285    Clone,
286    Debug,
287    Default,
288    Deserialize,
289    Eq,
290    MutGetters,
291    Getters,
292    Setters,
293    PartialEq,
294    Serialize,
295)]
296#[serde(rename_all = "camelCase")]
297#[builder(
298    default,
299    pattern = "owned",
300    setter(into, strip_option),
301    build_fn(error = "OciSpecError")
302)]
303#[getset(get_mut = "pub", get = "pub", set = "pub")]
304pub struct MemoryPolicy {
305    /// modes is the list of known memory policy modes, e.g., "MPOL_INTERLEAVE".
306    modes: Option<Vec<String>>,
307    /// flags is the list of known memory policy mode flags, e.g., "MPOL_F_STATIC_NODES".
308    flags: Option<Vec<String>>,
309}
310
311/// MountExtensions represents the "mountExtensions" field.
312#[derive(
313    Builder,
314    Clone,
315    Debug,
316    Default,
317    Deserialize,
318    Eq,
319    MutGetters,
320    Getters,
321    Setters,
322    PartialEq,
323    Serialize,
324)]
325#[serde(rename_all = "camelCase")]
326#[builder(
327    default,
328    pattern = "owned",
329    setter(into, strip_option),
330    build_fn(error = "OciSpecError")
331)]
332#[getset(get_mut = "pub", get = "pub", set = "pub")]
333pub struct MountExtensions {
334    /// "idMap" field represents the ID mapping support.
335    idmap: Option<IDMap>,
336}
337
338/// NetDevices represents the "netDevices" field.
339#[derive(
340    Builder,
341    Clone,
342    Debug,
343    Default,
344    Deserialize,
345    Eq,
346    MutGetters,
347    Getters,
348    Setters,
349    PartialEq,
350    Serialize,
351)]
352#[serde(rename_all = "camelCase")]
353#[builder(
354    default,
355    pattern = "owned",
356    setter(into, strip_option),
357    build_fn(error = "OciSpecError")
358)]
359#[getset(get_mut = "pub", get = "pub", set = "pub")]
360pub struct NetDevices {
361    /// "enabled" field represents whether Net Devices support is compiled in.
362    /// Unrelated to whether the host supports Net Devices or not.
363    enabled: Option<bool>,
364}
365
366/// IDMap represents the "idmap" field.
367#[derive(
368    Builder,
369    Clone,
370    Debug,
371    Default,
372    Deserialize,
373    Eq,
374    MutGetters,
375    Getters,
376    Setters,
377    PartialEq,
378    Serialize,
379)]
380#[serde(rename_all = "camelCase")]
381#[builder(
382    default,
383    pattern = "owned",
384    setter(into, strip_option),
385    build_fn(error = "OciSpecError")
386)]
387#[getset(get_mut = "pub", get = "pub", set = "pub")]
388pub struct IDMap {
389    /// "enabled" field represents whether idmap mounts supports is compiled in.
390    /// Unrelated to whether the host supports it or not.
391    /// "None" means "unknown", not "false".
392    enabled: Option<bool>,
393}
394
395#[cfg(test)]
396mod tests {
397    use std::ops::Deref;
398
399    use super::*;
400
401    #[test]
402    fn test_parse_features() {
403        let example_json = r#"
404{
405    "ociVersionMin": "1.0.0",
406    "ociVersionMax": "1.1.0-rc.2",
407    "hooks": [
408        "prestart",
409        "createRuntime",
410        "createContainer",
411        "startContainer",
412        "poststart",
413        "poststop"
414    ],
415    "mountOptions": [
416        "async",
417        "atime",
418        "bind",
419        "defaults",
420        "dev",
421        "diratime",
422        "dirsync",
423        "exec",
424        "iversion",
425        "lazytime",
426        "loud",
427        "mand",
428        "noatime",
429        "nodev",
430        "nodiratime",
431        "noexec",
432        "noiversion",
433        "nolazytime",
434        "nomand",
435        "norelatime",
436        "nostrictatime",
437        "nosuid",
438        "nosymfollow",
439        "private",
440        "ratime",
441        "rbind",
442        "rdev",
443        "rdiratime",
444        "relatime",
445        "remount",
446        "rexec",
447        "rnoatime",
448        "rnodev",
449        "rnodiratime",
450        "rnoexec",
451        "rnorelatime",
452        "rnostrictatime",
453        "rnosuid",
454        "rnosymfollow",
455        "ro",
456        "rprivate",
457        "rrelatime",
458        "rro",
459        "rrw",
460        "rshared",
461        "rslave",
462        "rstrictatime",
463        "rsuid",
464        "rsymfollow",
465        "runbindable",
466        "rw",
467        "shared",
468        "silent",
469        "slave",
470        "strictatime",
471        "suid",
472        "symfollow",
473        "sync",
474        "tmpcopyup",
475        "unbindable"
476    ],
477    "linux": {
478        "namespaces": [
479            "cgroup",
480            "ipc",
481            "mount",
482            "network",
483            "pid",
484            "user",
485            "uts"
486        ],
487        "capabilities": [
488            "CAP_CHOWN",
489            "CAP_DAC_OVERRIDE",
490            "CAP_DAC_READ_SEARCH",
491            "CAP_FOWNER",
492            "CAP_FSETID",
493            "CAP_KILL",
494            "CAP_SETGID",
495            "CAP_SETUID",
496            "CAP_SETPCAP",
497            "CAP_LINUX_IMMUTABLE",
498            "CAP_NET_BIND_SERVICE",
499            "CAP_NET_BROADCAST",
500            "CAP_NET_ADMIN",
501            "CAP_NET_RAW",
502            "CAP_IPC_LOCK",
503            "CAP_IPC_OWNER",
504            "CAP_SYS_MODULE",
505            "CAP_SYS_RAWIO",
506            "CAP_SYS_CHROOT",
507            "CAP_SYS_PTRACE",
508            "CAP_SYS_PACCT",
509            "CAP_SYS_ADMIN",
510            "CAP_SYS_BOOT",
511            "CAP_SYS_NICE",
512            "CAP_SYS_RESOURCE",
513            "CAP_SYS_TIME",
514            "CAP_SYS_TTY_CONFIG",
515            "CAP_MKNOD",
516            "CAP_LEASE",
517            "CAP_AUDIT_WRITE",
518            "CAP_AUDIT_CONTROL",
519            "CAP_SETFCAP",
520            "CAP_MAC_OVERRIDE",
521            "CAP_MAC_ADMIN",
522            "CAP_SYSLOG",
523            "CAP_WAKE_ALARM",
524            "CAP_BLOCK_SUSPEND",
525            "CAP_AUDIT_READ",
526            "CAP_PERFMON",
527            "CAP_BPF",
528            "CAP_CHECKPOINT_RESTORE"
529        ],
530        "cgroup": {
531            "v1": true,
532            "v2": true,
533            "systemd": true,
534            "systemdUser": true,
535            "rdma": true
536        },
537        "seccomp": {
538            "enabled": true,
539            "actions": [
540                "SCMP_ACT_ALLOW",
541                "SCMP_ACT_ERRNO",
542                "SCMP_ACT_KILL",
543                "SCMP_ACT_KILL_PROCESS",
544                "SCMP_ACT_KILL_THREAD",
545                "SCMP_ACT_LOG",
546                "SCMP_ACT_NOTIFY",
547                "SCMP_ACT_TRACE",
548                "SCMP_ACT_TRAP"
549            ],
550            "operators": [
551                "SCMP_CMP_EQ",
552                "SCMP_CMP_GE",
553                "SCMP_CMP_GT",
554                "SCMP_CMP_LE",
555                "SCMP_CMP_LT",
556                "SCMP_CMP_MASKED_EQ",
557                "SCMP_CMP_NE"
558            ],
559            "archs": [
560                "SCMP_ARCH_AARCH64",
561                "SCMP_ARCH_ARM",
562                "SCMP_ARCH_MIPS",
563                "SCMP_ARCH_MIPS64",
564                "SCMP_ARCH_MIPS64N32",
565                "SCMP_ARCH_MIPSEL",
566                "SCMP_ARCH_MIPSEL64",
567                "SCMP_ARCH_MIPSEL64N32",
568                "SCMP_ARCH_PPC",
569                "SCMP_ARCH_PPC64",
570                "SCMP_ARCH_PPC64LE",
571                "SCMP_ARCH_RISCV64",
572                "SCMP_ARCH_S390",
573                "SCMP_ARCH_S390X",
574                "SCMP_ARCH_X32",
575                "SCMP_ARCH_X86",
576                "SCMP_ARCH_X86_64"
577            ],
578            "knownFlags": [
579                "SECCOMP_FILTER_FLAG_TSYNC",
580                "SECCOMP_FILTER_FLAG_SPEC_ALLOW",
581                "SECCOMP_FILTER_FLAG_LOG"
582            ],
583            "supportedFlags": [
584                "SECCOMP_FILTER_FLAG_TSYNC",
585                "SECCOMP_FILTER_FLAG_SPEC_ALLOW",
586                "SECCOMP_FILTER_FLAG_LOG"
587            ]
588        },
589        "apparmor": {
590            "enabled": true
591        },
592        "selinux": {
593            "enabled": true
594        },
595        "intelRdt": {
596            "enabled": true
597        },
598        "memoryPolicy": {
599            "modes": [
600                "MPOL_DEFAULT",
601                "MPOL_BIND",
602                "MPOL_INTERLEAVE",
603                "MPOL_WEIGHTED_INTERLEAVE",
604                "MPOL_PREFERRED",
605                "MPOL_PREFERRED_MANY",
606                "MPOL_LOCAL"
607            ],
608            "flags": [
609                "MPOL_F_NUMA_BALANCING",
610                "MPOL_F_RELATIVE_NODES",
611                "MPOL_F_STATIC_NODES"
612            ]
613        },
614        "netDevices": {
615            "enabled": true
616        }
617    },
618    "annotations": {
619        "io.github.seccomp.libseccomp.version": "2.5.4",
620        "org.opencontainers.runc.checkpoint.enabled": "true",
621        "org.opencontainers.runc.commit": "v1.1.0-534-g26851168",
622        "org.opencontainers.runc.version": "1.1.0+dev"
623    }
624}"#;
625
626        // Parse and check each field
627        let features: Features = serde_json::from_str(example_json).unwrap();
628        assert_eq!(features.oci_version_min().deref(), "1.0.0".to_string());
629        assert_eq!(features.oci_version_max().deref(), "1.1.0-rc.2".to_string());
630
631        assert_eq!(
632            features.hooks.as_ref().unwrap(),
633            &[
634                "prestart",
635                "createRuntime",
636                "createContainer",
637                "startContainer",
638                "poststart",
639                "poststop"
640            ]
641        );
642
643        assert_eq!(
644            features.mount_options.as_ref().unwrap(),
645            &[
646                "async",
647                "atime",
648                "bind",
649                "defaults",
650                "dev",
651                "diratime",
652                "dirsync",
653                "exec",
654                "iversion",
655                "lazytime",
656                "loud",
657                "mand",
658                "noatime",
659                "nodev",
660                "nodiratime",
661                "noexec",
662                "noiversion",
663                "nolazytime",
664                "nomand",
665                "norelatime",
666                "nostrictatime",
667                "nosuid",
668                "nosymfollow",
669                "private",
670                "ratime",
671                "rbind",
672                "rdev",
673                "rdiratime",
674                "relatime",
675                "remount",
676                "rexec",
677                "rnoatime",
678                "rnodev",
679                "rnodiratime",
680                "rnoexec",
681                "rnorelatime",
682                "rnostrictatime",
683                "rnosuid",
684                "rnosymfollow",
685                "ro",
686                "rprivate",
687                "rrelatime",
688                "rro",
689                "rrw",
690                "rshared",
691                "rslave",
692                "rstrictatime",
693                "rsuid",
694                "rsymfollow",
695                "runbindable",
696                "rw",
697                "shared",
698                "silent",
699                "slave",
700                "strictatime",
701                "suid",
702                "symfollow",
703                "sync",
704                "tmpcopyup",
705                "unbindable"
706            ]
707        );
708
709        let linux = features.linux().as_ref().unwrap();
710
711        assert_eq!(
712            linux.namespaces.as_ref().unwrap(),
713            &[
714                LinuxNamespaceType::Cgroup,
715                LinuxNamespaceType::Ipc,
716                LinuxNamespaceType::Mount,
717                LinuxNamespaceType::Network,
718                LinuxNamespaceType::Pid,
719                LinuxNamespaceType::User,
720                LinuxNamespaceType::Uts,
721            ]
722        );
723
724        assert_eq!(
725            linux.capabilities.as_ref().unwrap(),
726            &[
727                "CAP_CHOWN",
728                "CAP_DAC_OVERRIDE",
729                "CAP_DAC_READ_SEARCH",
730                "CAP_FOWNER",
731                "CAP_FSETID",
732                "CAP_KILL",
733                "CAP_SETGID",
734                "CAP_SETUID",
735                "CAP_SETPCAP",
736                "CAP_LINUX_IMMUTABLE",
737                "CAP_NET_BIND_SERVICE",
738                "CAP_NET_BROADCAST",
739                "CAP_NET_ADMIN",
740                "CAP_NET_RAW",
741                "CAP_IPC_LOCK",
742                "CAP_IPC_OWNER",
743                "CAP_SYS_MODULE",
744                "CAP_SYS_RAWIO",
745                "CAP_SYS_CHROOT",
746                "CAP_SYS_PTRACE",
747                "CAP_SYS_PACCT",
748                "CAP_SYS_ADMIN",
749                "CAP_SYS_BOOT",
750                "CAP_SYS_NICE",
751                "CAP_SYS_RESOURCE",
752                "CAP_SYS_TIME",
753                "CAP_SYS_TTY_CONFIG",
754                "CAP_MKNOD",
755                "CAP_LEASE",
756                "CAP_AUDIT_WRITE",
757                "CAP_AUDIT_CONTROL",
758                "CAP_SETFCAP",
759                "CAP_MAC_OVERRIDE",
760                "CAP_MAC_ADMIN",
761                "CAP_SYSLOG",
762                "CAP_WAKE_ALARM",
763                "CAP_BLOCK_SUSPEND",
764                "CAP_AUDIT_READ",
765                "CAP_PERFMON",
766                "CAP_BPF",
767                "CAP_CHECKPOINT_RESTORE"
768            ],
769        );
770
771        assert_eq!(
772            linux.cgroup.as_ref().unwrap(),
773            &Cgroup {
774                v1: Some(true),
775                v2: Some(true),
776                systemd: Some(true),
777                systemd_user: Some(true),
778                rdma: Some(true),
779            }
780        );
781
782        assert_eq!(
783            linux.seccomp.as_ref().unwrap(),
784            &Seccomp {
785                enabled: Some(true),
786                actions: Some(vec![
787                    LinuxSeccompAction::ScmpActAllow,
788                    LinuxSeccompAction::ScmpActErrno,
789                    LinuxSeccompAction::ScmpActKill,
790                    LinuxSeccompAction::ScmpActKillProcess,
791                    LinuxSeccompAction::ScmpActKillThread,
792                    LinuxSeccompAction::ScmpActLog,
793                    LinuxSeccompAction::ScmpActNotify,
794                    LinuxSeccompAction::ScmpActTrace,
795                    LinuxSeccompAction::ScmpActTrap
796                ]),
797                operators: Some(vec![
798                    "SCMP_CMP_EQ".to_string(),
799                    "SCMP_CMP_GE".to_string(),
800                    "SCMP_CMP_GT".to_string(),
801                    "SCMP_CMP_LE".to_string(),
802                    "SCMP_CMP_LT".to_string(),
803                    "SCMP_CMP_MASKED_EQ".to_string(),
804                    "SCMP_CMP_NE".to_string()
805                ]),
806                archs: Some(vec![
807                    Arch::ScmpArchAarch64,
808                    Arch::ScmpArchArm,
809                    Arch::ScmpArchMips,
810                    Arch::ScmpArchMips64,
811                    Arch::ScmpArchMips64n32,
812                    Arch::ScmpArchMipsel,
813                    Arch::ScmpArchMipsel64,
814                    Arch::ScmpArchMipsel64n32,
815                    Arch::ScmpArchPpc,
816                    Arch::ScmpArchPpc64,
817                    Arch::ScmpArchPpc64le,
818                    Arch::ScmpArchRiscv64,
819                    Arch::ScmpArchS390,
820                    Arch::ScmpArchS390x,
821                    Arch::ScmpArchX32,
822                    Arch::ScmpArchX86,
823                    Arch::ScmpArchX86_64,
824                ]),
825                known_flags: Some(vec![
826                    "SECCOMP_FILTER_FLAG_TSYNC".to_string(),
827                    "SECCOMP_FILTER_FLAG_SPEC_ALLOW".to_string(),
828                    "SECCOMP_FILTER_FLAG_LOG".to_string()
829                ]),
830                supported_flags: Some(vec![
831                    "SECCOMP_FILTER_FLAG_TSYNC".to_string(),
832                    "SECCOMP_FILTER_FLAG_SPEC_ALLOW".to_string(),
833                    "SECCOMP_FILTER_FLAG_LOG".to_string()
834                ])
835            },
836        );
837
838        assert_eq!(
839            linux.apparmor.as_ref().unwrap(),
840            &Apparmor {
841                enabled: Some(true)
842            }
843        );
844
845        assert_eq!(
846            linux.selinux.as_ref().unwrap(),
847            &Selinux {
848                enabled: Some(true)
849            }
850        );
851
852        assert_eq!(
853            linux.intel_rdt.as_ref().unwrap(),
854            &IntelRdt {
855                enabled: Some(true)
856            }
857        );
858
859        assert_eq!(
860            linux.memory_policy.as_ref().unwrap(),
861            &MemoryPolicy {
862                modes: Some(vec![
863                    "MPOL_DEFAULT".to_string(),
864                    "MPOL_BIND".to_string(),
865                    "MPOL_INTERLEAVE".to_string(),
866                    "MPOL_WEIGHTED_INTERLEAVE".to_string(),
867                    "MPOL_PREFERRED".to_string(),
868                    "MPOL_PREFERRED_MANY".to_string(),
869                    "MPOL_LOCAL".to_string(),
870                ]),
871                flags: Some(vec![
872                    "MPOL_F_NUMA_BALANCING".to_string(),
873                    "MPOL_F_RELATIVE_NODES".to_string(),
874                    "MPOL_F_STATIC_NODES".to_string(),
875                ]),
876            }
877        );
878
879        assert_eq!(
880            linux.net_devices.as_ref().unwrap(),
881            &NetDevices {
882                enabled: Some(true)
883            }
884        );
885
886        assert_eq!(
887            features.annotations().as_ref().unwrap(),
888            &[
889                (
890                    "io.github.seccomp.libseccomp.version".to_string(),
891                    "2.5.4".to_string()
892                ),
893                (
894                    "org.opencontainers.runc.checkpoint.enabled".to_string(),
895                    "true".to_string()
896                ),
897                (
898                    "org.opencontainers.runc.commit".to_string(),
899                    "v1.1.0-534-g26851168".to_string()
900                ),
901                (
902                    "org.opencontainers.runc.version".to_string(),
903                    "1.1.0+dev".to_string()
904                )
905            ]
906            .iter()
907            .cloned()
908            .collect()
909        );
910
911        assert_eq!(
912            features.potentially_unsafe_config_annotations().as_ref(),
913            None,
914        );
915    }
916}