1use crate::error::{oci_error, OciSpecError};
2
3use derive_builder::Builder;
4use getset::{CopyGetters, Getters, MutGetters, Setters};
5use serde::{Deserialize, Serialize};
6use std::{collections::HashMap, fmt::Display, path::PathBuf, vec};
7use strum_macros::{Display as StrumDisplay, EnumString};
8
9#[derive(
10 Builder, Clone, Debug, Deserialize, Eq, Getters, MutGetters, Setters, PartialEq, Serialize,
11)]
12#[serde(rename_all = "camelCase")]
13#[builder(
14 default,
15 pattern = "owned",
16 setter(into, strip_option),
17 build_fn(error = "OciSpecError")
18)]
19#[getset(get_mut = "pub", get = "pub", set = "pub")]
20pub struct Linux {
23 #[serde(default, skip_serializing_if = "Option::is_none")]
24 uid_mappings: Option<Vec<LinuxIdMapping>>,
26
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 gid_mappings: Option<Vec<LinuxIdMapping>>,
30
31 #[serde(default, skip_serializing_if = "Option::is_none")]
32 sysctl: Option<HashMap<String, String>>,
35
36 #[serde(default, skip_serializing_if = "Option::is_none")]
37 resources: Option<LinuxResources>,
40
41 #[serde(default, skip_serializing_if = "Option::is_none")]
42 cgroups_path: Option<PathBuf>,
47
48 #[serde(default, skip_serializing_if = "Option::is_none")]
49 namespaces: Option<Vec<LinuxNamespace>>,
52
53 #[serde(default, skip_serializing_if = "Option::is_none")]
54 devices: Option<Vec<LinuxDevice>>,
57
58 #[serde(default, skip_serializing_if = "Option::is_none")]
59 seccomp: Option<LinuxSeccomp>,
61
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 rootfs_propagation: Option<String>,
66
67 #[serde(default, skip_serializing_if = "Option::is_none")]
68 masked_paths: Option<Vec<String>>,
70
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 readonly_paths: Option<Vec<String>>,
74
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 mount_label: Option<String>,
79
80 #[serde(default, skip_serializing_if = "Option::is_none")]
81 intel_rdt: Option<LinuxIntelRdt>,
85
86 #[serde(default, skip_serializing_if = "Option::is_none")]
87 personality: Option<LinuxPersonality>,
90
91 #[serde(default, skip_serializing_if = "Option::is_none")]
92 time_offsets: Option<HashMap<String, String>>,
94}
95
96impl Default for Linux {
98 fn default() -> Self {
99 Linux {
100 uid_mappings: Default::default(),
102 gid_mappings: Default::default(),
104 sysctl: Default::default(),
106 resources: Some(LinuxResources {
107 devices: vec![].into(),
108 memory: Default::default(),
109 cpu: Default::default(),
110 pids: Default::default(),
111 block_io: Default::default(),
112 hugepage_limits: Default::default(),
113 network: Default::default(),
114 rdma: Default::default(),
115 unified: Default::default(),
116 }),
117 cgroups_path: Default::default(),
119 namespaces: get_default_namespaces().into(),
120 devices: Default::default(),
122 rootfs_propagation: Default::default(),
124 masked_paths: get_default_maskedpaths().into(),
125 readonly_paths: get_default_readonly_paths().into(),
126 mount_label: Default::default(),
128 seccomp: None,
129 intel_rdt: None,
130 personality: None,
131 time_offsets: None,
132 }
133 }
134}
135
136impl Linux {
137 pub fn rootless(uid: u32, gid: u32) -> Self {
139 let mut namespaces = get_default_namespaces();
140 namespaces.retain(|ns| ns.typ != LinuxNamespaceType::Network);
141 namespaces.push(LinuxNamespace {
142 typ: LinuxNamespaceType::User,
143 ..Default::default()
144 });
145 Self {
146 resources: None,
147 uid_mappings: Some(vec![LinuxIdMapping {
148 container_id: 0,
149 host_id: uid,
150 size: 1,
151 }]),
152 gid_mappings: Some(vec![LinuxIdMapping {
153 container_id: 0,
154 host_id: gid,
155 size: 1,
156 }]),
157 namespaces: Some(namespaces),
158 ..Default::default()
159 }
160 }
161}
162
163#[derive(
164 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
165)]
166#[serde(rename_all = "camelCase")]
167#[builder(
168 default,
169 pattern = "owned",
170 setter(into, strip_option),
171 build_fn(error = "OciSpecError")
172)]
173#[getset(get_copy = "pub", set = "pub")]
174pub struct LinuxIdMapping {
176 #[serde(default, rename = "hostID")]
177 host_id: u32,
180
181 #[serde(default, rename = "containerID")]
182 container_id: u32,
184
185 #[serde(default)]
186 size: u32,
188}
189
190#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, EnumString)]
191#[strum(serialize_all = "lowercase")]
192#[serde(rename_all = "lowercase")]
193pub enum LinuxDeviceType {
195 A,
197
198 B,
200
201 C,
203
204 U,
206
207 P,
209}
210
211#[allow(clippy::derivable_impls)] impl Default for LinuxDeviceType {
213 fn default() -> LinuxDeviceType {
214 LinuxDeviceType::A
215 }
216}
217
218impl LinuxDeviceType {
219 pub fn as_str(&self) -> &str {
221 match self {
222 Self::A => "a",
223 Self::B => "b",
224 Self::C => "c",
225 Self::U => "u",
226 Self::P => "p",
227 }
228 }
229}
230
231#[derive(
232 Builder,
233 Clone,
234 CopyGetters,
235 Debug,
236 Default,
237 Deserialize,
238 Eq,
239 Getters,
240 MutGetters,
241 Setters,
242 PartialEq,
243 Serialize,
244)]
245#[builder(
246 default,
247 pattern = "owned",
248 setter(into, strip_option),
249 build_fn(error = "OciSpecError")
250)]
251pub struct LinuxDeviceCgroup {
254 #[serde(default)]
255 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
256 allow: bool,
258
259 #[serde(default, rename = "type", skip_serializing_if = "Option::is_none")]
260 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
261 typ: Option<LinuxDeviceType>,
263
264 #[serde(default, skip_serializing_if = "Option::is_none")]
265 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
266 major: Option<i64>,
268
269 #[serde(default, skip_serializing_if = "Option::is_none")]
270 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
271 minor: Option<i64>,
273
274 #[serde(default)]
276 #[getset(get_mut = "pub", get = "pub", set = "pub")]
277 access: Option<String>,
278}
279
280impl Display for LinuxDeviceCgroup {
284 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
285 let major = self
286 .major
287 .map(|mj| mj.to_string())
288 .unwrap_or_else(|| "*".to_string());
289 let minor = self
290 .minor
291 .map(|mi| mi.to_string())
292 .unwrap_or_else(|| "*".to_string());
293 let access = self.access.as_deref().unwrap_or("");
294 write!(
295 f,
296 "{} {}:{} {}",
297 &self.typ.unwrap_or_default().as_str(),
298 &major,
299 &minor,
300 &access
301 )
302 }
303}
304
305#[derive(
306 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
307)]
308#[serde(rename_all = "camelCase")]
309#[builder(
310 default,
311 pattern = "owned",
312 setter(into, strip_option),
313 build_fn(error = "OciSpecError")
314)]
315#[getset(get_copy = "pub", set = "pub")]
316pub struct LinuxMemory {
318 #[serde(skip_serializing_if = "Option::is_none")]
319 #[getset(get_copy = "pub", set = "pub")]
320 limit: Option<i64>,
322
323 #[serde(skip_serializing_if = "Option::is_none")]
324 #[getset(get_copy = "pub", set = "pub")]
325 reservation: Option<i64>,
327
328 #[serde(skip_serializing_if = "Option::is_none")]
329 #[getset(get_copy = "pub", set = "pub")]
330 swap: Option<i64>,
332
333 #[serde(skip_serializing_if = "Option::is_none")]
334 #[getset(get_copy = "pub", set = "pub")]
335 kernel: Option<i64>,
337
338 #[serde(skip_serializing_if = "Option::is_none", rename = "kernelTCP")]
339 #[getset(get_copy = "pub", set = "pub")]
340 kernel_tcp: Option<i64>,
342
343 #[serde(skip_serializing_if = "Option::is_none")]
344 #[getset(get_copy = "pub", set = "pub")]
345 swappiness: Option<u64>,
347
348 #[serde(skip_serializing_if = "Option::is_none", rename = "disableOOMKiller")]
349 #[getset(get_copy = "pub", set = "pub")]
350 disable_oom_killer: Option<bool>,
353
354 #[serde(skip_serializing_if = "Option::is_none")]
355 #[getset(get_copy = "pub", set = "pub")]
356 use_hierarchy: Option<bool>,
358
359 #[serde(skip_serializing_if = "Option::is_none")]
360 #[getset(get_copy = "pub", set = "pub")]
361 check_before_update: Option<bool>,
363}
364
365#[derive(
366 Builder,
367 Clone,
368 CopyGetters,
369 Debug,
370 Default,
371 Deserialize,
372 Eq,
373 Getters,
374 Setters,
375 PartialEq,
376 Serialize,
377)]
378#[serde(rename_all = "camelCase")]
379#[builder(
380 default,
381 pattern = "owned",
382 setter(into, strip_option),
383 build_fn(error = "OciSpecError")
384)]
385pub struct LinuxCpu {
387 #[serde(skip_serializing_if = "Option::is_none")]
388 #[getset(get_copy = "pub", set = "pub")]
389 shares: Option<u64>,
392
393 #[serde(skip_serializing_if = "Option::is_none")]
394 #[getset(get_copy = "pub", set = "pub")]
395 quota: Option<i64>,
397
398 #[serde(skip_serializing_if = "Option::is_none")]
399 #[getset(get_copy = "pub", set = "pub")]
400 idle: Option<i64>,
402
403 #[serde(skip_serializing_if = "Option::is_none")]
404 #[getset(get_copy = "pub", set = "pub")]
405 burst: Option<u64>,
408
409 #[serde(skip_serializing_if = "Option::is_none")]
410 #[getset(get_copy = "pub", set = "pub")]
411 period: Option<u64>,
413
414 #[serde(skip_serializing_if = "Option::is_none")]
415 #[getset(get_copy = "pub", set = "pub")]
416 realtime_runtime: Option<i64>,
418
419 #[serde(skip_serializing_if = "Option::is_none")]
420 #[getset(get_copy = "pub", set = "pub")]
421 realtime_period: Option<u64>,
423
424 #[serde(default, skip_serializing_if = "Option::is_none")]
425 #[getset(get = "pub", set = "pub")]
426 cpus: Option<String>,
428
429 #[serde(default, skip_serializing_if = "Option::is_none")]
430 #[getset(get = "pub", set = "pub")]
431 mems: Option<String>,
434}
435
436#[derive(
437 Builder,
438 Clone,
439 Copy,
440 Debug,
441 Default,
442 Deserialize,
443 Eq,
444 CopyGetters,
445 Setters,
446 PartialEq,
447 Serialize,
448)]
449#[builder(
450 default,
451 pattern = "owned",
452 setter(into, strip_option),
453 build_fn(error = "OciSpecError")
454)]
455#[getset(get_copy = "pub", set = "pub")]
456pub struct LinuxPids {
458 #[serde(default)]
459 limit: i64,
461}
462
463#[derive(
464 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
465)]
466#[serde(rename_all = "camelCase")]
467#[builder(
468 default,
469 pattern = "owned",
470 setter(into, strip_option),
471 build_fn(error = "OciSpecError")
472)]
473#[getset(get_copy = "pub", set = "pub")]
474pub struct LinuxWeightDevice {
477 #[serde(default)]
478 major: i64,
480
481 #[serde(default)]
482 minor: i64,
484
485 #[serde(skip_serializing_if = "Option::is_none")]
486 weight: Option<u16>,
488
489 #[serde(skip_serializing_if = "Option::is_none")]
490 leaf_weight: Option<u16>,
493}
494
495#[derive(
496 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
497)]
498#[builder(
499 default,
500 pattern = "owned",
501 setter(into, strip_option),
502 build_fn(error = "OciSpecError")
503)]
504#[getset(get_copy = "pub", set = "pub")]
505pub struct LinuxThrottleDevice {
507 #[serde(default)]
508 major: i64,
510
511 #[serde(default)]
512 minor: i64,
514
515 #[serde(default)]
516 rate: u64,
518}
519
520#[derive(
521 Builder,
522 Clone,
523 CopyGetters,
524 Debug,
525 Default,
526 Deserialize,
527 Eq,
528 Getters,
529 Setters,
530 PartialEq,
531 Serialize,
532)]
533#[serde(rename_all = "camelCase")]
534#[builder(
535 default,
536 pattern = "owned",
537 setter(into, strip_option),
538 build_fn(error = "OciSpecError")
539)]
540pub struct LinuxBlockIo {
542 #[serde(skip_serializing_if = "Option::is_none")]
543 #[getset(get_copy = "pub", set = "pub")]
544 weight: Option<u16>,
546
547 #[serde(skip_serializing_if = "Option::is_none")]
548 #[getset(get_copy = "pub", set = "pub")]
549 leaf_weight: Option<u16>,
552
553 #[serde(skip_serializing_if = "Option::is_none")]
554 #[getset(get = "pub", set = "pub")]
555 weight_device: Option<Vec<LinuxWeightDevice>>,
557
558 #[serde(skip_serializing_if = "Option::is_none")]
559 #[getset(get = "pub", set = "pub")]
560 throttle_read_bps_device: Option<Vec<LinuxThrottleDevice>>,
562
563 #[serde(skip_serializing_if = "Option::is_none")]
564 #[getset(get = "pub", set = "pub")]
565 throttle_write_bps_device: Option<Vec<LinuxThrottleDevice>>,
567
568 #[serde(skip_serializing_if = "Option::is_none")]
569 #[getset(get = "pub", set = "pub")]
570 throttle_read_iops_device: Option<Vec<LinuxThrottleDevice>>,
572
573 #[serde(skip_serializing_if = "Option::is_none")]
574 #[getset(get = "pub", set = "pub")]
575 throttle_write_iops_device: Option<Vec<LinuxThrottleDevice>>,
577}
578
579#[derive(
580 Builder,
581 Clone,
582 CopyGetters,
583 Debug,
584 Default,
585 Deserialize,
586 Eq,
587 Getters,
588 Setters,
589 PartialEq,
590 Serialize,
591)]
592#[serde(rename_all = "camelCase")]
593#[builder(
594 default,
595 pattern = "owned",
596 setter(into, strip_option),
597 build_fn(error = "OciSpecError")
598)]
599pub struct LinuxHugepageLimit {
602 #[serde(default)]
603 #[getset(get = "pub", set = "pub")]
604 page_size: String,
607
608 #[serde(default)]
609 #[getset(get_copy = "pub", set = "pub")]
610 limit: i64,
612}
613
614#[derive(
615 Builder,
616 Clone,
617 CopyGetters,
618 Debug,
619 Default,
620 Deserialize,
621 Eq,
622 Getters,
623 Setters,
624 PartialEq,
625 Serialize,
626)]
627#[builder(
628 default,
629 pattern = "owned",
630 setter(into, strip_option),
631 build_fn(error = "OciSpecError")
632)]
633pub struct LinuxInterfacePriority {
635 #[serde(default)]
636 #[getset(get = "pub", set = "pub")]
637 name: String,
639
640 #[serde(default)]
641 #[getset(get_copy = "pub", set = "pub")]
642 priority: u32,
644}
645
646impl Display for LinuxInterfacePriority {
650 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
651 writeln!(f, "{} {}", self.name, self.priority)
654 }
655}
656
657#[derive(
658 Builder,
659 Clone,
660 CopyGetters,
661 Debug,
662 Default,
663 Deserialize,
664 Eq,
665 Getters,
666 Setters,
667 PartialEq,
668 Serialize,
669)]
670#[builder(
671 default,
672 pattern = "owned",
673 setter(into, strip_option),
674 build_fn(error = "OciSpecError")
675)]
676pub struct LinuxNetwork {
678 #[serde(skip_serializing_if = "Option::is_none", rename = "classID")]
679 #[getset(get_copy = "pub", set = "pub")]
680 class_id: Option<u32>,
682
683 #[serde(default, skip_serializing_if = "Option::is_none")]
684 #[getset(get = "pub", set = "pub")]
685 priorities: Option<Vec<LinuxInterfacePriority>>,
687}
688
689#[derive(
690 Builder,
691 Clone,
692 CopyGetters,
693 Debug,
694 Default,
695 Deserialize,
696 Eq,
697 Getters,
698 MutGetters,
699 Setters,
700 PartialEq,
701 Serialize,
702)]
703#[serde(rename_all = "camelCase")]
704#[builder(
705 default,
706 pattern = "owned",
707 setter(into, strip_option),
708 build_fn(error = "OciSpecError")
709)]
710pub struct LinuxResources {
712 #[serde(default, skip_serializing_if = "Option::is_none")]
713 #[getset(get_mut = "pub", get = "pub", set = "pub")]
714 devices: Option<Vec<LinuxDeviceCgroup>>,
716
717 #[serde(default, skip_serializing_if = "Option::is_none")]
718 #[getset(get_mut = "pub", get = "pub", set = "pub")]
719 memory: Option<LinuxMemory>,
721
722 #[serde(default, skip_serializing_if = "Option::is_none")]
723 #[getset(get_mut = "pub", get = "pub", set = "pub")]
724 cpu: Option<LinuxCpu>,
726
727 #[serde(default, skip_serializing_if = "Option::is_none")]
728 #[getset(get_mut = "pub", get = "pub", set = "pub")]
729 pids: Option<LinuxPids>,
731
732 #[serde(default, skip_serializing_if = "Option::is_none", rename = "blockIO")]
733 #[getset(get_mut = "pub", get = "pub", set = "pub")]
734 block_io: Option<LinuxBlockIo>,
736
737 #[serde(default, skip_serializing_if = "Option::is_none")]
738 #[getset(get_mut = "pub", get = "pub", set = "pub")]
739 hugepage_limits: Option<Vec<LinuxHugepageLimit>>,
741
742 #[serde(default, skip_serializing_if = "Option::is_none")]
743 #[getset(get_mut = "pub", get = "pub", set = "pub")]
744 network: Option<LinuxNetwork>,
746
747 #[serde(default, skip_serializing_if = "Option::is_none")]
748 #[getset(get_mut = "pub", get = "pub", set = "pub")]
749 rdma: Option<HashMap<String, LinuxRdma>>,
753
754 #[serde(default, skip_serializing_if = "Option::is_none")]
755 #[getset(get_mut = "pub", get = "pub", set = "pub")]
756 unified: Option<HashMap<String, String>>,
758}
759
760#[derive(
761 Builder,
762 Clone,
763 Copy,
764 CopyGetters,
765 Debug,
766 Default,
767 Deserialize,
768 Eq,
769 MutGetters,
770 PartialEq,
771 Serialize,
772)]
773#[serde(rename_all = "camelCase")]
774#[builder(
775 default,
776 pattern = "owned",
777 setter(into, strip_option),
778 build_fn(error = "OciSpecError")
779)]
780#[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
781pub struct LinuxRdma {
783 #[serde(skip_serializing_if = "Option::is_none")]
784 hca_handles: Option<u32>,
787
788 #[serde(skip_serializing_if = "Option::is_none")]
789 hca_objects: Option<u32>,
792}
793
794#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, Hash, StrumDisplay)]
795#[strum(serialize_all = "lowercase")]
796#[serde(rename_all = "snake_case")]
797pub enum LinuxNamespaceType {
799 #[strum(to_string = "mnt")]
800 Mount = 0x00020000,
802
803 Cgroup = 0x02000000,
805
806 Uts = 0x04000000,
808
809 Ipc = 0x08000000,
811
812 User = 0x10000000,
814
815 Pid = 0x20000000,
817
818 #[strum(to_string = "net")]
819 Network = 0x40000000,
821
822 Time = 0x00000080,
824}
825
826impl TryFrom<&str> for LinuxNamespaceType {
827 type Error = OciSpecError;
828
829 fn try_from(namespace: &str) -> Result<Self, Self::Error> {
830 match namespace {
831 "mnt" | "mount" => Ok(LinuxNamespaceType::Mount),
832 "cgroup" => Ok(LinuxNamespaceType::Cgroup),
833 "uts" => Ok(LinuxNamespaceType::Uts),
834 "ipc" => Ok(LinuxNamespaceType::Ipc),
835 "user" => Ok(LinuxNamespaceType::User),
836 "pid" => Ok(LinuxNamespaceType::Pid),
837 "net" | "network" => Ok(LinuxNamespaceType::Network),
838 "time" => Ok(LinuxNamespaceType::Time),
839 _ => Err(oci_error(format!(
840 "unknown namespace {namespace}, could not convert"
841 ))),
842 }
843 }
844}
845
846impl Default for LinuxNamespaceType {
847 fn default() -> Self {
848 Self::Pid
849 }
850}
851
852#[derive(
853 Builder,
854 Clone,
855 CopyGetters,
856 Debug,
857 Default,
858 Deserialize,
859 Eq,
860 Getters,
861 Setters,
862 PartialEq,
863 Serialize,
864)]
865#[builder(
866 default,
867 pattern = "owned",
868 setter(into, strip_option),
869 build_fn(error = "OciSpecError")
870)]
871pub struct LinuxNamespace {
873 #[serde(rename = "type")]
874 #[getset(get_copy = "pub", set = "pub")]
875 typ: LinuxNamespaceType,
877
878 #[serde(default, skip_serializing_if = "Option::is_none")]
879 #[getset(get = "pub", set = "pub")]
880 path: Option<PathBuf>,
883}
884
885pub fn get_default_namespaces() -> Vec<LinuxNamespace> {
887 vec![
888 LinuxNamespace {
889 typ: LinuxNamespaceType::Pid,
890 path: Default::default(),
891 },
892 LinuxNamespace {
893 typ: LinuxNamespaceType::Network,
894 path: Default::default(),
895 },
896 LinuxNamespace {
897 typ: LinuxNamespaceType::Ipc,
898 path: Default::default(),
899 },
900 LinuxNamespace {
901 typ: LinuxNamespaceType::Uts,
902 path: Default::default(),
903 },
904 LinuxNamespace {
905 typ: LinuxNamespaceType::Mount,
906 path: Default::default(),
907 },
908 LinuxNamespace {
909 typ: LinuxNamespaceType::Cgroup,
910 path: Default::default(),
911 },
912 ]
913}
914
915#[derive(
916 Builder,
917 Clone,
918 CopyGetters,
919 Debug,
920 Default,
921 Deserialize,
922 Eq,
923 Getters,
924 MutGetters,
925 Setters,
926 PartialEq,
927 Serialize,
928)]
929#[serde(rename_all = "camelCase")]
930#[builder(
931 default,
932 pattern = "owned",
933 setter(into, strip_option),
934 build_fn(error = "OciSpecError")
935)]
936pub struct LinuxDevice {
939 #[serde(default)]
940 #[getset(get_mut = "pub", get = "pub", set = "pub")]
941 path: PathBuf,
943
944 #[serde(rename = "type")]
945 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
946 typ: LinuxDeviceType,
948
949 #[serde(default)]
950 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
951 major: i64,
953
954 #[serde(default)]
955 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
956 minor: i64,
958
959 #[serde(default, skip_serializing_if = "Option::is_none")]
960 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
961 file_mode: Option<u32>,
963
964 #[serde(default, skip_serializing_if = "Option::is_none")]
965 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
966 uid: Option<u32>,
968
969 #[serde(default, skip_serializing_if = "Option::is_none")]
970 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
971 gid: Option<u32>,
973}
974
975impl From<&LinuxDevice> for LinuxDeviceCgroup {
976 fn from(linux_device: &LinuxDevice) -> LinuxDeviceCgroup {
977 LinuxDeviceCgroup {
978 allow: true,
979 typ: linux_device.typ.into(),
980 major: Some(linux_device.major),
981 minor: Some(linux_device.minor),
982 access: "rwm".to_string().into(),
983 }
984 }
985}
986
987#[derive(
988 Builder,
989 Clone,
990 CopyGetters,
991 Debug,
992 Default,
993 Deserialize,
994 Eq,
995 Getters,
996 Setters,
997 PartialEq,
998 Serialize,
999)]
1000#[serde(rename_all = "camelCase")]
1001#[builder(
1002 default,
1003 pattern = "owned",
1004 setter(into, strip_option),
1005 build_fn(error = "OciSpecError")
1006)]
1007pub struct LinuxSeccomp {
1009 #[getset(get_copy = "pub", set = "pub")]
1010 default_action: LinuxSeccompAction,
1012
1013 #[serde(default, skip_serializing_if = "Option::is_none")]
1014 #[getset(get_copy = "pub", set = "pub")]
1015 default_errno_ret: Option<u32>,
1017
1018 #[serde(default, skip_serializing_if = "Option::is_none")]
1019 #[getset(get = "pub", set = "pub")]
1020 architectures: Option<Vec<Arch>>,
1022
1023 #[serde(default, skip_serializing_if = "Option::is_none")]
1024 #[getset(get = "pub", set = "pub")]
1025 flags: Option<Vec<LinuxSeccompFilterFlag>>,
1027
1028 #[serde(default, skip_serializing_if = "Option::is_none")]
1029 #[getset(get = "pub", set = "pub")]
1030 listener_path: Option<PathBuf>,
1032
1033 #[serde(default, skip_serializing_if = "Option::is_none")]
1034 #[getset(get = "pub", set = "pub")]
1035 listener_metadata: Option<String>,
1037
1038 #[serde(default, skip_serializing_if = "Option::is_none")]
1039 #[getset(get = "pub", set = "pub")]
1040 syscalls: Option<Vec<LinuxSyscall>>,
1042}
1043
1044#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1045#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1046#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1047pub enum LinuxSeccompAction {
1049 ScmpActKill,
1051
1052 ScmpActKillThread,
1054
1055 ScmpActKillProcess,
1057
1058 ScmpActTrap,
1060
1061 ScmpActErrno,
1063
1064 ScmpActNotify,
1066
1067 ScmpActTrace,
1069
1070 ScmpActLog,
1072
1073 ScmpActAllow,
1075}
1076
1077impl From<LinuxSeccompAction> for u32 {
1078 fn from(action: LinuxSeccompAction) -> Self {
1079 match action {
1080 LinuxSeccompAction::ScmpActKill => 0x00000000,
1081 LinuxSeccompAction::ScmpActKillThread => 0x00000000,
1082 LinuxSeccompAction::ScmpActKillProcess => 0x80000000,
1083 LinuxSeccompAction::ScmpActTrap => 0x00030000,
1084 LinuxSeccompAction::ScmpActErrno => 0x00050001,
1085 LinuxSeccompAction::ScmpActNotify => 0x7fc00000,
1086 LinuxSeccompAction::ScmpActTrace => 0x7ff00001,
1087 LinuxSeccompAction::ScmpActLog => 0x7ffc0000,
1088 LinuxSeccompAction::ScmpActAllow => 0x7fff0000,
1089 }
1090 }
1091}
1092
1093impl Default for LinuxSeccompAction {
1094 fn default() -> Self {
1095 Self::ScmpActAllow
1096 }
1097}
1098
1099#[allow(clippy::enum_clike_unportable_variant)]
1100#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1101#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1102#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1103pub enum Arch {
1105 ScmpArchNative = 0x00000000,
1107
1108 ScmpArchX86 = 0x40000003,
1110
1111 ScmpArchX86_64 = 0xc000003e,
1113
1114 ScmpArchX32 = 0x4000003e,
1119
1120 ScmpArchArm = 0x40000028,
1122
1123 ScmpArchAarch64 = 0xc00000b7,
1125
1126 ScmpArchMips = 0x00000008,
1128
1129 ScmpArchMips64 = 0x80000008,
1131
1132 ScmpArchMips64n32 = 0xa0000008,
1134
1135 ScmpArchMipsel = 0x40000008,
1137
1138 ScmpArchMipsel64 = 0xc0000008,
1140
1141 ScmpArchMipsel64n32 = 0xe0000008,
1143
1144 ScmpArchPpc = 0x00000014,
1146
1147 ScmpArchPpc64 = 0x80000015,
1149
1150 ScmpArchPpc64le = 0xc0000015,
1152
1153 ScmpArchS390 = 0x00000016,
1155
1156 ScmpArchS390x = 0x80000016,
1158
1159 ScmpArchRiscv64 = 0xc00000f3,
1161}
1162
1163#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1164#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1165#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1166pub enum LinuxSeccompFilterFlag {
1168 SeccompFilterFlagLog,
1172
1173 SeccompFilterFlagTsync,
1183
1184 SeccompFilterFlagSpecAllow,
1186}
1187
1188#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1189#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1190#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1191#[repr(u32)]
1192pub enum LinuxSeccompOperator {
1194 ScmpCmpNe = 1,
1196
1197 ScmpCmpLt = 2,
1199
1200 ScmpCmpLe = 3,
1202
1203 ScmpCmpEq = 4,
1205
1206 ScmpCmpGe = 5,
1208
1209 ScmpCmpGt = 6,
1211
1212 ScmpCmpMaskedEq = 7,
1214}
1215
1216impl Default for LinuxSeccompOperator {
1217 fn default() -> Self {
1218 Self::ScmpCmpEq
1219 }
1220}
1221
1222#[derive(
1223 Builder,
1224 Clone,
1225 CopyGetters,
1226 Debug,
1227 Default,
1228 Deserialize,
1229 Eq,
1230 Getters,
1231 Setters,
1232 PartialEq,
1233 Serialize,
1234)]
1235#[serde(rename_all = "camelCase")]
1236#[builder(
1237 default,
1238 pattern = "owned",
1239 setter(into, strip_option),
1240 build_fn(error = "OciSpecError")
1241)]
1242pub struct LinuxSyscall {
1244 #[getset(get = "pub", set = "pub")]
1245 names: Vec<String>,
1247
1248 #[getset(get_copy = "pub", set = "pub")]
1249 action: LinuxSeccompAction,
1251
1252 #[serde(default, skip_serializing_if = "Option::is_none")]
1253 #[getset(get_copy = "pub", set = "pub")]
1254 errno_ret: Option<u32>,
1256
1257 #[serde(default, skip_serializing_if = "Option::is_none")]
1258 #[getset(get = "pub", set = "pub")]
1259 args: Option<Vec<LinuxSeccompArg>>,
1261}
1262
1263#[derive(
1264 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
1265)]
1266#[serde(rename_all = "camelCase")]
1267#[builder(
1268 default,
1269 pattern = "owned",
1270 setter(into, strip_option),
1271 build_fn(error = "OciSpecError")
1272)]
1273#[getset(get_copy = "pub", set = "pub")]
1274pub struct LinuxSeccompArg {
1276 index: usize,
1278
1279 value: u64,
1281
1282 #[serde(default, skip_serializing_if = "Option::is_none")]
1283 value_two: Option<u64>,
1285
1286 op: LinuxSeccompOperator,
1288}
1289
1290pub fn get_default_maskedpaths() -> Vec<String> {
1292 vec![
1293 "/proc/acpi".to_string(),
1296 "/proc/asound".to_string(),
1297 "/proc/kcore".to_string(),
1298 "/proc/keys".to_string(),
1299 "/proc/latency_stats".to_string(),
1300 "/proc/timer_list".to_string(),
1301 "/proc/timer_stats".to_string(),
1302 "/proc/sched_debug".to_string(),
1303 "/sys/firmware".to_string(),
1304 "/proc/scsi".to_string(),
1305 ]
1306}
1307
1308pub fn get_default_readonly_paths() -> Vec<String> {
1311 vec![
1312 "/proc/bus".to_string(),
1313 "/proc/fs".to_string(),
1314 "/proc/irq".to_string(),
1315 "/proc/sys".to_string(),
1316 "/proc/sysrq-trigger".to_string(),
1317 ]
1318}
1319
1320#[derive(
1321 Builder,
1322 Clone,
1323 Debug,
1324 Default,
1325 Deserialize,
1326 Eq,
1327 Getters,
1328 MutGetters,
1329 Setters,
1330 PartialEq,
1331 Serialize,
1332)]
1333#[serde(rename_all = "camelCase")]
1334#[builder(
1335 default,
1336 pattern = "owned",
1337 setter(into, strip_option),
1338 build_fn(error = "OciSpecError")
1339)]
1340#[getset(get_mut = "pub", get = "pub", set = "pub")]
1341pub struct LinuxIntelRdt {
1345 #[serde(default, skip_serializing_if = "Option::is_none", rename = "closID")]
1346 clos_id: Option<String>,
1348
1349 #[serde(default, skip_serializing_if = "Option::is_none")]
1350 l3_cache_schema: Option<String>,
1353
1354 #[serde(default, skip_serializing_if = "Option::is_none")]
1355 mem_bw_schema: Option<String>,
1361
1362 #[serde(default, skip_serializing_if = "Option::is_none")]
1363 enable_cmt: Option<bool>,
1366
1367 #[serde(default, skip_serializing_if = "Option::is_none")]
1368 enable_mbm: Option<bool>,
1371}
1372
1373#[derive(
1374 Builder,
1375 Clone,
1376 CopyGetters,
1377 Debug,
1378 Default,
1379 Deserialize,
1380 Eq,
1381 Getters,
1382 Setters,
1383 PartialEq,
1384 Serialize,
1385)]
1386#[builder(
1387 default,
1388 pattern = "owned",
1389 setter(into, strip_option),
1390 build_fn(error = "OciSpecError")
1391)]
1392pub struct LinuxPersonality {
1394 #[getset(get_copy = "pub", set = "pub")]
1395 domain: LinuxPersonalityDomain,
1397
1398 #[serde(default, skip_serializing_if = "Option::is_none")]
1399 #[getset(get = "pub", set = "pub")]
1400 flags: Option<Vec<String>>,
1402}
1403
1404#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1405pub enum LinuxPersonalityDomain {
1407 #[serde(rename = "LINUX")]
1408 #[strum(serialize = "LINUX")]
1409 PerLinux,
1411
1412 #[serde(rename = "LINUX32")]
1413 #[strum(serialize = "LINUX32")]
1414 PerLinux32,
1416}
1417
1418impl Default for LinuxPersonalityDomain {
1419 fn default() -> Self {
1420 Self::PerLinux
1421 }
1422}
1423
1424#[cfg(feature = "proptests")]
1425use quickcheck::{Arbitrary, Gen};
1426
1427#[cfg(feature = "proptests")]
1428fn some_none_generator_util<T: Arbitrary>(g: &mut Gen) -> Option<T> {
1429 let choice = g.choose(&[true, false]).unwrap();
1430 match choice {
1431 false => None,
1432 true => Some(T::arbitrary(g)),
1433 }
1434}
1435
1436#[cfg(feature = "proptests")]
1437impl Arbitrary for LinuxDeviceCgroup {
1438 fn arbitrary(g: &mut Gen) -> LinuxDeviceCgroup {
1439 let typ_choices = ["a", "b", "c", "u", "p"];
1440
1441 let typ_chosen = g.choose(&typ_choices).unwrap();
1442
1443 let typ = match typ_chosen.to_string().as_str() {
1444 "a" => LinuxDeviceType::A,
1445 "b" => LinuxDeviceType::B,
1446 "c" => LinuxDeviceType::C,
1447 "u" => LinuxDeviceType::U,
1448 "p" => LinuxDeviceType::P,
1449 _ => LinuxDeviceType::A,
1450 };
1451
1452 let access_choices = ["rwm", "m"];
1453 LinuxDeviceCgroup {
1454 allow: bool::arbitrary(g),
1455 typ: typ.into(),
1456 major: some_none_generator_util::<i64>(g),
1457 minor: some_none_generator_util::<i64>(g),
1458 access: g.choose(&access_choices).unwrap().to_string().into(),
1459 }
1460 }
1461}
1462
1463#[cfg(feature = "proptests")]
1464impl Arbitrary for LinuxMemory {
1465 fn arbitrary(g: &mut Gen) -> LinuxMemory {
1466 LinuxMemory {
1467 kernel: some_none_generator_util::<i64>(g),
1468 kernel_tcp: some_none_generator_util::<i64>(g),
1469 limit: some_none_generator_util::<i64>(g),
1470 reservation: some_none_generator_util::<i64>(g),
1471 swap: some_none_generator_util::<i64>(g),
1472 swappiness: some_none_generator_util::<u64>(g),
1473 disable_oom_killer: some_none_generator_util::<bool>(g),
1474 use_hierarchy: some_none_generator_util::<bool>(g),
1475 check_before_update: some_none_generator_util::<bool>(g),
1476 }
1477 }
1478}
1479
1480#[cfg(feature = "proptests")]
1481impl Arbitrary for LinuxHugepageLimit {
1482 fn arbitrary(g: &mut Gen) -> LinuxHugepageLimit {
1483 let unit_choice = ["KB", "MB", "GB"];
1484 let unit = g.choose(&unit_choice).unwrap();
1485 let page_size = u64::arbitrary(g).to_string() + unit;
1486
1487 LinuxHugepageLimit {
1488 page_size,
1489 limit: i64::arbitrary(g),
1490 }
1491 }
1492}
1493
1494#[cfg(test)]
1495mod tests {
1496 use super::*;
1497
1498 #[test]
1500 fn device_type_enum_to_str() {
1501 let type_a = LinuxDeviceType::A;
1502 assert_eq!(type_a.as_str(), "a");
1503
1504 let type_b = LinuxDeviceType::B;
1505 assert_eq!(type_b.as_str(), "b");
1506
1507 let type_c = LinuxDeviceType::C;
1508 assert_eq!(type_c.as_str(), "c");
1509 }
1510
1511 #[test]
1512 fn device_type_string_to_enum() {
1513 let devtype_str = "a";
1514 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1515 assert_eq!(devtype_enum, LinuxDeviceType::A);
1516
1517 let devtype_str = "b";
1518 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1519 assert_eq!(devtype_enum, LinuxDeviceType::B);
1520
1521 let devtype_str = "c";
1522 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1523 assert_eq!(devtype_enum, LinuxDeviceType::C);
1524
1525 let invalid_devtype_str = "x";
1526 let unknown_devtype = invalid_devtype_str.parse::<LinuxDeviceType>();
1527 assert!(unknown_devtype.is_err());
1528 }
1529
1530 #[test]
1532 fn ns_type_enum_to_string() {
1533 let type_a = LinuxNamespaceType::Network;
1534 assert_eq!(type_a.to_string(), "net");
1535
1536 let type_b = LinuxNamespaceType::Mount;
1537 assert_eq!(type_b.to_string(), "mnt");
1538
1539 let type_c = LinuxNamespaceType::Ipc;
1540 assert_eq!(type_c.to_string(), "ipc");
1541 }
1542
1543 #[test]
1544 fn ns_type_string_to_enum() {
1545 let nstype_str = "net";
1546 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1547 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1548
1549 let nstype_str = "network";
1550 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1551 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1552
1553 let nstype_str = "ipc";
1554 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1555 assert_eq!(nstype_enum, LinuxNamespaceType::Ipc);
1556
1557 let nstype_str = "cgroup";
1558 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1559 assert_eq!(nstype_enum, LinuxNamespaceType::Cgroup);
1560
1561 let nstype_str = "mount";
1562 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1563 assert_eq!(nstype_enum, LinuxNamespaceType::Mount);
1564
1565 let invalid_nstype_str = "xxx";
1566 let unknown_nstype = LinuxNamespaceType::try_from(invalid_nstype_str);
1567 assert!(unknown_nstype.is_err());
1568 }
1569
1570 #[test]
1572 fn seccomp_action_enum_to_string() {
1573 let type_a = LinuxSeccompAction::ScmpActKill;
1574 assert_eq!(type_a.to_string(), "SCMP_ACT_KILL");
1575
1576 let type_b = LinuxSeccompAction::ScmpActAllow;
1577 assert_eq!(type_b.to_string(), "SCMP_ACT_ALLOW");
1578
1579 let type_c = LinuxSeccompAction::ScmpActNotify;
1580 assert_eq!(type_c.to_string(), "SCMP_ACT_NOTIFY");
1581 }
1582
1583 #[test]
1584 fn seccomp_action_string_to_enum() {
1585 let action_str = "SCMP_ACT_KILL";
1586 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1587 assert_eq!(action_enum, LinuxSeccompAction::ScmpActKill);
1588
1589 let action_str = "SCMP_ACT_ALLOW";
1590 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1591 assert_eq!(action_enum, LinuxSeccompAction::ScmpActAllow);
1592
1593 let action_str = "SCMP_ACT_NOTIFY";
1594 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1595 assert_eq!(action_enum, LinuxSeccompAction::ScmpActNotify);
1596
1597 let invalid_action_str = "x";
1598 let unknown_action = invalid_action_str.parse::<LinuxSeccompAction>();
1599 assert!(unknown_action.is_err());
1600 }
1601
1602 #[test]
1604 fn seccomp_arch_enum_to_string() {
1605 let type_a = Arch::ScmpArchX86_64;
1606 assert_eq!(type_a.to_string(), "SCMP_ARCH_X86_64");
1607
1608 let type_b = Arch::ScmpArchAarch64;
1609 assert_eq!(type_b.to_string(), "SCMP_ARCH_AARCH64");
1610
1611 let type_c = Arch::ScmpArchPpc64le;
1612 assert_eq!(type_c.to_string(), "SCMP_ARCH_PPC64LE");
1613 }
1614
1615 #[test]
1616 fn seccomp_arch_string_to_enum() {
1617 let arch_type_str = "SCMP_ARCH_X86_64";
1618 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1619 assert_eq!(arch_type_enum, Arch::ScmpArchX86_64);
1620
1621 let arch_type_str = "SCMP_ARCH_AARCH64";
1622 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1623 assert_eq!(arch_type_enum, Arch::ScmpArchAarch64);
1624
1625 let arch_type_str = "SCMP_ARCH_PPC64LE";
1626 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1627 assert_eq!(arch_type_enum, Arch::ScmpArchPpc64le);
1628
1629 let invalid_arch_str = "x";
1630 let unknown_arch = invalid_arch_str.parse::<Arch>();
1631 assert!(unknown_arch.is_err());
1632 }
1633
1634 #[test]
1636 fn seccomp_filter_flag_enum_to_string() {
1637 let type_a = LinuxSeccompFilterFlag::SeccompFilterFlagLog;
1638 assert_eq!(type_a.to_string(), "SECCOMP_FILTER_FLAG_LOG");
1639
1640 let type_b = LinuxSeccompFilterFlag::SeccompFilterFlagTsync;
1641 assert_eq!(type_b.to_string(), "SECCOMP_FILTER_FLAG_TSYNC");
1642
1643 let type_c = LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow;
1644 assert_eq!(type_c.to_string(), "SECCOMP_FILTER_FLAG_SPEC_ALLOW");
1645 }
1646
1647 #[test]
1648 fn seccomp_filter_flag_string_to_enum() {
1649 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_LOG";
1650 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1651 assert_eq!(
1652 filter_flag_type_enum,
1653 LinuxSeccompFilterFlag::SeccompFilterFlagLog
1654 );
1655
1656 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_TSYNC";
1657 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1658 assert_eq!(
1659 filter_flag_type_enum,
1660 LinuxSeccompFilterFlag::SeccompFilterFlagTsync
1661 );
1662
1663 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_SPEC_ALLOW";
1664 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1665 assert_eq!(
1666 filter_flag_type_enum,
1667 LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow
1668 );
1669
1670 let invalid_filter_flag_str = "x";
1671 let unknown_arch = invalid_filter_flag_str.parse::<LinuxSeccompFilterFlag>();
1672 assert!(unknown_arch.is_err());
1673 }
1674
1675 #[test]
1677 fn seccomp_operator_enum_to_string() {
1678 let type_a = LinuxSeccompOperator::ScmpCmpNe;
1679 assert_eq!(type_a.to_string(), "SCMP_CMP_NE");
1680
1681 let type_b = LinuxSeccompOperator::ScmpCmpMaskedEq;
1682 assert_eq!(type_b.to_string(), "SCMP_CMP_MASKED_EQ");
1683
1684 let type_c = LinuxSeccompOperator::ScmpCmpGt;
1685 assert_eq!(type_c.to_string(), "SCMP_CMP_GT");
1686 }
1687
1688 #[test]
1689 fn seccomp_operator_string_to_enum() {
1690 let seccomp_operator_str = "SCMP_CMP_GT";
1691 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1692 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpGt);
1693
1694 let seccomp_operator_str = "SCMP_CMP_NE";
1695 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1696 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpNe);
1697
1698 let seccomp_operator_str = "SCMP_CMP_MASKED_EQ";
1699 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1700 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpMaskedEq);
1701
1702 let invalid_seccomp_operator_str = "x";
1703 let unknown_operator = invalid_seccomp_operator_str.parse::<LinuxSeccompOperator>();
1704 assert!(unknown_operator.is_err());
1705 }
1706}