oci_spec/runtime/
linux.rs

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")]
20/// Linux contains platform-specific configuration for Linux based
21/// containers.
22pub struct Linux {
23    #[serde(default, skip_serializing_if = "Option::is_none")]
24    /// UIDMappings specifies user mappings for supporting user namespaces.
25    uid_mappings: Option<Vec<LinuxIdMapping>>,
26
27    #[serde(default, skip_serializing_if = "Option::is_none")]
28    /// GIDMappings specifies group mappings for supporting user namespaces.
29    gid_mappings: Option<Vec<LinuxIdMapping>>,
30
31    #[serde(default, skip_serializing_if = "Option::is_none")]
32    /// Sysctl are a set of key value pairs that are set for the container
33    /// on start.
34    sysctl: Option<HashMap<String, String>>,
35
36    #[serde(default, skip_serializing_if = "Option::is_none")]
37    /// Resources contain cgroup information for handling resource
38    /// constraints for the container.
39    resources: Option<LinuxResources>,
40
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    /// CgroupsPath specifies the path to cgroups that are created and/or
43    /// joined by the container. The path is expected to be relative
44    /// to the cgroups mountpoint. If resources are specified,
45    /// the cgroups at CgroupsPath will be updated based on resources.
46    cgroups_path: Option<PathBuf>,
47
48    #[serde(default, skip_serializing_if = "Option::is_none")]
49    /// Namespaces contains the namespaces that are created and/or joined by
50    /// the container.
51    namespaces: Option<Vec<LinuxNamespace>>,
52
53    #[serde(default, skip_serializing_if = "Option::is_none")]
54    /// Devices are a list of device nodes that are created for the
55    /// container.
56    devices: Option<Vec<LinuxDevice>>,
57
58    #[serde(default, skip_serializing_if = "Option::is_none")]
59    /// Seccomp specifies the seccomp security settings for the container.
60    seccomp: Option<LinuxSeccomp>,
61
62    #[serde(default, skip_serializing_if = "Option::is_none")]
63    /// RootfsPropagation is the rootfs mount propagation mode for the
64    /// container.
65    rootfs_propagation: Option<String>,
66
67    #[serde(default, skip_serializing_if = "Option::is_none")]
68    /// MaskedPaths masks over the provided paths inside the container.
69    masked_paths: Option<Vec<String>>,
70
71    #[serde(default, skip_serializing_if = "Option::is_none")]
72    /// ReadonlyPaths sets the provided paths as RO inside the container.
73    readonly_paths: Option<Vec<String>>,
74
75    #[serde(default, skip_serializing_if = "Option::is_none")]
76    /// MountLabel specifies the selinux context for the mounts in the
77    /// container.
78    mount_label: Option<String>,
79
80    #[serde(default, skip_serializing_if = "Option::is_none")]
81    /// IntelRdt contains Intel Resource Director Technology (RDT)
82    /// information for handling resource constraints and monitoring metrics
83    /// (e.g., L3 cache, memory bandwidth) for the container.
84    intel_rdt: Option<LinuxIntelRdt>,
85
86    #[serde(default, skip_serializing_if = "Option::is_none")]
87    /// Personality contains configuration for the Linux personality
88    /// syscall.
89    personality: Option<LinuxPersonality>,
90
91    #[serde(default, skip_serializing_if = "Option::is_none")]
92    /// TimeOffsets specifies the offset for supporting time namespaces.
93    time_offsets: Option<HashMap<String, String>>,
94}
95
96// Default impl for Linux (see funtions for more info)
97impl Default for Linux {
98    fn default() -> Self {
99        Linux {
100            // Creates empty Vec
101            uid_mappings: Default::default(),
102            // Creates empty Vec
103            gid_mappings: Default::default(),
104            // Empty sysctl Hashmap
105            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            // Defaults to None
118            cgroups_path: Default::default(),
119            namespaces: get_default_namespaces().into(),
120            // Empty Vec
121            devices: Default::default(),
122            // Empty String
123            rootfs_propagation: Default::default(),
124            masked_paths: get_default_maskedpaths().into(),
125            readonly_paths: get_default_readonly_paths().into(),
126            // Empty String
127            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    /// Return rootless Linux configuration.
138    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")]
174/// LinuxIDMapping specifies UID/GID mappings.
175pub struct LinuxIdMapping {
176    #[serde(default, rename = "hostID")]
177    /// HostID is the starting UID/GID on the host to be mapped to
178    /// `container_id`.
179    host_id: u32,
180
181    #[serde(default, rename = "containerID")]
182    /// ContainerID is the starting UID/GID in the container.
183    container_id: u32,
184
185    #[serde(default)]
186    /// Size is the number of IDs to be mapped.
187    size: u32,
188}
189
190#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, EnumString)]
191#[strum(serialize_all = "lowercase")]
192#[serde(rename_all = "lowercase")]
193/// Device types
194pub enum LinuxDeviceType {
195    /// All
196    A,
197
198    /// block (buffered)
199    B,
200
201    /// character (unbuffered)
202    C,
203
204    /// character (unbufferd)
205    U,
206
207    /// FIFO
208    P,
209}
210
211#[allow(clippy::derivable_impls)] // because making it clear that All is the default
212impl Default for LinuxDeviceType {
213    fn default() -> LinuxDeviceType {
214        LinuxDeviceType::A
215    }
216}
217
218impl LinuxDeviceType {
219    /// Retrieve a string reference for the device type.
220    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)]
251/// Represents a device rule for the devices specified to the device
252/// controller
253pub struct LinuxDeviceCgroup {
254    #[serde(default)]
255    #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
256    /// Allow or deny
257    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    /// Device type, block, char, etc.
262    typ: Option<LinuxDeviceType>,
263
264    #[serde(default, skip_serializing_if = "Option::is_none")]
265    #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
266    /// Device's major number
267    major: Option<i64>,
268
269    #[serde(default, skip_serializing_if = "Option::is_none")]
270    #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
271    /// Device's minor number
272    minor: Option<i64>,
273
274    /// Cgroup access premissions format, rwm.
275    #[serde(default)]
276    #[getset(get_mut = "pub", get = "pub", set = "pub")]
277    access: Option<String>,
278}
279
280/// This ToString trait is automatically implemented for any type which implements the Display trait.
281/// As such, ToString shouldn’t be implemented directly: Display should be implemented instead,
282/// and you get the ToString implementation for free.
283impl 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")]
316/// LinuxMemory for Linux cgroup 'memory' resource management.
317pub struct LinuxMemory {
318    #[serde(skip_serializing_if = "Option::is_none")]
319    #[getset(get_copy = "pub", set = "pub")]
320    /// Memory limit (in bytes).
321    limit: Option<i64>,
322
323    #[serde(skip_serializing_if = "Option::is_none")]
324    #[getset(get_copy = "pub", set = "pub")]
325    /// Memory reservation or soft_limit (in bytes).
326    reservation: Option<i64>,
327
328    #[serde(skip_serializing_if = "Option::is_none")]
329    #[getset(get_copy = "pub", set = "pub")]
330    /// Total memory limit (memory + swap).
331    swap: Option<i64>,
332
333    #[serde(skip_serializing_if = "Option::is_none")]
334    #[getset(get_copy = "pub", set = "pub")]
335    /// Kernel memory limit (in bytes).
336    kernel: Option<i64>,
337
338    #[serde(skip_serializing_if = "Option::is_none", rename = "kernelTCP")]
339    #[getset(get_copy = "pub", set = "pub")]
340    /// Kernel memory limit for tcp (in bytes).
341    kernel_tcp: Option<i64>,
342
343    #[serde(skip_serializing_if = "Option::is_none")]
344    #[getset(get_copy = "pub", set = "pub")]
345    /// How aggressive the kernel will swap memory pages.
346    swappiness: Option<u64>,
347
348    #[serde(skip_serializing_if = "Option::is_none", rename = "disableOOMKiller")]
349    #[getset(get_copy = "pub", set = "pub")]
350    /// DisableOOMKiller disables the OOM killer for out of memory
351    /// conditions.
352    disable_oom_killer: Option<bool>,
353
354    #[serde(skip_serializing_if = "Option::is_none")]
355    #[getset(get_copy = "pub", set = "pub")]
356    /// Enables hierarchical memory accounting
357    use_hierarchy: Option<bool>,
358
359    #[serde(skip_serializing_if = "Option::is_none")]
360    #[getset(get_copy = "pub", set = "pub")]
361    /// Enables checking if a new memory limit is lower
362    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)]
385/// LinuxCPU for Linux cgroup 'cpu' resource management.
386pub struct LinuxCpu {
387    #[serde(skip_serializing_if = "Option::is_none")]
388    #[getset(get_copy = "pub", set = "pub")]
389    /// CPU shares (relative weight (ratio) vs. other cgroups with cpu
390    /// shares).
391    shares: Option<u64>,
392
393    #[serde(skip_serializing_if = "Option::is_none")]
394    #[getset(get_copy = "pub", set = "pub")]
395    /// CPU hardcap limit (in usecs). Allowed cpu time in a given period.
396    quota: Option<i64>,
397
398    #[serde(skip_serializing_if = "Option::is_none")]
399    #[getset(get_copy = "pub", set = "pub")]
400    /// Cgroups are configured with minimum weight, 0: default behavior, 1: SCHED_IDLE.
401    idle: Option<i64>,
402
403    #[serde(skip_serializing_if = "Option::is_none")]
404    #[getset(get_copy = "pub", set = "pub")]
405    /// Maximum amount of accumulated time in microseconds for which tasks
406    /// in a cgroup can run additionally for burst during one period
407    burst: Option<u64>,
408
409    #[serde(skip_serializing_if = "Option::is_none")]
410    #[getset(get_copy = "pub", set = "pub")]
411    /// CPU period to be used for hardcapping (in usecs).
412    period: Option<u64>,
413
414    #[serde(skip_serializing_if = "Option::is_none")]
415    #[getset(get_copy = "pub", set = "pub")]
416    /// How much time realtime scheduling may use (in usecs).
417    realtime_runtime: Option<i64>,
418
419    #[serde(skip_serializing_if = "Option::is_none")]
420    #[getset(get_copy = "pub", set = "pub")]
421    /// CPU period to be used for realtime scheduling (in usecs).
422    realtime_period: Option<u64>,
423
424    #[serde(default, skip_serializing_if = "Option::is_none")]
425    #[getset(get = "pub", set = "pub")]
426    /// CPUs to use within the cpuset. Default is to use any CPU available.
427    cpus: Option<String>,
428
429    #[serde(default, skip_serializing_if = "Option::is_none")]
430    #[getset(get = "pub", set = "pub")]
431    /// List of memory nodes in the cpuset. Default is to use any available
432    /// memory node.
433    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")]
456/// LinuxPids for Linux cgroup 'pids' resource management (Linux 4.3).
457pub struct LinuxPids {
458    #[serde(default)]
459    /// Maximum number of PIDs. Default is "no limit".
460    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")]
474/// LinuxWeightDevice struct holds a `major:minor weight` pair for
475/// weightDevice.
476pub struct LinuxWeightDevice {
477    #[serde(default)]
478    /// Major is the device's major number.
479    major: i64,
480
481    #[serde(default)]
482    /// Minor is the device's minor number.
483    minor: i64,
484
485    #[serde(skip_serializing_if = "Option::is_none")]
486    /// Weight is the bandwidth rate for the device.
487    weight: Option<u16>,
488
489    #[serde(skip_serializing_if = "Option::is_none")]
490    /// LeafWeight is the bandwidth rate for the device while competing with
491    /// the cgroup's child cgroups, CFQ scheduler only.
492    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")]
505/// LinuxThrottleDevice struct holds a `major:minor rate_per_second` pair.
506pub struct LinuxThrottleDevice {
507    #[serde(default)]
508    /// Major is the device's major number.
509    major: i64,
510
511    #[serde(default)]
512    /// Minor is the device's minor number.
513    minor: i64,
514
515    #[serde(default)]
516    /// Rate is the IO rate limit per cgroup per device.
517    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)]
540/// LinuxBlockIO for Linux cgroup 'blkio' resource management.
541pub struct LinuxBlockIo {
542    #[serde(skip_serializing_if = "Option::is_none")]
543    #[getset(get_copy = "pub", set = "pub")]
544    /// Specifies per cgroup weight.
545    weight: Option<u16>,
546
547    #[serde(skip_serializing_if = "Option::is_none")]
548    #[getset(get_copy = "pub", set = "pub")]
549    /// Specifies tasks' weight in the given cgroup while competing with the
550    /// cgroup's child cgroups, CFQ scheduler only.
551    leaf_weight: Option<u16>,
552
553    #[serde(skip_serializing_if = "Option::is_none")]
554    #[getset(get = "pub", set = "pub")]
555    /// Weight per cgroup per device, can override BlkioWeight.
556    weight_device: Option<Vec<LinuxWeightDevice>>,
557
558    #[serde(skip_serializing_if = "Option::is_none")]
559    #[getset(get = "pub", set = "pub")]
560    /// IO read rate limit per cgroup per device, bytes per second.
561    throttle_read_bps_device: Option<Vec<LinuxThrottleDevice>>,
562
563    #[serde(skip_serializing_if = "Option::is_none")]
564    #[getset(get = "pub", set = "pub")]
565    /// IO write rate limit per cgroup per device, bytes per second.
566    throttle_write_bps_device: Option<Vec<LinuxThrottleDevice>>,
567
568    #[serde(skip_serializing_if = "Option::is_none")]
569    #[getset(get = "pub", set = "pub")]
570    /// IO read rate limit per cgroup per device, IO per second.
571    throttle_read_iops_device: Option<Vec<LinuxThrottleDevice>>,
572
573    #[serde(skip_serializing_if = "Option::is_none")]
574    #[getset(get = "pub", set = "pub")]
575    /// IO write rate limit per cgroup per device, IO per second.
576    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)]
599/// LinuxHugepageLimit structure corresponds to limiting kernel hugepages.
600/// Default to reservation limits if supported. Otherwise fallback to page fault limits.
601pub struct LinuxHugepageLimit {
602    #[serde(default)]
603    #[getset(get = "pub", set = "pub")]
604    /// Pagesize is the hugepage size.
605    /// Format: "&lt;size&gt;&lt;unit-prefix&gt;B' (e.g. 64KB, 2MB, 1GB, etc.)
606    page_size: String,
607
608    #[serde(default)]
609    #[getset(get_copy = "pub", set = "pub")]
610    /// Limit is the limit of "hugepagesize" hugetlb reservations (if supported) or usage.
611    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)]
633/// LinuxInterfacePriority for network interfaces.
634pub struct LinuxInterfacePriority {
635    #[serde(default)]
636    #[getset(get = "pub", set = "pub")]
637    /// Name is the name of the network interface.
638    name: String,
639
640    #[serde(default)]
641    #[getset(get_copy = "pub", set = "pub")]
642    /// Priority for the interface.
643    priority: u32,
644}
645
646/// This ToString trait is automatically implemented for any type which implements the Display trait.
647/// As such, ToString shouldn’t be implemented directly: Display should be implemented instead,
648/// and you get the ToString implementation for free.
649impl Display for LinuxInterfacePriority {
650    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
651        // Serde seralization never fails since this is
652        // a combination of String and enums.
653        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)]
676/// LinuxNetwork identification and priority configuration.
677pub struct LinuxNetwork {
678    #[serde(skip_serializing_if = "Option::is_none", rename = "classID")]
679    #[getset(get_copy = "pub", set = "pub")]
680    /// Set class identifier for container's network packets
681    class_id: Option<u32>,
682
683    #[serde(default, skip_serializing_if = "Option::is_none")]
684    #[getset(get = "pub", set = "pub")]
685    /// Set priority of network traffic for container.
686    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)]
710/// Resource constraints for container
711pub struct LinuxResources {
712    #[serde(default, skip_serializing_if = "Option::is_none")]
713    #[getset(get_mut = "pub", get = "pub", set = "pub")]
714    /// Devices configures the device allowlist.
715    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 restriction configuration.
720    memory: Option<LinuxMemory>,
721
722    #[serde(default, skip_serializing_if = "Option::is_none")]
723    #[getset(get_mut = "pub", get = "pub", set = "pub")]
724    /// CPU resource restriction configuration.
725    cpu: Option<LinuxCpu>,
726
727    #[serde(default, skip_serializing_if = "Option::is_none")]
728    #[getset(get_mut = "pub", get = "pub", set = "pub")]
729    /// Task resource restrictions
730    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    /// BlockIO restriction configuration.
735    block_io: Option<LinuxBlockIo>,
736
737    #[serde(default, skip_serializing_if = "Option::is_none")]
738    #[getset(get_mut = "pub", get = "pub", set = "pub")]
739    /// Hugetlb limit (in bytes).
740    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 restriction configuration.
745    network: Option<LinuxNetwork>,
746
747    #[serde(default, skip_serializing_if = "Option::is_none")]
748    #[getset(get_mut = "pub", get = "pub", set = "pub")]
749    /// Rdma resource restriction configuration. Limits are a set of key
750    /// value pairs that define RDMA resource limits, where the key
751    /// is device name and value is resource limits.
752    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 resources.
757    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")]
781/// LinuxRdma for Linux cgroup 'rdma' resource management (Linux 4.11).
782pub struct LinuxRdma {
783    #[serde(skip_serializing_if = "Option::is_none")]
784    /// Maximum number of HCA handles that can be opened. Default is "no
785    /// limit".
786    hca_handles: Option<u32>,
787
788    #[serde(skip_serializing_if = "Option::is_none")]
789    /// Maximum number of HCA objects that can be created. Default is "no
790    /// limit".
791    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")]
797/// Available Linux namespaces.
798pub enum LinuxNamespaceType {
799    #[strum(to_string = "mnt")]
800    /// Mount Namespace for isolating mount points
801    Mount = 0x00020000,
802
803    /// Cgroup Namespace for isolating cgroup hierarchies
804    Cgroup = 0x02000000,
805
806    /// Uts Namespace for isolating hostname and NIS domain name
807    Uts = 0x04000000,
808
809    /// Ipc Namespace for isolating System V, IPC, POSIX message queues
810    Ipc = 0x08000000,
811
812    /// User Namespace for isolating user and group  ids
813    User = 0x10000000,
814
815    /// PID Namespace for isolating process ids
816    Pid = 0x20000000,
817
818    #[strum(to_string = "net")]
819    /// Network Namespace for isolating network devices, ports, stacks etc.
820    Network = 0x40000000,
821
822    /// Time Namespace for isolating the clocks
823    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)]
871/// LinuxNamespace is the configuration for a Linux namespace.
872pub struct LinuxNamespace {
873    #[serde(rename = "type")]
874    #[getset(get_copy = "pub", set = "pub")]
875    /// Type is the type of namespace.
876    typ: LinuxNamespaceType,
877
878    #[serde(default, skip_serializing_if = "Option::is_none")]
879    #[getset(get = "pub", set = "pub")]
880    /// Path is a path to an existing namespace persisted on disk that can
881    /// be joined and is of the same type
882    path: Option<PathBuf>,
883}
884
885/// Utility function to get default namespaces.
886pub 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)]
936/// LinuxDevice represents the mknod information for a Linux special device
937/// file.
938pub struct LinuxDevice {
939    #[serde(default)]
940    #[getset(get_mut = "pub", get = "pub", set = "pub")]
941    /// Path to the device.
942    path: PathBuf,
943
944    #[serde(rename = "type")]
945    #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
946    /// Device type, block, char, etc..
947    typ: LinuxDeviceType,
948
949    #[serde(default)]
950    #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
951    /// Major is the device's major number.
952    major: i64,
953
954    #[serde(default)]
955    #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
956    /// Minor is the device's minor number.
957    minor: i64,
958
959    #[serde(default, skip_serializing_if = "Option::is_none")]
960    #[getset(get_mut = "pub", get_copy = "pub", set = "pub")]
961    /// FileMode permission bits for the device.
962    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 of the device.
967    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 of the device.
972    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)]
1007/// LinuxSeccomp represents syscall restrictions.
1008pub struct LinuxSeccomp {
1009    #[getset(get_copy = "pub", set = "pub")]
1010    /// The default action to be done.
1011    default_action: LinuxSeccompAction,
1012
1013    #[serde(default, skip_serializing_if = "Option::is_none")]
1014    #[getset(get_copy = "pub", set = "pub")]
1015    /// The default error return code to use when the default action is SCMP_ACT_ERRNO.
1016    default_errno_ret: Option<u32>,
1017
1018    #[serde(default, skip_serializing_if = "Option::is_none")]
1019    #[getset(get = "pub", set = "pub")]
1020    /// Available architectures for the restriction.
1021    architectures: Option<Vec<Arch>>,
1022
1023    #[serde(default, skip_serializing_if = "Option::is_none")]
1024    #[getset(get = "pub", set = "pub")]
1025    /// Flags added to the seccomp restriction.
1026    flags: Option<Vec<LinuxSeccompFilterFlag>>,
1027
1028    #[serde(default, skip_serializing_if = "Option::is_none")]
1029    #[getset(get = "pub", set = "pub")]
1030    /// The unix domain socket path over which runtime will use for `SCMP_ACT_NOTIFY`.
1031    listener_path: Option<PathBuf>,
1032
1033    #[serde(default, skip_serializing_if = "Option::is_none")]
1034    #[getset(get = "pub", set = "pub")]
1035    /// An opaque data to pass to the seccomp agent.
1036    listener_metadata: Option<String>,
1037
1038    #[serde(default, skip_serializing_if = "Option::is_none")]
1039    #[getset(get = "pub", set = "pub")]
1040    /// The syscalls for the restriction.
1041    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")]
1047/// Available seccomp actions.
1048pub enum LinuxSeccompAction {
1049    /// Kill the thread, defined for backward compatibility.
1050    ScmpActKill,
1051
1052    /// Kill the thread
1053    ScmpActKillThread,
1054
1055    /// Kill the process.
1056    ScmpActKillProcess,
1057
1058    /// Throw a SIGSYS signal.
1059    ScmpActTrap,
1060
1061    /// Return the specified error code.
1062    ScmpActErrno,
1063
1064    /// Notifies userspace.
1065    ScmpActNotify,
1066
1067    /// Notify a tracing process with the specified value.
1068    ScmpActTrace,
1069
1070    /// Allow the syscall to be executed after the action has been logged.
1071    ScmpActLog,
1072
1073    /// Allow the syscall to be executed.
1074    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")]
1103/// Available seccomp architectures.
1104pub enum Arch {
1105    /// The native architecture.
1106    ScmpArchNative = 0x00000000,
1107
1108    /// The x86 (32-bit) architecture.
1109    ScmpArchX86 = 0x40000003,
1110
1111    /// The x86-64 (64-bit) architecture.
1112    ScmpArchX86_64 = 0xc000003e,
1113
1114    /// The x32 (32-bit x86_64) architecture.
1115    ///
1116    /// This is different from the value used by the kernel because we need to
1117    /// be able to distinguish between x32 and x86_64.
1118    ScmpArchX32 = 0x4000003e,
1119
1120    /// The ARM architecture.
1121    ScmpArchArm = 0x40000028,
1122
1123    /// The AArch64 architecture.
1124    ScmpArchAarch64 = 0xc00000b7,
1125
1126    /// The MIPS architecture.
1127    ScmpArchMips = 0x00000008,
1128
1129    /// The MIPS64 architecture.
1130    ScmpArchMips64 = 0x80000008,
1131
1132    /// The MIPS64n32 architecture.
1133    ScmpArchMips64n32 = 0xa0000008,
1134
1135    /// The MIPSel architecture.
1136    ScmpArchMipsel = 0x40000008,
1137
1138    /// The MIPSel64 architecture.
1139    ScmpArchMipsel64 = 0xc0000008,
1140
1141    /// The MIPSel64n32 architecture.
1142    ScmpArchMipsel64n32 = 0xe0000008,
1143
1144    /// The PowerPC architecture.
1145    ScmpArchPpc = 0x00000014,
1146
1147    /// The PowerPC64 architecture.
1148    ScmpArchPpc64 = 0x80000015,
1149
1150    /// The PowerPC64le architecture.
1151    ScmpArchPpc64le = 0xc0000015,
1152
1153    /// The S390 architecture.
1154    ScmpArchS390 = 0x00000016,
1155
1156    /// The S390x architecture.
1157    ScmpArchS390x = 0x80000016,
1158
1159    /// The RISCV64 architecture.
1160    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")]
1166/// Available seccomp filter flags.
1167pub enum LinuxSeccompFilterFlag {
1168    /// All filter return actions except SECCOMP_RET_ALLOW should be logged. An administrator may
1169    /// override this filter flag by preventing specific actions from being logged via the
1170    /// /proc/sys/kernel/seccomp/actions_logged file. (since Linux 4.14)
1171    SeccompFilterFlagLog,
1172
1173    /// When adding a new filter, synchronize all other threads of the calling process to the same
1174    /// seccomp filter tree. A "filter tree" is the ordered list of filters attached to a thread.
1175    /// (Attaching identical filters in separate seccomp() calls results in different filters from this
1176    /// perspective.)
1177    ///
1178    /// If any thread cannot synchronize to the same filter tree, the call will not attach the new
1179    /// seccomp filter, and will fail, returning the first thread ID found that cannot synchronize.
1180    /// Synchronization will fail if another thread in the same process is in SECCOMP_MODE_STRICT or if
1181    /// it has attached new seccomp filters to itself, diverging from the calling thread's filter tree.
1182    SeccompFilterFlagTsync,
1183
1184    /// Disable Speculative Store Bypass mitigation. (since Linux 4.17)
1185    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)]
1192/// The seccomp operator to be used for args.
1193pub enum LinuxSeccompOperator {
1194    /// Refers to the SCMP_CMP_NE operator (not equal).
1195    ScmpCmpNe = 1,
1196
1197    /// Refers to the SCMP_CMP_LT operator (less than).
1198    ScmpCmpLt = 2,
1199
1200    /// Refers to the SCMP_CMP_LE operator (less equal).
1201    ScmpCmpLe = 3,
1202
1203    /// Refers to the SCMP_CMP_EQ operator (equal to).
1204    ScmpCmpEq = 4,
1205
1206    /// Refers to the SCMP_CMP_GE operator (greater equal).
1207    ScmpCmpGe = 5,
1208
1209    /// Refers to the SCMP_CMP_GT operator (greater than).
1210    ScmpCmpGt = 6,
1211
1212    /// Refers to the SCMP_CMP_MASKED_EQ operator (masked equal).
1213    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)]
1242/// LinuxSyscall is used to match a syscall in seccomp.
1243pub struct LinuxSyscall {
1244    #[getset(get = "pub", set = "pub")]
1245    /// The names of the syscalls.
1246    names: Vec<String>,
1247
1248    #[getset(get_copy = "pub", set = "pub")]
1249    /// The action to be done for the syscalls.
1250    action: LinuxSeccompAction,
1251
1252    #[serde(default, skip_serializing_if = "Option::is_none")]
1253    #[getset(get_copy = "pub", set = "pub")]
1254    /// The error return value.
1255    errno_ret: Option<u32>,
1256
1257    #[serde(default, skip_serializing_if = "Option::is_none")]
1258    #[getset(get = "pub", set = "pub")]
1259    /// The arguments for the syscalls.
1260    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")]
1274/// LinuxSeccompArg used for matching specific syscall arguments in seccomp.
1275pub struct LinuxSeccompArg {
1276    /// The index of the argument.
1277    index: usize,
1278
1279    /// The value of the argument.
1280    value: u64,
1281
1282    #[serde(default, skip_serializing_if = "Option::is_none")]
1283    /// The second value of the argument.
1284    value_two: Option<u64>,
1285
1286    /// The operator for the argument.
1287    op: LinuxSeccompOperator,
1288}
1289
1290/// Default masks paths, cannot read these host files.
1291pub fn get_default_maskedpaths() -> Vec<String> {
1292    vec![
1293        // For example now host interfaces such as
1294        // bluetooth cannot be accessed due to /proc/acpi
1295        "/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
1308/// Default readonly paths, for example most containers shouldn't have permission to write to
1309/// `/proc/sys`.
1310pub 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")]
1341/// LinuxIntelRdt has container runtime resource constraints for Intel RDT CAT and MBA
1342/// features and flags enabling Intel RDT CMT and MBM features.
1343/// Intel RDT features are available in Linux 4.14 and newer kernel versions.
1344pub struct LinuxIntelRdt {
1345    #[serde(default, skip_serializing_if = "Option::is_none", rename = "closID")]
1346    /// The identity for RDT Class of Service.
1347    clos_id: Option<String>,
1348
1349    #[serde(default, skip_serializing_if = "Option::is_none")]
1350    /// The schema for L3 cache id and capacity bitmask (CBM).
1351    /// Format: "L3:&lt;cache_id0&gt;=&lt;cbm0&gt;;&lt;cache_id1&gt;=&lt;cbm1&gt;;..."
1352    l3_cache_schema: Option<String>,
1353
1354    #[serde(default, skip_serializing_if = "Option::is_none")]
1355    /// The schema of memory bandwidth per L3 cache id.
1356    /// Format: "MB:&lt;cache_id0&gt;=bandwidth0;&lt;cache_id1&gt;=bandwidth1;..."
1357    /// The unit of memory bandwidth is specified in "percentages" by
1358    /// default, and in "MBps" if MBA Software Controller is
1359    /// enabled.
1360    mem_bw_schema: Option<String>,
1361
1362    #[serde(default, skip_serializing_if = "Option::is_none")]
1363    /// EnableCMT is the flag to indicate if the Intel RDT CMT is enabled. CMT (Cache Monitoring Technology) supports monitoring of
1364    /// the last-level cache (LLC) occupancy for the container.
1365    enable_cmt: Option<bool>,
1366
1367    #[serde(default, skip_serializing_if = "Option::is_none")]
1368    /// EnableMBM is the flag to indicate if the Intel RDT MBM is enabled. MBM (Memory Bandwidth Monitoring) supports monitoring of
1369    /// total and local memory bandwidth for the container.
1370    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)]
1392/// LinuxPersonality represents the Linux personality syscall input.
1393pub struct LinuxPersonality {
1394    #[getset(get_copy = "pub", set = "pub")]
1395    /// Domain for the personality.
1396    domain: LinuxPersonalityDomain,
1397
1398    #[serde(default, skip_serializing_if = "Option::is_none")]
1399    #[getset(get = "pub", set = "pub")]
1400    /// Additional flags
1401    flags: Option<Vec<String>>,
1402}
1403
1404#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize, StrumDisplay, EnumString)]
1405/// Define domain and flags for LinuxPersonality.
1406pub enum LinuxPersonalityDomain {
1407    #[serde(rename = "LINUX")]
1408    #[strum(serialize = "LINUX")]
1409    /// PerLinux is the standard Linux personality.
1410    PerLinux,
1411
1412    #[serde(rename = "LINUX32")]
1413    #[strum(serialize = "LINUX32")]
1414    /// PerLinux32 sets personality to 32 bit.
1415    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    // LinuxDeviceType test cases
1499    #[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    // LinuxNamespaceType test cases
1531    #[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    // LinuxSeccompAction test cases
1571    #[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    // LinuxSeccomp Arch test cases
1603    #[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    // LinuxSeccompFilterFlag test cases
1635    #[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    // LinuxSeccompOperator test cases
1676    #[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}