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 net_devices: Option<HashMap<String, LinuxNetDevice>>,
26
27 #[serde(default, skip_serializing_if = "Option::is_none")]
28 uid_mappings: Option<Vec<LinuxIdMapping>>,
30
31 #[serde(default, skip_serializing_if = "Option::is_none")]
32 gid_mappings: Option<Vec<LinuxIdMapping>>,
34
35 #[serde(default, skip_serializing_if = "Option::is_none")]
36 sysctl: Option<HashMap<String, String>>,
39
40 #[serde(default, skip_serializing_if = "Option::is_none")]
41 resources: Option<LinuxResources>,
44
45 #[serde(default, skip_serializing_if = "Option::is_none")]
46 cgroups_path: Option<PathBuf>,
51
52 #[serde(default, skip_serializing_if = "Option::is_none")]
53 namespaces: Option<Vec<LinuxNamespace>>,
56
57 #[serde(default, skip_serializing_if = "Option::is_none")]
58 devices: Option<Vec<LinuxDevice>>,
61
62 #[serde(default, skip_serializing_if = "Option::is_none")]
63 seccomp: Option<LinuxSeccomp>,
65
66 #[serde(default, skip_serializing_if = "Option::is_none")]
67 rootfs_propagation: Option<String>,
70
71 #[serde(default, skip_serializing_if = "Option::is_none")]
72 masked_paths: Option<Vec<String>>,
74
75 #[serde(default, skip_serializing_if = "Option::is_none")]
76 readonly_paths: Option<Vec<String>>,
78
79 #[serde(default, skip_serializing_if = "Option::is_none")]
80 mount_label: Option<String>,
83
84 #[serde(default, skip_serializing_if = "Option::is_none")]
85 intel_rdt: Option<LinuxIntelRdt>,
89
90 #[serde(default, skip_serializing_if = "Option::is_none")]
91 memory_policy: Option<LinuxMemoryPolicy>,
93
94 #[serde(default, skip_serializing_if = "Option::is_none")]
95 personality: Option<LinuxPersonality>,
98
99 #[serde(default, skip_serializing_if = "Option::is_none")]
100 time_offsets: Option<HashMap<String, LinuxTimeOffset>>,
102}
103
104impl Default for Linux {
106 fn default() -> Self {
107 Linux {
108 net_devices: None,
110 uid_mappings: Default::default(),
112 gid_mappings: Default::default(),
114 sysctl: Default::default(),
116 resources: Some(LinuxResources {
117 devices: vec![].into(),
118 memory: Default::default(),
119 cpu: Default::default(),
120 pids: Default::default(),
121 block_io: Default::default(),
122 hugepage_limits: Default::default(),
123 network: Default::default(),
124 rdma: Default::default(),
125 unified: Default::default(),
126 }),
127 cgroups_path: Default::default(),
129 namespaces: get_default_namespaces().into(),
130 devices: Default::default(),
132 rootfs_propagation: Default::default(),
134 masked_paths: get_default_maskedpaths().into(),
135 readonly_paths: get_default_readonly_paths().into(),
136 mount_label: Default::default(),
138 seccomp: None,
139 intel_rdt: None,
140 memory_policy: None,
141 personality: None,
142 time_offsets: None,
143 }
144 }
145}
146
147impl Linux {
148 pub fn rootless(uid: u32, gid: u32) -> Self {
150 let mut namespaces = get_default_namespaces();
151 namespaces.retain(|ns| ns.typ != LinuxNamespaceType::Network);
152 namespaces.push(LinuxNamespace {
153 typ: LinuxNamespaceType::User,
154 ..Default::default()
155 });
156 Self {
157 resources: None,
158 uid_mappings: Some(vec![LinuxIdMapping {
159 container_id: 0,
160 host_id: uid,
161 size: 1,
162 }]),
163 gid_mappings: Some(vec![LinuxIdMapping {
164 container_id: 0,
165 host_id: gid,
166 size: 1,
167 }]),
168 namespaces: Some(namespaces),
169 ..Default::default()
170 }
171 }
172}
173
174#[derive(
175 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
176)]
177#[serde(rename_all = "camelCase")]
178#[builder(
179 default,
180 pattern = "owned",
181 setter(into, strip_option),
182 build_fn(error = "OciSpecError")
183)]
184#[getset(get_copy = "pub", set = "pub")]
185pub struct LinuxIdMapping {
187 #[serde(default, rename = "hostID")]
188 host_id: u32,
191
192 #[serde(default, rename = "containerID")]
193 container_id: u32,
195
196 #[serde(default)]
197 size: u32,
199}
200
201#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, EnumString)]
202#[strum(serialize_all = "lowercase")]
203#[serde(rename_all = "lowercase")]
204pub enum LinuxDeviceType {
206 A,
208
209 B,
211
212 C,
214
215 U,
217
218 P,
220}
221
222#[allow(clippy::derivable_impls)] impl Default for LinuxDeviceType {
224 fn default() -> LinuxDeviceType {
225 LinuxDeviceType::A
226 }
227}
228
229impl LinuxDeviceType {
230 pub fn as_str(&self) -> &str {
232 match self {
233 Self::A => "a",
234 Self::B => "b",
235 Self::C => "c",
236 Self::U => "u",
237 Self::P => "p",
238 }
239 }
240}
241
242#[derive(
243 Builder,
244 Clone,
245 Debug,
246 Default,
247 Deserialize,
248 Eq,
249 Getters,
250 MutGetters,
251 Setters,
252 PartialEq,
253 Serialize,
254)]
255#[builder(
256 default,
257 pattern = "owned",
258 setter(into, strip_option),
259 build_fn(error = "OciSpecError")
260)]
261pub struct LinuxNetDevice {
263 #[serde(default)]
264 #[getset(get_mut = "pub", get = "pub", set = "pub")]
265 name: Option<String>,
267}
268
269#[derive(
270 Builder,
271 Clone,
272 CopyGetters,
273 Debug,
274 Default,
275 Deserialize,
276 Eq,
277 Getters,
278 MutGetters,
279 Setters,
280 PartialEq,
281 Serialize,
282)]
283#[builder(
284 default,
285 pattern = "owned",
286 setter(into, strip_option),
287 build_fn(error = "OciSpecError")
288)]
289pub struct LinuxDeviceCgroup {
292 #[serde(default)]
293 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
294 allow: bool,
296
297 #[serde(default, rename = "type", skip_serializing_if = "Option::is_none")]
298 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
299 typ: Option<LinuxDeviceType>,
301
302 #[serde(default, skip_serializing_if = "Option::is_none")]
303 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
304 major: Option<i64>,
306
307 #[serde(default, skip_serializing_if = "Option::is_none")]
308 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
309 minor: Option<i64>,
311
312 #[serde(default)]
314 #[getset(get_mut = "pub", get = "pub", set = "pub")]
315 access: Option<String>,
316}
317
318impl Display for LinuxDeviceCgroup {
322 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
323 let major = self
324 .major
325 .map(|mj| mj.to_string())
326 .unwrap_or_else(|| "*".to_string());
327 let minor = self
328 .minor
329 .map(|mi| mi.to_string())
330 .unwrap_or_else(|| "*".to_string());
331 let access = self.access.as_deref().unwrap_or("");
332 write!(
333 f,
334 "{} {}:{} {}",
335 &self.typ.unwrap_or_default().as_str(),
336 &major,
337 &minor,
338 &access
339 )
340 }
341}
342
343#[derive(
344 Builder,
345 Clone,
346 Copy,
347 CopyGetters,
348 Debug,
349 Default,
350 Deserialize,
351 Eq,
352 PartialEq,
353 Serialize,
354 Setters,
355)]
356#[serde(rename_all = "camelCase")]
357#[builder(
358 default,
359 pattern = "owned",
360 setter(into, strip_option),
361 build_fn(error = "OciSpecError")
362)]
363#[getset(get_copy = "pub", set = "pub")]
364pub struct LinuxMemory {
366 #[serde(skip_serializing_if = "Option::is_none")]
367 #[getset(get_copy = "pub", set = "pub")]
368 limit: Option<i64>,
370
371 #[serde(skip_serializing_if = "Option::is_none")]
372 #[getset(get_copy = "pub", set = "pub")]
373 reservation: Option<i64>,
375
376 #[serde(skip_serializing_if = "Option::is_none")]
377 #[getset(get_copy = "pub", set = "pub")]
378 swap: Option<i64>,
380
381 #[serde(skip_serializing_if = "Option::is_none")]
382 #[getset(get_copy = "pub", set = "pub")]
383 kernel: Option<i64>,
385
386 #[serde(skip_serializing_if = "Option::is_none", rename = "kernelTCP")]
387 #[getset(get_copy = "pub", set = "pub")]
388 kernel_tcp: Option<i64>,
390
391 #[serde(skip_serializing_if = "Option::is_none")]
392 #[getset(get_copy = "pub", set = "pub")]
393 swappiness: Option<u64>,
395
396 #[serde(skip_serializing_if = "Option::is_none", rename = "disableOOMKiller")]
397 #[getset(get_copy = "pub", set = "pub")]
398 disable_oom_killer: Option<bool>,
401
402 #[serde(skip_serializing_if = "Option::is_none")]
403 #[getset(get_copy = "pub", set = "pub")]
404 use_hierarchy: Option<bool>,
406
407 #[serde(skip_serializing_if = "Option::is_none")]
408 #[getset(get_copy = "pub", set = "pub")]
409 check_before_update: Option<bool>,
411}
412
413#[derive(
414 Builder,
415 Clone,
416 CopyGetters,
417 Debug,
418 Default,
419 Deserialize,
420 Eq,
421 Getters,
422 Setters,
423 PartialEq,
424 Serialize,
425)]
426#[serde(rename_all = "camelCase")]
427#[builder(
428 default,
429 pattern = "owned",
430 setter(into, strip_option),
431 build_fn(error = "OciSpecError")
432)]
433pub struct LinuxCpu {
435 #[serde(skip_serializing_if = "Option::is_none")]
436 #[getset(get_copy = "pub", set = "pub")]
437 shares: Option<u64>,
440
441 #[serde(skip_serializing_if = "Option::is_none")]
442 #[getset(get_copy = "pub", set = "pub")]
443 quota: Option<i64>,
445
446 #[serde(skip_serializing_if = "Option::is_none")]
447 #[getset(get_copy = "pub", set = "pub")]
448 idle: Option<i64>,
450
451 #[serde(skip_serializing_if = "Option::is_none")]
452 #[getset(get_copy = "pub", set = "pub")]
453 burst: Option<u64>,
456
457 #[serde(skip_serializing_if = "Option::is_none")]
458 #[getset(get_copy = "pub", set = "pub")]
459 period: Option<u64>,
461
462 #[serde(skip_serializing_if = "Option::is_none")]
463 #[getset(get_copy = "pub", set = "pub")]
464 realtime_runtime: Option<i64>,
466
467 #[serde(skip_serializing_if = "Option::is_none")]
468 #[getset(get_copy = "pub", set = "pub")]
469 realtime_period: Option<u64>,
471
472 #[serde(default, skip_serializing_if = "Option::is_none")]
473 #[getset(get = "pub", set = "pub")]
474 cpus: Option<String>,
476
477 #[serde(default, skip_serializing_if = "Option::is_none")]
478 #[getset(get = "pub", set = "pub")]
479 mems: Option<String>,
482}
483
484#[derive(
485 Builder,
486 Clone,
487 Copy,
488 Debug,
489 Default,
490 Deserialize,
491 Eq,
492 CopyGetters,
493 Setters,
494 PartialEq,
495 Serialize,
496)]
497#[builder(
498 default,
499 pattern = "owned",
500 setter(into, strip_option),
501 build_fn(error = "OciSpecError")
502)]
503#[getset(get_copy = "pub", set = "pub")]
504pub struct LinuxPids {
506 #[serde(default)]
507 limit: i64,
509}
510
511#[derive(
512 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
513)]
514#[serde(rename_all = "camelCase")]
515#[builder(
516 default,
517 pattern = "owned",
518 setter(into, strip_option),
519 build_fn(error = "OciSpecError")
520)]
521#[getset(get_copy = "pub", set = "pub")]
522pub struct LinuxWeightDevice {
525 #[serde(default)]
526 major: i64,
528
529 #[serde(default)]
530 minor: i64,
532
533 #[serde(skip_serializing_if = "Option::is_none")]
534 weight: Option<u16>,
536
537 #[serde(skip_serializing_if = "Option::is_none")]
538 leaf_weight: Option<u16>,
541}
542
543#[derive(
544 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
545)]
546#[builder(
547 default,
548 pattern = "owned",
549 setter(into, strip_option),
550 build_fn(error = "OciSpecError")
551)]
552#[getset(get_copy = "pub", set = "pub")]
553pub struct LinuxThrottleDevice {
555 #[serde(default)]
556 major: i64,
558
559 #[serde(default)]
560 minor: i64,
562
563 #[serde(default)]
564 rate: u64,
566}
567
568#[derive(
569 Builder,
570 Clone,
571 CopyGetters,
572 Debug,
573 Default,
574 Deserialize,
575 Eq,
576 Getters,
577 Setters,
578 PartialEq,
579 Serialize,
580)]
581#[serde(rename_all = "camelCase")]
582#[builder(
583 default,
584 pattern = "owned",
585 setter(into, strip_option),
586 build_fn(error = "OciSpecError")
587)]
588pub struct LinuxBlockIo {
590 #[serde(skip_serializing_if = "Option::is_none")]
591 #[getset(get_copy = "pub", set = "pub")]
592 weight: Option<u16>,
594
595 #[serde(skip_serializing_if = "Option::is_none")]
596 #[getset(get_copy = "pub", set = "pub")]
597 leaf_weight: Option<u16>,
600
601 #[serde(skip_serializing_if = "Option::is_none")]
602 #[getset(get = "pub", set = "pub")]
603 weight_device: Option<Vec<LinuxWeightDevice>>,
605
606 #[serde(skip_serializing_if = "Option::is_none")]
607 #[getset(get = "pub", set = "pub")]
608 throttle_read_bps_device: Option<Vec<LinuxThrottleDevice>>,
610
611 #[serde(skip_serializing_if = "Option::is_none")]
612 #[getset(get = "pub", set = "pub")]
613 throttle_write_bps_device: Option<Vec<LinuxThrottleDevice>>,
615
616 #[serde(
617 skip_serializing_if = "Option::is_none",
618 rename = "throttleReadIOPSDevice"
619 )]
620 #[getset(get = "pub", set = "pub")]
621 throttle_read_iops_device: Option<Vec<LinuxThrottleDevice>>,
623
624 #[serde(
625 skip_serializing_if = "Option::is_none",
626 rename = "throttleWriteIOPSDevice"
627 )]
628 #[getset(get = "pub", set = "pub")]
629 throttle_write_iops_device: Option<Vec<LinuxThrottleDevice>>,
631}
632
633#[derive(
634 Builder,
635 Clone,
636 CopyGetters,
637 Debug,
638 Default,
639 Deserialize,
640 Eq,
641 Getters,
642 Setters,
643 PartialEq,
644 Serialize,
645)]
646#[serde(rename_all = "camelCase")]
647#[builder(
648 default,
649 pattern = "owned",
650 setter(into, strip_option),
651 build_fn(error = "OciSpecError")
652)]
653pub struct LinuxHugepageLimit {
656 #[serde(default)]
657 #[getset(get = "pub", set = "pub")]
658 page_size: String,
661
662 #[serde(default)]
663 #[getset(get_copy = "pub", set = "pub")]
664 limit: i64,
666}
667
668#[derive(
669 Builder,
670 Clone,
671 CopyGetters,
672 Debug,
673 Default,
674 Deserialize,
675 Eq,
676 Getters,
677 Setters,
678 PartialEq,
679 Serialize,
680)]
681#[builder(
682 default,
683 pattern = "owned",
684 setter(into, strip_option),
685 build_fn(error = "OciSpecError")
686)]
687pub struct LinuxInterfacePriority {
689 #[serde(default)]
690 #[getset(get = "pub", set = "pub")]
691 name: String,
693
694 #[serde(default)]
695 #[getset(get_copy = "pub", set = "pub")]
696 priority: u32,
698}
699
700impl Display for LinuxInterfacePriority {
704 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
705 writeln!(f, "{} {}", self.name, self.priority)
708 }
709}
710
711#[derive(
712 Builder,
713 Clone,
714 CopyGetters,
715 Debug,
716 Default,
717 Deserialize,
718 Eq,
719 Getters,
720 Setters,
721 PartialEq,
722 Serialize,
723)]
724#[builder(
725 default,
726 pattern = "owned",
727 setter(into, strip_option),
728 build_fn(error = "OciSpecError")
729)]
730pub struct LinuxNetwork {
732 #[serde(skip_serializing_if = "Option::is_none", rename = "classID")]
733 #[getset(get_copy = "pub", set = "pub")]
734 class_id: Option<u32>,
736
737 #[serde(default, skip_serializing_if = "Option::is_none")]
738 #[getset(get = "pub", set = "pub")]
739 priorities: Option<Vec<LinuxInterfacePriority>>,
741}
742
743#[derive(
744 Builder,
745 Clone,
746 CopyGetters,
747 Debug,
748 Default,
749 Deserialize,
750 Eq,
751 Getters,
752 MutGetters,
753 Setters,
754 PartialEq,
755 Serialize,
756)]
757#[serde(rename_all = "camelCase")]
758#[builder(
759 default,
760 pattern = "owned",
761 setter(into, strip_option),
762 build_fn(error = "OciSpecError")
763)]
764pub struct LinuxResources {
766 #[serde(default, skip_serializing_if = "Option::is_none")]
767 #[getset(get_mut = "pub", get = "pub", set = "pub")]
768 devices: Option<Vec<LinuxDeviceCgroup>>,
770
771 #[serde(default, skip_serializing_if = "Option::is_none")]
772 #[getset(get_mut = "pub", get = "pub", set = "pub")]
773 memory: Option<LinuxMemory>,
775
776 #[serde(default, skip_serializing_if = "Option::is_none")]
777 #[getset(get_mut = "pub", get = "pub", set = "pub")]
778 cpu: Option<LinuxCpu>,
780
781 #[serde(default, skip_serializing_if = "Option::is_none")]
782 #[getset(get_mut = "pub", get = "pub", set = "pub")]
783 pids: Option<LinuxPids>,
785
786 #[serde(default, skip_serializing_if = "Option::is_none", rename = "blockIO")]
787 #[getset(get_mut = "pub", get = "pub", set = "pub")]
788 block_io: Option<LinuxBlockIo>,
790
791 #[serde(default, skip_serializing_if = "Option::is_none")]
792 #[getset(get_mut = "pub", get = "pub", set = "pub")]
793 hugepage_limits: Option<Vec<LinuxHugepageLimit>>,
795
796 #[serde(default, skip_serializing_if = "Option::is_none")]
797 #[getset(get_mut = "pub", get = "pub", set = "pub")]
798 network: Option<LinuxNetwork>,
800
801 #[serde(default, skip_serializing_if = "Option::is_none")]
802 #[getset(get_mut = "pub", get = "pub", set = "pub")]
803 rdma: Option<HashMap<String, LinuxRdma>>,
807
808 #[serde(default, skip_serializing_if = "Option::is_none")]
809 #[getset(get_mut = "pub", get = "pub", set = "pub")]
810 unified: Option<HashMap<String, String>>,
812}
813
814#[derive(
815 Builder,
816 Clone,
817 Copy,
818 CopyGetters,
819 Debug,
820 Default,
821 Deserialize,
822 Eq,
823 MutGetters,
824 PartialEq,
825 Serialize,
826)]
827#[serde(rename_all = "camelCase")]
828#[builder(
829 default,
830 pattern = "owned",
831 setter(into, strip_option),
832 build_fn(error = "OciSpecError")
833)]
834#[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
835pub struct LinuxRdma {
837 #[serde(skip_serializing_if = "Option::is_none")]
838 hca_handles: Option<u32>,
841
842 #[serde(skip_serializing_if = "Option::is_none")]
843 hca_objects: Option<u32>,
846}
847
848#[derive(
849 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, Hash, StrumDisplay,
850)]
851#[strum(serialize_all = "lowercase")]
852#[serde(rename_all = "snake_case")]
853pub enum LinuxNamespaceType {
855 #[strum(to_string = "mnt")]
856 Mount = 0x00020000,
858
859 Cgroup = 0x02000000,
861
862 Uts = 0x04000000,
864
865 Ipc = 0x08000000,
867
868 User = 0x10000000,
870
871 #[default]
873 Pid = 0x20000000,
874
875 #[strum(to_string = "net")]
876 Network = 0x40000000,
878
879 Time = 0x00000080,
881}
882
883impl TryFrom<&str> for LinuxNamespaceType {
884 type Error = OciSpecError;
885
886 fn try_from(namespace: &str) -> Result<Self, Self::Error> {
887 match namespace {
888 "mnt" | "mount" => Ok(LinuxNamespaceType::Mount),
889 "cgroup" => Ok(LinuxNamespaceType::Cgroup),
890 "uts" => Ok(LinuxNamespaceType::Uts),
891 "ipc" => Ok(LinuxNamespaceType::Ipc),
892 "user" => Ok(LinuxNamespaceType::User),
893 "pid" => Ok(LinuxNamespaceType::Pid),
894 "net" | "network" => Ok(LinuxNamespaceType::Network),
895 "time" => Ok(LinuxNamespaceType::Time),
896 _ => Err(oci_error(format!(
897 "unknown namespace {namespace}, could not convert"
898 ))),
899 }
900 }
901}
902
903#[derive(
904 Builder,
905 Clone,
906 CopyGetters,
907 Debug,
908 Default,
909 Deserialize,
910 Eq,
911 Getters,
912 Setters,
913 PartialEq,
914 Serialize,
915)]
916#[builder(
917 default,
918 pattern = "owned",
919 setter(into, strip_option),
920 build_fn(error = "OciSpecError")
921)]
922pub struct LinuxNamespace {
924 #[serde(rename = "type")]
925 #[getset(get_copy = "pub", set = "pub")]
926 typ: LinuxNamespaceType,
928
929 #[serde(default, skip_serializing_if = "Option::is_none")]
930 #[getset(get = "pub", set = "pub")]
931 path: Option<PathBuf>,
934}
935
936pub fn get_default_namespaces() -> Vec<LinuxNamespace> {
938 vec![
939 LinuxNamespace {
940 typ: LinuxNamespaceType::Pid,
941 path: Default::default(),
942 },
943 LinuxNamespace {
944 typ: LinuxNamespaceType::Network,
945 path: Default::default(),
946 },
947 LinuxNamespace {
948 typ: LinuxNamespaceType::Ipc,
949 path: Default::default(),
950 },
951 LinuxNamespace {
952 typ: LinuxNamespaceType::Uts,
953 path: Default::default(),
954 },
955 LinuxNamespace {
956 typ: LinuxNamespaceType::Mount,
957 path: Default::default(),
958 },
959 LinuxNamespace {
960 typ: LinuxNamespaceType::Cgroup,
961 path: Default::default(),
962 },
963 ]
964}
965
966#[derive(
967 Builder,
968 Clone,
969 CopyGetters,
970 Debug,
971 Default,
972 Deserialize,
973 Eq,
974 Getters,
975 MutGetters,
976 Setters,
977 PartialEq,
978 Serialize,
979)]
980#[serde(rename_all = "camelCase")]
981#[builder(
982 default,
983 pattern = "owned",
984 setter(into, strip_option),
985 build_fn(error = "OciSpecError")
986)]
987pub struct LinuxDevice {
990 #[serde(default)]
991 #[getset(get_mut = "pub", get = "pub", set = "pub")]
992 path: PathBuf,
994
995 #[serde(rename = "type")]
996 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
997 typ: LinuxDeviceType,
999
1000 #[serde(default)]
1001 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1002 major: i64,
1004
1005 #[serde(default)]
1006 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1007 minor: i64,
1009
1010 #[serde(default, skip_serializing_if = "Option::is_none")]
1011 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1012 file_mode: Option<u32>,
1014
1015 #[serde(default, skip_serializing_if = "Option::is_none")]
1016 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1017 uid: Option<u32>,
1019
1020 #[serde(default, skip_serializing_if = "Option::is_none")]
1021 #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
1022 gid: Option<u32>,
1024}
1025
1026impl From<&LinuxDevice> for LinuxDeviceCgroup {
1027 fn from(linux_device: &LinuxDevice) -> LinuxDeviceCgroup {
1028 LinuxDeviceCgroup {
1029 allow: true,
1030 typ: linux_device.typ.into(),
1031 major: Some(linux_device.major),
1032 minor: Some(linux_device.minor),
1033 access: "rwm".to_string().into(),
1034 }
1035 }
1036}
1037
1038#[derive(
1039 Builder,
1040 Clone,
1041 CopyGetters,
1042 Debug,
1043 Default,
1044 Deserialize,
1045 Eq,
1046 Getters,
1047 Setters,
1048 PartialEq,
1049 Serialize,
1050)]
1051#[serde(rename_all = "camelCase")]
1052#[builder(
1053 default,
1054 pattern = "owned",
1055 setter(into, strip_option),
1056 build_fn(error = "OciSpecError")
1057)]
1058pub struct LinuxSeccomp {
1060 #[getset(get_copy = "pub", set = "pub")]
1061 default_action: LinuxSeccompAction,
1063
1064 #[serde(default, skip_serializing_if = "Option::is_none")]
1065 #[getset(get_copy = "pub", set = "pub")]
1066 default_errno_ret: Option<u32>,
1068
1069 #[serde(default, skip_serializing_if = "Option::is_none")]
1070 #[getset(get = "pub", set = "pub")]
1071 architectures: Option<Vec<Arch>>,
1073
1074 #[serde(default, skip_serializing_if = "Option::is_none")]
1075 #[getset(get = "pub", set = "pub")]
1076 flags: Option<Vec<LinuxSeccompFilterFlag>>,
1078
1079 #[serde(default, skip_serializing_if = "Option::is_none")]
1080 #[getset(get = "pub", set = "pub")]
1081 listener_path: Option<PathBuf>,
1083
1084 #[serde(default, skip_serializing_if = "Option::is_none")]
1085 #[getset(get = "pub", set = "pub")]
1086 listener_metadata: Option<String>,
1088
1089 #[serde(default, skip_serializing_if = "Option::is_none")]
1090 #[getset(get = "pub", set = "pub")]
1091 syscalls: Option<Vec<LinuxSyscall>>,
1093}
1094
1095#[derive(
1096 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1097)]
1098#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1099#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1100pub enum LinuxSeccompAction {
1102 ScmpActKill,
1104
1105 ScmpActKillThread,
1107
1108 ScmpActKillProcess,
1110
1111 ScmpActTrap,
1113
1114 ScmpActErrno,
1116
1117 ScmpActNotify,
1119
1120 ScmpActTrace,
1122
1123 ScmpActLog,
1125
1126 #[default]
1128 ScmpActAllow,
1129}
1130
1131impl From<LinuxSeccompAction> for u32 {
1133 fn from(action: LinuxSeccompAction) -> Self {
1134 action.as_u32(None)
1135 }
1136}
1137
1138impl LinuxSeccompAction {
1139 pub fn as_u32(&self, errno_ret: Option<u32>) -> u32 {
1145 match self {
1146 LinuxSeccompAction::ScmpActKill => 0x00000000,
1147 LinuxSeccompAction::ScmpActKillThread => 0x00000000,
1148 LinuxSeccompAction::ScmpActKillProcess => 0x80000000,
1149 LinuxSeccompAction::ScmpActTrap => 0x00030000,
1150 LinuxSeccompAction::ScmpActErrno => {
1151 if let Some(errno_ret) = errno_ret {
1152 0x00050000 | errno_ret
1153 } else {
1154 0x00050001
1155 }
1156 }
1157 LinuxSeccompAction::ScmpActNotify => 0x7fc00000,
1158 LinuxSeccompAction::ScmpActTrace => {
1159 if let Some(errno_ret) = errno_ret {
1160 0x7ff00000 | errno_ret
1161 } else {
1162 0x7ff00001
1163 }
1164 }
1165 LinuxSeccompAction::ScmpActLog => 0x7ffc0000,
1166 LinuxSeccompAction::ScmpActAllow => 0x7fff0000,
1167 }
1168 }
1169}
1170
1171#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1172#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1173#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1174#[repr(u32)]
1175pub enum Arch {
1177 ScmpArchNative = 0x00000000,
1179
1180 ScmpArchX86 = 0x40000003,
1182
1183 ScmpArchX86_64 = 0xc000003e,
1185
1186 ScmpArchX32 = 0x4000003e,
1191
1192 ScmpArchArm = 0x40000028,
1194
1195 ScmpArchAarch64 = 0xc00000b7,
1197
1198 ScmpArchMips = 0x00000008,
1200
1201 ScmpArchMips64 = 0x80000008,
1203
1204 ScmpArchMips64n32 = 0xa0000008,
1206
1207 ScmpArchMipsel = 0x40000008,
1209
1210 ScmpArchMipsel64 = 0xc0000008,
1212
1213 ScmpArchMipsel64n32 = 0xe0000008,
1215
1216 ScmpArchPpc = 0x00000014,
1218
1219 ScmpArchPpc64 = 0x80000015,
1221
1222 ScmpArchPpc64le = 0xc0000015,
1224
1225 ScmpArchS390 = 0x00000016,
1227
1228 ScmpArchS390x = 0x80000016,
1230
1231 ScmpArchRiscv64 = 0xc00000f3,
1233}
1234
1235#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1236#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1237#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1238pub enum LinuxSeccompFilterFlag {
1240 SeccompFilterFlagLog,
1244
1245 SeccompFilterFlagTsync,
1255
1256 SeccompFilterFlagSpecAllow,
1258
1259 SeccompFilterFlagWaitKillableRecv,
1261}
1262
1263#[derive(
1264 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1265)]
1266#[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
1267#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
1268#[repr(u32)]
1269pub enum LinuxSeccompOperator {
1271 ScmpCmpNe = 1,
1273
1274 ScmpCmpLt = 2,
1276
1277 ScmpCmpLe = 3,
1279
1280 #[default]
1282 ScmpCmpEq = 4,
1283
1284 ScmpCmpGe = 5,
1286
1287 ScmpCmpGt = 6,
1289
1290 ScmpCmpMaskedEq = 7,
1292}
1293
1294#[derive(
1295 Builder,
1296 Clone,
1297 CopyGetters,
1298 Debug,
1299 Default,
1300 Deserialize,
1301 Eq,
1302 Getters,
1303 Setters,
1304 PartialEq,
1305 Serialize,
1306)]
1307#[serde(rename_all = "camelCase")]
1308#[builder(
1309 default,
1310 pattern = "owned",
1311 setter(into, strip_option),
1312 build_fn(error = "OciSpecError")
1313)]
1314pub struct LinuxSyscall {
1316 #[getset(get = "pub", set = "pub")]
1317 names: Vec<String>,
1319
1320 #[getset(get_copy = "pub", set = "pub")]
1321 action: LinuxSeccompAction,
1323
1324 #[serde(default, skip_serializing_if = "Option::is_none")]
1325 #[getset(get_copy = "pub", set = "pub")]
1326 errno_ret: Option<u32>,
1328
1329 #[serde(default, skip_serializing_if = "Option::is_none")]
1330 #[getset(get = "pub", set = "pub")]
1331 args: Option<Vec<LinuxSeccompArg>>,
1333}
1334
1335#[derive(
1336 Builder, Clone, Copy, CopyGetters, Debug, Default, Deserialize, Eq, PartialEq, Serialize,
1337)]
1338#[serde(rename_all = "camelCase")]
1339#[builder(
1340 default,
1341 pattern = "owned",
1342 setter(into, strip_option),
1343 build_fn(error = "OciSpecError")
1344)]
1345#[getset(get_copy = "pub", set = "pub")]
1346pub struct LinuxSeccompArg {
1348 index: usize,
1350
1351 value: u64,
1353
1354 #[serde(default, skip_serializing_if = "Option::is_none")]
1355 value_two: Option<u64>,
1357
1358 op: LinuxSeccompOperator,
1360}
1361
1362pub fn get_default_maskedpaths() -> Vec<String> {
1364 vec![
1365 "/proc/acpi".to_string(),
1368 "/proc/asound".to_string(),
1369 "/proc/kcore".to_string(),
1370 "/proc/keys".to_string(),
1371 "/proc/latency_stats".to_string(),
1372 "/proc/timer_list".to_string(),
1373 "/proc/timer_stats".to_string(),
1374 "/proc/sched_debug".to_string(),
1375 "/sys/firmware".to_string(),
1376 "/proc/scsi".to_string(),
1377 ]
1378}
1379
1380pub fn get_default_readonly_paths() -> Vec<String> {
1383 vec![
1384 "/proc/bus".to_string(),
1385 "/proc/fs".to_string(),
1386 "/proc/irq".to_string(),
1387 "/proc/sys".to_string(),
1388 "/proc/sysrq-trigger".to_string(),
1389 ]
1390}
1391
1392#[derive(
1393 Builder,
1394 Clone,
1395 Debug,
1396 Default,
1397 Deserialize,
1398 Eq,
1399 Getters,
1400 MutGetters,
1401 Setters,
1402 PartialEq,
1403 Serialize,
1404)]
1405#[serde(rename_all = "camelCase")]
1406#[builder(
1407 default,
1408 pattern = "owned",
1409 setter(into, strip_option),
1410 build_fn(error = "OciSpecError")
1411)]
1412#[getset(get_mut = "pub", get = "pub", set = "pub")]
1413pub struct LinuxIntelRdt {
1417 #[serde(default, skip_serializing_if = "Option::is_none", rename = "closID")]
1418 clos_id: Option<String>,
1420
1421 #[serde(default, skip_serializing_if = "Option::is_none")]
1422 l3_cache_schema: Option<String>,
1425
1426 #[serde(default, skip_serializing_if = "Option::is_none")]
1427 mem_bw_schema: Option<String>,
1433
1434 #[serde(default, skip_serializing_if = "Option::is_none")]
1435 enable_cmt: Option<bool>,
1438
1439 #[serde(default, skip_serializing_if = "Option::is_none")]
1440 enable_mbm: Option<bool>,
1443}
1444
1445#[derive(
1446 Builder,
1447 Clone,
1448 CopyGetters,
1449 Debug,
1450 Default,
1451 Deserialize,
1452 Eq,
1453 Getters,
1454 Setters,
1455 PartialEq,
1456 Serialize,
1457)]
1458#[builder(
1459 default,
1460 pattern = "owned",
1461 setter(into, strip_option),
1462 build_fn(error = "OciSpecError")
1463)]
1464pub struct LinuxPersonality {
1466 #[getset(get_copy = "pub", set = "pub")]
1467 domain: LinuxPersonalityDomain,
1469
1470 #[serde(default, skip_serializing_if = "Option::is_none")]
1471 #[getset(get = "pub", set = "pub")]
1472 flags: Option<Vec<String>>,
1474}
1475
1476#[derive(
1477 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1478)]
1479pub enum LinuxPersonalityDomain {
1481 #[serde(rename = "LINUX")]
1482 #[strum(serialize = "LINUX")]
1483 #[default]
1485 PerLinux,
1486
1487 #[serde(rename = "LINUX32")]
1488 #[strum(serialize = "LINUX32")]
1489 PerLinux32,
1491}
1492
1493#[derive(
1494 Builder,
1495 Clone,
1496 CopyGetters,
1497 Debug,
1498 Deserialize,
1499 Eq,
1500 Getters,
1501 MutGetters,
1502 Setters,
1503 PartialEq,
1504 Serialize,
1505)]
1506#[serde(rename_all = "camelCase")]
1507#[builder(
1508 pattern = "owned",
1509 setter(into, strip_option),
1510 build_fn(error = "OciSpecError")
1511)]
1512pub struct LinuxMemoryPolicy {
1514 #[getset(get_copy = "pub", set = "pub")]
1515 mode: MemoryPolicyModeType,
1517
1518 #[serde(default, skip_serializing_if = "Option::is_none")]
1519 #[getset(get = "pub", set = "pub")]
1520 nodes: Option<String>,
1523
1524 #[serde(default, skip_serializing_if = "Option::is_none")]
1525 #[getset(get = "pub", get_mut = "pub", set = "pub")]
1526 flags: Option<Vec<MemoryPolicyFlagType>>,
1528}
1529
1530impl Default for LinuxMemoryPolicy {
1531 fn default() -> Self {
1532 Self {
1533 mode: MemoryPolicyModeType::MpolDefault,
1534 nodes: None,
1535 flags: None,
1536 }
1537 }
1538}
1539
1540#[derive(
1541 Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString,
1542)]
1543pub enum MemoryPolicyModeType {
1545 #[serde(rename = "MPOL_DEFAULT")]
1546 #[strum(serialize = "MPOL_DEFAULT")]
1547 #[default]
1549 MpolDefault,
1550
1551 #[serde(rename = "MPOL_BIND")]
1552 #[strum(serialize = "MPOL_BIND")]
1553 MpolBind,
1555
1556 #[serde(rename = "MPOL_INTERLEAVE")]
1557 #[strum(serialize = "MPOL_INTERLEAVE")]
1558 MpolInterleave,
1560
1561 #[serde(rename = "MPOL_WEIGHTED_INTERLEAVE")]
1562 #[strum(serialize = "MPOL_WEIGHTED_INTERLEAVE")]
1563 MpolWeightedInterleave,
1565
1566 #[serde(rename = "MPOL_PREFERRED")]
1567 #[strum(serialize = "MPOL_PREFERRED")]
1568 MpolPreferred,
1570
1571 #[serde(rename = "MPOL_PREFERRED_MANY")]
1572 #[strum(serialize = "MPOL_PREFERRED_MANY")]
1573 MpolPreferredMany,
1575
1576 #[serde(rename = "MPOL_LOCAL")]
1577 #[strum(serialize = "MPOL_LOCAL")]
1578 MpolLocal,
1580}
1581
1582#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1583pub enum MemoryPolicyFlagType {
1585 #[serde(rename = "MPOL_F_NUMA_BALANCING")]
1586 #[strum(serialize = "MPOL_F_NUMA_BALANCING")]
1587 MpolFNumaBalancing,
1589
1590 #[serde(rename = "MPOL_F_RELATIVE_NODES")]
1591 #[strum(serialize = "MPOL_F_RELATIVE_NODES")]
1592 MpolFRelativeNodes,
1594
1595 #[serde(rename = "MPOL_F_STATIC_NODES")]
1596 #[strum(serialize = "MPOL_F_STATIC_NODES")]
1597 MpolFStaticNodes,
1599}
1600
1601#[derive(
1602 Builder,
1603 Clone,
1604 CopyGetters,
1605 Debug,
1606 Default,
1607 Deserialize,
1608 Eq,
1609 Getters,
1610 Setters,
1611 PartialEq,
1612 Serialize,
1613)]
1614#[builder(
1615 default,
1616 pattern = "owned",
1617 setter(into, strip_option),
1618 build_fn(error = "OciSpecError")
1619)]
1620pub struct LinuxTimeOffset {
1622 #[serde(default, skip_serializing_if = "Option::is_none")]
1624 #[getset(get_copy = "pub", set = "pub")]
1625 secs: Option<i64>,
1626 #[serde(default, skip_serializing_if = "Option::is_none")]
1628 #[getset(get_copy = "pub", set = "pub")]
1629 nanosecs: Option<u32>,
1630}
1631
1632#[cfg(feature = "proptests")]
1633use quickcheck::{Arbitrary, Gen};
1634
1635#[cfg(feature = "proptests")]
1636fn some_none_generator_util<T: Arbitrary>(g: &mut Gen) -> Option<T> {
1637 let choice = g.choose(&[true, false]).unwrap();
1638 match choice {
1639 false => None,
1640 true => Some(T::arbitrary(g)),
1641 }
1642}
1643
1644#[cfg(feature = "proptests")]
1645impl Arbitrary for LinuxDeviceCgroup {
1646 fn arbitrary(g: &mut Gen) -> LinuxDeviceCgroup {
1647 let typ_choices = ["a", "b", "c", "u", "p"];
1648
1649 let typ_chosen = g.choose(&typ_choices).unwrap();
1650
1651 let typ = match typ_chosen.to_string().as_str() {
1652 "a" => LinuxDeviceType::A,
1653 "b" => LinuxDeviceType::B,
1654 "c" => LinuxDeviceType::C,
1655 "u" => LinuxDeviceType::U,
1656 "p" => LinuxDeviceType::P,
1657 _ => LinuxDeviceType::A,
1658 };
1659
1660 let access_choices = ["rwm", "m"];
1661 LinuxDeviceCgroup {
1662 allow: bool::arbitrary(g),
1663 typ: typ.into(),
1664 major: some_none_generator_util::<i64>(g),
1665 minor: some_none_generator_util::<i64>(g),
1666 access: g.choose(&access_choices).unwrap().to_string().into(),
1667 }
1668 }
1669}
1670
1671#[cfg(feature = "proptests")]
1672impl Arbitrary for LinuxMemory {
1673 fn arbitrary(g: &mut Gen) -> LinuxMemory {
1674 LinuxMemory {
1675 kernel: some_none_generator_util::<i64>(g),
1676 kernel_tcp: some_none_generator_util::<i64>(g),
1677 limit: some_none_generator_util::<i64>(g),
1678 reservation: some_none_generator_util::<i64>(g),
1679 swap: some_none_generator_util::<i64>(g),
1680 swappiness: some_none_generator_util::<u64>(g),
1681 disable_oom_killer: some_none_generator_util::<bool>(g),
1682 use_hierarchy: some_none_generator_util::<bool>(g),
1683 check_before_update: some_none_generator_util::<bool>(g),
1684 }
1685 }
1686}
1687
1688#[cfg(feature = "proptests")]
1689impl Arbitrary for LinuxHugepageLimit {
1690 fn arbitrary(g: &mut Gen) -> LinuxHugepageLimit {
1691 let unit_choice = ["KB", "MB", "GB"];
1692 let unit = g.choose(&unit_choice).unwrap();
1693 let page_size = u64::arbitrary(g).to_string() + unit;
1694
1695 LinuxHugepageLimit {
1696 page_size,
1697 limit: i64::arbitrary(g),
1698 }
1699 }
1700}
1701
1702#[cfg(test)]
1703mod tests {
1704 use super::*;
1705
1706 #[test]
1708 fn device_type_enum_to_str() {
1709 let type_a = LinuxDeviceType::A;
1710 assert_eq!(type_a.as_str(), "a");
1711
1712 let type_b = LinuxDeviceType::B;
1713 assert_eq!(type_b.as_str(), "b");
1714
1715 let type_c = LinuxDeviceType::C;
1716 assert_eq!(type_c.as_str(), "c");
1717 }
1718
1719 #[test]
1720 fn device_type_string_to_enum() {
1721 let devtype_str = "a";
1722 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1723 assert_eq!(devtype_enum, LinuxDeviceType::A);
1724
1725 let devtype_str = "b";
1726 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1727 assert_eq!(devtype_enum, LinuxDeviceType::B);
1728
1729 let devtype_str = "c";
1730 let devtype_enum: LinuxDeviceType = devtype_str.parse().unwrap();
1731 assert_eq!(devtype_enum, LinuxDeviceType::C);
1732
1733 let invalid_devtype_str = "x";
1734 let unknown_devtype = invalid_devtype_str.parse::<LinuxDeviceType>();
1735 assert!(unknown_devtype.is_err());
1736 }
1737
1738 #[test]
1740 fn ns_type_enum_to_string() {
1741 let type_a = LinuxNamespaceType::Network;
1742 assert_eq!(type_a.to_string(), "net");
1743
1744 let type_b = LinuxNamespaceType::Mount;
1745 assert_eq!(type_b.to_string(), "mnt");
1746
1747 let type_c = LinuxNamespaceType::Ipc;
1748 assert_eq!(type_c.to_string(), "ipc");
1749 }
1750
1751 #[test]
1752 fn ns_type_string_to_enum() {
1753 let nstype_str = "net";
1754 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1755 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1756
1757 let nstype_str = "network";
1758 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1759 assert_eq!(nstype_enum, LinuxNamespaceType::Network);
1760
1761 let nstype_str = "ipc";
1762 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1763 assert_eq!(nstype_enum, LinuxNamespaceType::Ipc);
1764
1765 let nstype_str = "cgroup";
1766 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1767 assert_eq!(nstype_enum, LinuxNamespaceType::Cgroup);
1768
1769 let nstype_str = "mount";
1770 let nstype_enum = LinuxNamespaceType::try_from(nstype_str).unwrap();
1771 assert_eq!(nstype_enum, LinuxNamespaceType::Mount);
1772
1773 let invalid_nstype_str = "xxx";
1774 let unknown_nstype = LinuxNamespaceType::try_from(invalid_nstype_str);
1775 assert!(unknown_nstype.is_err());
1776 }
1777
1778 #[test]
1780 fn seccomp_action_enum_to_string() {
1781 let type_a = LinuxSeccompAction::ScmpActKill;
1782 assert_eq!(type_a.to_string(), "SCMP_ACT_KILL");
1783
1784 let type_b = LinuxSeccompAction::ScmpActAllow;
1785 assert_eq!(type_b.to_string(), "SCMP_ACT_ALLOW");
1786
1787 let type_c = LinuxSeccompAction::ScmpActNotify;
1788 assert_eq!(type_c.to_string(), "SCMP_ACT_NOTIFY");
1789 }
1790
1791 #[test]
1792 fn seccomp_action_string_to_enum() {
1793 let action_str = "SCMP_ACT_KILL";
1794 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1795 assert_eq!(action_enum, LinuxSeccompAction::ScmpActKill);
1796
1797 let action_str = "SCMP_ACT_ALLOW";
1798 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1799 assert_eq!(action_enum, LinuxSeccompAction::ScmpActAllow);
1800
1801 let action_str = "SCMP_ACT_NOTIFY";
1802 let action_enum: LinuxSeccompAction = action_str.parse().unwrap();
1803 assert_eq!(action_enum, LinuxSeccompAction::ScmpActNotify);
1804
1805 let invalid_action_str = "x";
1806 let unknown_action = invalid_action_str.parse::<LinuxSeccompAction>();
1807 assert!(unknown_action.is_err());
1808 }
1809
1810 #[test]
1812 fn seccomp_arch_enum_to_string() {
1813 let type_a = Arch::ScmpArchX86_64;
1814 assert_eq!(type_a.to_string(), "SCMP_ARCH_X86_64");
1815
1816 let type_b = Arch::ScmpArchAarch64;
1817 assert_eq!(type_b.to_string(), "SCMP_ARCH_AARCH64");
1818
1819 let type_c = Arch::ScmpArchPpc64le;
1820 assert_eq!(type_c.to_string(), "SCMP_ARCH_PPC64LE");
1821 }
1822
1823 #[test]
1824 fn seccomp_arch_string_to_enum() {
1825 let arch_type_str = "SCMP_ARCH_X86_64";
1826 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1827 assert_eq!(arch_type_enum, Arch::ScmpArchX86_64);
1828
1829 let arch_type_str = "SCMP_ARCH_AARCH64";
1830 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1831 assert_eq!(arch_type_enum, Arch::ScmpArchAarch64);
1832
1833 let arch_type_str = "SCMP_ARCH_PPC64LE";
1834 let arch_type_enum: Arch = arch_type_str.parse().unwrap();
1835 assert_eq!(arch_type_enum, Arch::ScmpArchPpc64le);
1836
1837 let invalid_arch_str = "x";
1838 let unknown_arch = invalid_arch_str.parse::<Arch>();
1839 assert!(unknown_arch.is_err());
1840 }
1841
1842 #[test]
1844 fn seccomp_filter_flag_enum_to_string() {
1845 let type_a = LinuxSeccompFilterFlag::SeccompFilterFlagLog;
1846 assert_eq!(type_a.to_string(), "SECCOMP_FILTER_FLAG_LOG");
1847
1848 let type_b = LinuxSeccompFilterFlag::SeccompFilterFlagTsync;
1849 assert_eq!(type_b.to_string(), "SECCOMP_FILTER_FLAG_TSYNC");
1850
1851 let type_c = LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow;
1852 assert_eq!(type_c.to_string(), "SECCOMP_FILTER_FLAG_SPEC_ALLOW");
1853
1854 let type_d = LinuxSeccompFilterFlag::SeccompFilterFlagWaitKillableRecv;
1855 assert_eq!(type_d.to_string(), "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV");
1856 }
1857
1858 #[test]
1859 fn seccomp_filter_flag_string_to_enum() {
1860 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_LOG";
1861 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1862 assert_eq!(
1863 filter_flag_type_enum,
1864 LinuxSeccompFilterFlag::SeccompFilterFlagLog
1865 );
1866
1867 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_TSYNC";
1868 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1869 assert_eq!(
1870 filter_flag_type_enum,
1871 LinuxSeccompFilterFlag::SeccompFilterFlagTsync
1872 );
1873
1874 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_SPEC_ALLOW";
1875 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1876 assert_eq!(
1877 filter_flag_type_enum,
1878 LinuxSeccompFilterFlag::SeccompFilterFlagSpecAllow
1879 );
1880
1881 let filter_flag_type_str = "SECCOMP_FILTER_FLAG_WAIT_KILLABLE_RECV";
1882 let filter_flag_type_enum: LinuxSeccompFilterFlag = filter_flag_type_str.parse().unwrap();
1883 assert_eq!(
1884 filter_flag_type_enum,
1885 LinuxSeccompFilterFlag::SeccompFilterFlagWaitKillableRecv
1886 );
1887
1888 let invalid_filter_flag_str = "x";
1889 let unknown_arch = invalid_filter_flag_str.parse::<LinuxSeccompFilterFlag>();
1890 assert!(unknown_arch.is_err());
1891 }
1892
1893 #[test]
1895 fn seccomp_operator_enum_to_string() {
1896 let type_a = LinuxSeccompOperator::ScmpCmpNe;
1897 assert_eq!(type_a.to_string(), "SCMP_CMP_NE");
1898
1899 let type_b = LinuxSeccompOperator::ScmpCmpMaskedEq;
1900 assert_eq!(type_b.to_string(), "SCMP_CMP_MASKED_EQ");
1901
1902 let type_c = LinuxSeccompOperator::ScmpCmpGt;
1903 assert_eq!(type_c.to_string(), "SCMP_CMP_GT");
1904 }
1905
1906 #[test]
1908 fn seccomp_action_as_u32() {
1909 let action = LinuxSeccompAction::ScmpActErrno;
1910 assert_eq!(action.as_u32(Option::None), 0x00050001);
1911
1912 let action = LinuxSeccompAction::ScmpActErrno;
1913 assert_eq!(action.as_u32(Option::Some(10)), 0x00050000 | 10);
1914
1915 let action = LinuxSeccompAction::ScmpActTrace;
1916 assert_eq!(action.as_u32(Option::None), 0x7ff00001);
1917
1918 let action = LinuxSeccompAction::ScmpActTrace;
1919 assert_eq!(action.as_u32(Option::Some(10)), 0x7ff00000 | 10);
1920 }
1921
1922 #[test]
1923 fn seccomp_operator_string_to_enum() {
1924 let seccomp_operator_str = "SCMP_CMP_GT";
1925 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1926 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpGt);
1927
1928 let seccomp_operator_str = "SCMP_CMP_NE";
1929 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1930 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpNe);
1931
1932 let seccomp_operator_str = "SCMP_CMP_MASKED_EQ";
1933 let seccomp_operator_enum: LinuxSeccompOperator = seccomp_operator_str.parse().unwrap();
1934 assert_eq!(seccomp_operator_enum, LinuxSeccompOperator::ScmpCmpMaskedEq);
1935
1936 let invalid_seccomp_operator_str = "x";
1937 let unknown_operator = invalid_seccomp_operator_str.parse::<LinuxSeccompOperator>();
1938 assert!(unknown_operator.is_err());
1939 }
1940
1941 #[test]
1943 fn memory_policy_mode_enum_to_string() {
1944 let mode_a = MemoryPolicyModeType::MpolDefault;
1945 assert_eq!(mode_a.to_string(), "MPOL_DEFAULT");
1946
1947 let mode_b = MemoryPolicyModeType::MpolBind;
1948 assert_eq!(mode_b.to_string(), "MPOL_BIND");
1949
1950 let mode_c = MemoryPolicyModeType::MpolInterleave;
1951 assert_eq!(mode_c.to_string(), "MPOL_INTERLEAVE");
1952
1953 let mode_d = MemoryPolicyModeType::MpolWeightedInterleave;
1954 assert_eq!(mode_d.to_string(), "MPOL_WEIGHTED_INTERLEAVE");
1955
1956 let mode_e = MemoryPolicyModeType::MpolPreferred;
1957 assert_eq!(mode_e.to_string(), "MPOL_PREFERRED");
1958
1959 let mode_f = MemoryPolicyModeType::MpolPreferredMany;
1960 assert_eq!(mode_f.to_string(), "MPOL_PREFERRED_MANY");
1961
1962 let mode_g = MemoryPolicyModeType::MpolLocal;
1963 assert_eq!(mode_g.to_string(), "MPOL_LOCAL");
1964 }
1965
1966 #[test]
1967 fn memory_policy_mode_string_to_enum() {
1968 let mode_str = "MPOL_INTERLEAVE";
1969 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1970 assert_eq!(mode_enum, MemoryPolicyModeType::MpolInterleave);
1971
1972 let mode_str = "MPOL_BIND";
1973 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1974 assert_eq!(mode_enum, MemoryPolicyModeType::MpolBind);
1975
1976 let mode_str = "MPOL_DEFAULT";
1977 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1978 assert_eq!(mode_enum, MemoryPolicyModeType::MpolDefault);
1979
1980 let mode_str = "MPOL_WEIGHTED_INTERLEAVE";
1981 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1982 assert_eq!(mode_enum, MemoryPolicyModeType::MpolWeightedInterleave);
1983
1984 let mode_str = "MPOL_PREFERRED";
1985 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1986 assert_eq!(mode_enum, MemoryPolicyModeType::MpolPreferred);
1987
1988 let mode_str = "MPOL_PREFERRED_MANY";
1989 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1990 assert_eq!(mode_enum, MemoryPolicyModeType::MpolPreferredMany);
1991
1992 let mode_str = "MPOL_LOCAL";
1993 let mode_enum: MemoryPolicyModeType = mode_str.parse().unwrap();
1994 assert_eq!(mode_enum, MemoryPolicyModeType::MpolLocal);
1995
1996 let invalid_mode_str = "INVALID_MODE";
1997 let unknown_mode = invalid_mode_str.parse::<MemoryPolicyModeType>();
1998 assert!(unknown_mode.is_err());
1999 }
2000
2001 #[test]
2003 fn memory_policy_flag_enum_to_string() {
2004 let flag_a = MemoryPolicyFlagType::MpolFNumaBalancing;
2005 assert_eq!(flag_a.to_string(), "MPOL_F_NUMA_BALANCING");
2006
2007 let flag_b = MemoryPolicyFlagType::MpolFRelativeNodes;
2008 assert_eq!(flag_b.to_string(), "MPOL_F_RELATIVE_NODES");
2009
2010 let flag_c = MemoryPolicyFlagType::MpolFStaticNodes;
2011 assert_eq!(flag_c.to_string(), "MPOL_F_STATIC_NODES");
2012 }
2013
2014 #[test]
2015 fn memory_policy_flag_string_to_enum() {
2016 let flag_str = "MPOL_F_NUMA_BALANCING";
2017 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
2018 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFNumaBalancing);
2019
2020 let flag_str = "MPOL_F_RELATIVE_NODES";
2021 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
2022 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFRelativeNodes);
2023
2024 let flag_str = "MPOL_F_STATIC_NODES";
2025 let flag_enum: MemoryPolicyFlagType = flag_str.parse().unwrap();
2026 assert_eq!(flag_enum, MemoryPolicyFlagType::MpolFStaticNodes);
2027
2028 let invalid_flag_str = "INVALID_FLAG";
2029 let unknown_flag = invalid_flag_str.parse::<MemoryPolicyFlagType>();
2030 assert!(unknown_flag.is_err());
2031 }
2032
2033 #[test]
2034 fn test_linux_memory_policy_serialization() {
2035 let memory_policy = LinuxMemoryPolicy {
2036 mode: MemoryPolicyModeType::MpolInterleave,
2037 nodes: Some("0-3,7".to_string()),
2038 flags: Some(vec![
2039 MemoryPolicyFlagType::MpolFStaticNodes,
2040 MemoryPolicyFlagType::MpolFRelativeNodes,
2041 ]),
2042 };
2043
2044 let json = serde_json::to_string(&memory_policy).unwrap();
2045 let deserialized: LinuxMemoryPolicy = serde_json::from_str(&json).unwrap();
2046
2047 assert_eq!(deserialized.mode, MemoryPolicyModeType::MpolInterleave);
2048 assert_eq!(deserialized.nodes, Some("0-3,7".to_string()));
2049 assert_eq!(
2050 deserialized.flags,
2051 Some(vec![
2052 MemoryPolicyFlagType::MpolFStaticNodes,
2053 MemoryPolicyFlagType::MpolFRelativeNodes,
2054 ])
2055 );
2056 }
2057
2058 #[test]
2059 fn test_linux_memory_policy_default() {
2060 let memory_policy = LinuxMemoryPolicy::default();
2061 assert_eq!(memory_policy.mode, MemoryPolicyModeType::MpolDefault);
2062 assert_eq!(memory_policy.nodes, None);
2063 assert_eq!(memory_policy.flags, None);
2064 }
2065}