Skip to main content

libcontainer/
capabilities.rs

1//! Handles Management of Capabilities
2use caps::{Capability as CapsCapability, *};
3use oci_spec::runtime::{Capabilities, Capability as SpecCapability, LinuxCapabilities};
4
5use crate::syscall::{Syscall, SyscallError};
6
7/// Converts a list of capability types to capabilities has set
8fn to_set(caps: &Capabilities) -> CapsHashSet {
9    let mut capabilities = CapsHashSet::new();
10
11    for c in caps {
12        let cap = c.to_cap();
13        capabilities.insert(cap);
14    }
15    capabilities
16}
17
18pub trait CapabilityExt {
19    /// Convert self to caps::Capability
20    fn to_cap(&self) -> caps::Capability;
21    /// Convert caps::Capability to self
22    fn from_cap(c: CapsCapability) -> Self;
23}
24
25impl CapabilityExt for SpecCapability {
26    /// Convert oci::runtime::Capability to caps::Capability
27    fn to_cap(&self) -> caps::Capability {
28        match self {
29            SpecCapability::AuditControl => CapsCapability::CAP_AUDIT_CONTROL,
30            SpecCapability::AuditRead => CapsCapability::CAP_AUDIT_READ,
31            SpecCapability::AuditWrite => CapsCapability::CAP_AUDIT_WRITE,
32            SpecCapability::BlockSuspend => CapsCapability::CAP_BLOCK_SUSPEND,
33            SpecCapability::Bpf => CapsCapability::CAP_BPF,
34            SpecCapability::CheckpointRestore => CapsCapability::CAP_CHECKPOINT_RESTORE,
35            SpecCapability::Chown => CapsCapability::CAP_CHOWN,
36            SpecCapability::DacOverride => CapsCapability::CAP_DAC_OVERRIDE,
37            SpecCapability::DacReadSearch => CapsCapability::CAP_DAC_READ_SEARCH,
38            SpecCapability::Fowner => CapsCapability::CAP_FOWNER,
39            SpecCapability::Fsetid => CapsCapability::CAP_FSETID,
40            SpecCapability::IpcLock => CapsCapability::CAP_IPC_LOCK,
41            SpecCapability::IpcOwner => CapsCapability::CAP_IPC_OWNER,
42            SpecCapability::Kill => CapsCapability::CAP_KILL,
43            SpecCapability::Lease => CapsCapability::CAP_LEASE,
44            SpecCapability::LinuxImmutable => CapsCapability::CAP_LINUX_IMMUTABLE,
45            SpecCapability::MacAdmin => CapsCapability::CAP_MAC_ADMIN,
46            SpecCapability::MacOverride => CapsCapability::CAP_MAC_OVERRIDE,
47            SpecCapability::Mknod => CapsCapability::CAP_MKNOD,
48            SpecCapability::NetAdmin => CapsCapability::CAP_NET_ADMIN,
49            SpecCapability::NetBindService => CapsCapability::CAP_NET_BIND_SERVICE,
50            SpecCapability::NetBroadcast => CapsCapability::CAP_NET_BROADCAST,
51            SpecCapability::NetRaw => CapsCapability::CAP_NET_RAW,
52            SpecCapability::Perfmon => CapsCapability::CAP_PERFMON,
53            SpecCapability::Setgid => CapsCapability::CAP_SETGID,
54            SpecCapability::Setfcap => CapsCapability::CAP_SETFCAP,
55            SpecCapability::Setpcap => CapsCapability::CAP_SETPCAP,
56            SpecCapability::Setuid => CapsCapability::CAP_SETUID,
57            SpecCapability::SysAdmin => CapsCapability::CAP_SYS_ADMIN,
58            SpecCapability::SysBoot => CapsCapability::CAP_SYS_BOOT,
59            SpecCapability::SysChroot => CapsCapability::CAP_SYS_CHROOT,
60            SpecCapability::SysModule => CapsCapability::CAP_SYS_MODULE,
61            SpecCapability::SysNice => CapsCapability::CAP_SYS_NICE,
62            SpecCapability::SysPacct => CapsCapability::CAP_SYS_PACCT,
63            SpecCapability::SysPtrace => CapsCapability::CAP_SYS_PTRACE,
64            SpecCapability::SysRawio => CapsCapability::CAP_SYS_RAWIO,
65            SpecCapability::SysResource => CapsCapability::CAP_SYS_RESOURCE,
66            SpecCapability::SysTime => CapsCapability::CAP_SYS_TIME,
67            SpecCapability::SysTtyConfig => CapsCapability::CAP_SYS_TTY_CONFIG,
68            SpecCapability::Syslog => CapsCapability::CAP_SYSLOG,
69            SpecCapability::WakeAlarm => CapsCapability::CAP_WAKE_ALARM,
70        }
71    }
72
73    /// Convert caps::Capability to oci::runtime::Capability
74    fn from_cap(c: CapsCapability) -> SpecCapability {
75        match c {
76            CapsCapability::CAP_AUDIT_CONTROL => SpecCapability::AuditControl,
77            CapsCapability::CAP_AUDIT_READ => SpecCapability::AuditRead,
78            CapsCapability::CAP_AUDIT_WRITE => SpecCapability::AuditWrite,
79            CapsCapability::CAP_BLOCK_SUSPEND => SpecCapability::BlockSuspend,
80            CapsCapability::CAP_BPF => SpecCapability::Bpf,
81            CapsCapability::CAP_CHECKPOINT_RESTORE => SpecCapability::CheckpointRestore,
82            CapsCapability::CAP_CHOWN => SpecCapability::Chown,
83            CapsCapability::CAP_DAC_OVERRIDE => SpecCapability::DacOverride,
84            CapsCapability::CAP_DAC_READ_SEARCH => SpecCapability::DacReadSearch,
85            CapsCapability::CAP_FOWNER => SpecCapability::Fowner,
86            CapsCapability::CAP_FSETID => SpecCapability::Fsetid,
87            CapsCapability::CAP_IPC_LOCK => SpecCapability::IpcLock,
88            CapsCapability::CAP_IPC_OWNER => SpecCapability::IpcOwner,
89            CapsCapability::CAP_KILL => SpecCapability::Kill,
90            CapsCapability::CAP_LEASE => SpecCapability::Lease,
91            CapsCapability::CAP_LINUX_IMMUTABLE => SpecCapability::LinuxImmutable,
92            CapsCapability::CAP_MAC_ADMIN => SpecCapability::MacAdmin,
93            CapsCapability::CAP_MAC_OVERRIDE => SpecCapability::MacOverride,
94            CapsCapability::CAP_MKNOD => SpecCapability::Mknod,
95            CapsCapability::CAP_NET_ADMIN => SpecCapability::NetAdmin,
96            CapsCapability::CAP_NET_BIND_SERVICE => SpecCapability::NetBindService,
97            CapsCapability::CAP_NET_BROADCAST => SpecCapability::NetBroadcast,
98            CapsCapability::CAP_NET_RAW => SpecCapability::NetRaw,
99            CapsCapability::CAP_PERFMON => SpecCapability::Perfmon,
100            CapsCapability::CAP_SETGID => SpecCapability::Setgid,
101            CapsCapability::CAP_SETFCAP => SpecCapability::Setfcap,
102            CapsCapability::CAP_SETPCAP => SpecCapability::Setpcap,
103            CapsCapability::CAP_SETUID => SpecCapability::Setuid,
104            CapsCapability::CAP_SYS_ADMIN => SpecCapability::SysAdmin,
105            CapsCapability::CAP_SYS_BOOT => SpecCapability::SysBoot,
106            CapsCapability::CAP_SYS_CHROOT => SpecCapability::SysChroot,
107            CapsCapability::CAP_SYS_MODULE => SpecCapability::SysModule,
108            CapsCapability::CAP_SYS_NICE => SpecCapability::SysNice,
109            CapsCapability::CAP_SYS_PACCT => SpecCapability::SysPacct,
110            CapsCapability::CAP_SYS_PTRACE => SpecCapability::SysPtrace,
111            CapsCapability::CAP_SYS_RAWIO => SpecCapability::SysRawio,
112            CapsCapability::CAP_SYS_RESOURCE => SpecCapability::SysResource,
113            CapsCapability::CAP_SYS_TIME => SpecCapability::SysTime,
114            CapsCapability::CAP_SYS_TTY_CONFIG => SpecCapability::SysTtyConfig,
115            CapsCapability::CAP_SYSLOG => SpecCapability::Syslog,
116            CapsCapability::CAP_WAKE_ALARM => SpecCapability::WakeAlarm,
117            CapsCapability::__Nonexhaustive => unreachable!("invalid capability"),
118        }
119    }
120}
121
122/// reset capabilities of process calling this to effective capabilities
123/// effective capability set is set of capabilities used by kernel to perform checks
124/// see <https://man7.org/linux/man-pages/man7/capabilities.7.html> for more information
125pub fn reset_effective<S: Syscall + ?Sized>(syscall: &S) -> Result<(), SyscallError> {
126    tracing::debug!("reset all caps");
127    // permitted capabilities are all the capabilities that we are allowed to acquire
128    let permitted = caps::read(None, CapSet::Permitted)?;
129    syscall.set_capability(CapSet::Effective, &permitted)?;
130    Ok(())
131}
132
133/// Drop any extra granted capabilities, and reset to defaults which are in oci specification
134pub fn drop_privileges<S: Syscall + ?Sized>(
135    cs: &LinuxCapabilities,
136    syscall: &S,
137) -> Result<(), SyscallError> {
138    if let Some(bounding) = cs.bounding() {
139        tracing::debug!("dropping bounding capabilities to {:?}", bounding);
140        syscall.set_capability(CapSet::Bounding, &to_set(bounding))?;
141    }
142
143    if let Some(effective) = cs.effective() {
144        tracing::debug!("dropping effective capabilities to {:?}", effective);
145        syscall.set_capability(CapSet::Effective, &to_set(effective))?;
146    }
147
148    if let Some(permitted) = cs.permitted() {
149        tracing::debug!("dropping permitted capabilities to {:?}", permitted);
150        syscall.set_capability(CapSet::Permitted, &to_set(permitted))?;
151    }
152
153    if let Some(inheritable) = cs.inheritable() {
154        tracing::debug!("dropping inheritable capabilities to {:?}", inheritable);
155        syscall.set_capability(CapSet::Inheritable, &to_set(inheritable))?;
156    }
157
158    if let Some(ambient) = cs.ambient() {
159        tracing::debug!("dropping ambient capabilities to {:?}", ambient);
160        syscall.set_capability(CapSet::Ambient, &to_set(ambient))?;
161    }
162
163    Ok(())
164}
165
166#[cfg(test)]
167mod tests {
168    use std::collections::HashSet;
169
170    use oci_spec::runtime::LinuxCapabilitiesBuilder;
171
172    use super::*;
173    use crate::syscall::test::TestHelperSyscall;
174
175    #[test]
176    fn test_reset_effective() {
177        let test_command = TestHelperSyscall::default();
178        let permitted_caps = caps::read(None, CapSet::Permitted).unwrap();
179        assert!(reset_effective(&test_command).is_ok());
180        let set_capability_args: Vec<_> = test_command
181            .get_set_capability_args()
182            .into_iter()
183            .map(|(_capset, caps)| caps)
184            .collect();
185        assert_eq!(set_capability_args, vec![permitted_caps]);
186    }
187
188    #[test]
189    fn test_convert_oci_spec_to_caps_type() {
190        struct Testcase {
191            input: SpecCapability,
192            want: CapsCapability,
193        }
194
195        let tests = vec![
196            Testcase {
197                input: SpecCapability::AuditControl,
198                want: CapsCapability::CAP_AUDIT_CONTROL,
199            },
200            Testcase {
201                input: SpecCapability::AuditRead,
202                want: CapsCapability::CAP_AUDIT_READ,
203            },
204            Testcase {
205                input: SpecCapability::AuditWrite,
206                want: CapsCapability::CAP_AUDIT_WRITE,
207            },
208            Testcase {
209                input: SpecCapability::BlockSuspend,
210                want: CapsCapability::CAP_BLOCK_SUSPEND,
211            },
212            Testcase {
213                input: SpecCapability::Bpf,
214                want: CapsCapability::CAP_BPF,
215            },
216            Testcase {
217                input: SpecCapability::CheckpointRestore,
218                want: CapsCapability::CAP_CHECKPOINT_RESTORE,
219            },
220            Testcase {
221                input: SpecCapability::Chown,
222                want: Capability::CAP_CHOWN,
223            },
224            Testcase {
225                input: SpecCapability::DacOverride,
226                want: CapsCapability::CAP_DAC_OVERRIDE,
227            },
228            Testcase {
229                input: SpecCapability::DacReadSearch,
230                want: CapsCapability::CAP_DAC_READ_SEARCH,
231            },
232            Testcase {
233                input: SpecCapability::Fowner,
234                want: CapsCapability::CAP_FOWNER,
235            },
236            Testcase {
237                input: SpecCapability::Fsetid,
238                want: CapsCapability::CAP_FSETID,
239            },
240            Testcase {
241                input: SpecCapability::IpcLock,
242                want: CapsCapability::CAP_IPC_LOCK,
243            },
244            Testcase {
245                input: SpecCapability::IpcOwner,
246                want: CapsCapability::CAP_IPC_OWNER,
247            },
248            Testcase {
249                input: SpecCapability::Kill,
250                want: CapsCapability::CAP_KILL,
251            },
252            Testcase {
253                input: SpecCapability::Lease,
254                want: CapsCapability::CAP_LEASE,
255            },
256            Testcase {
257                input: SpecCapability::LinuxImmutable,
258                want: CapsCapability::CAP_LINUX_IMMUTABLE,
259            },
260            Testcase {
261                input: SpecCapability::MacAdmin,
262                want: CapsCapability::CAP_MAC_ADMIN,
263            },
264            Testcase {
265                input: SpecCapability::MacOverride,
266                want: CapsCapability::CAP_MAC_OVERRIDE,
267            },
268            Testcase {
269                input: SpecCapability::Mknod,
270                want: CapsCapability::CAP_MKNOD,
271            },
272            Testcase {
273                input: SpecCapability::NetAdmin,
274                want: CapsCapability::CAP_NET_ADMIN,
275            },
276            Testcase {
277                input: SpecCapability::NetBindService,
278                want: CapsCapability::CAP_NET_BIND_SERVICE,
279            },
280            Testcase {
281                input: SpecCapability::NetBroadcast,
282                want: CapsCapability::CAP_NET_BROADCAST,
283            },
284            Testcase {
285                input: SpecCapability::NetRaw,
286                want: CapsCapability::CAP_NET_RAW,
287            },
288            Testcase {
289                input: SpecCapability::Perfmon,
290                want: CapsCapability::CAP_PERFMON,
291            },
292            Testcase {
293                input: SpecCapability::Setgid,
294                want: CapsCapability::CAP_SETGID,
295            },
296            Testcase {
297                input: SpecCapability::Setfcap,
298                want: CapsCapability::CAP_SETFCAP,
299            },
300            Testcase {
301                input: SpecCapability::Setpcap,
302                want: CapsCapability::CAP_SETPCAP,
303            },
304            Testcase {
305                input: SpecCapability::Setuid,
306                want: CapsCapability::CAP_SETUID,
307            },
308            Testcase {
309                input: SpecCapability::SysAdmin,
310                want: CapsCapability::CAP_SYS_ADMIN,
311            },
312            Testcase {
313                input: SpecCapability::SysBoot,
314                want: CapsCapability::CAP_SYS_BOOT,
315            },
316            Testcase {
317                input: SpecCapability::SysChroot,
318                want: CapsCapability::CAP_SYS_CHROOT,
319            },
320            Testcase {
321                input: SpecCapability::SysModule,
322                want: CapsCapability::CAP_SYS_MODULE,
323            },
324            Testcase {
325                input: SpecCapability::SysNice,
326                want: CapsCapability::CAP_SYS_NICE,
327            },
328            Testcase {
329                input: SpecCapability::SysPacct,
330                want: CapsCapability::CAP_SYS_PACCT,
331            },
332            Testcase {
333                input: SpecCapability::SysPtrace,
334                want: CapsCapability::CAP_SYS_PTRACE,
335            },
336            Testcase {
337                input: SpecCapability::SysRawio,
338                want: CapsCapability::CAP_SYS_RAWIO,
339            },
340            Testcase {
341                input: SpecCapability::SysResource,
342                want: CapsCapability::CAP_SYS_RESOURCE,
343            },
344            Testcase {
345                input: SpecCapability::SysTime,
346                want: CapsCapability::CAP_SYS_TIME,
347            },
348            Testcase {
349                input: SpecCapability::SysTtyConfig,
350                want: CapsCapability::CAP_SYS_TTY_CONFIG,
351            },
352            Testcase {
353                input: SpecCapability::Syslog,
354                want: CapsCapability::CAP_SYSLOG,
355            },
356            Testcase {
357                input: SpecCapability::WakeAlarm,
358                want: CapsCapability::CAP_WAKE_ALARM,
359            },
360        ];
361
362        for test in tests {
363            let got = test.input.to_cap();
364            assert_eq!(got, test.want);
365        }
366    }
367
368    #[test]
369    fn test_convert_caps_type_to_oci_spec() {
370        struct Testcase {
371            input: CapsCapability,
372            want: SpecCapability,
373        }
374
375        let tests = vec![
376            Testcase {
377                input: CapsCapability::CAP_AUDIT_CONTROL,
378                want: SpecCapability::AuditControl,
379            },
380            Testcase {
381                input: CapsCapability::CAP_AUDIT_READ,
382                want: SpecCapability::AuditRead,
383            },
384            Testcase {
385                input: CapsCapability::CAP_AUDIT_WRITE,
386                want: SpecCapability::AuditWrite,
387            },
388            Testcase {
389                input: CapsCapability::CAP_BLOCK_SUSPEND,
390                want: SpecCapability::BlockSuspend,
391            },
392            Testcase {
393                input: CapsCapability::CAP_BPF,
394                want: SpecCapability::Bpf,
395            },
396            Testcase {
397                input: CapsCapability::CAP_CHECKPOINT_RESTORE,
398                want: SpecCapability::CheckpointRestore,
399            },
400            Testcase {
401                input: CapsCapability::CAP_CHOWN,
402                want: SpecCapability::Chown,
403            },
404            Testcase {
405                input: CapsCapability::CAP_DAC_OVERRIDE,
406                want: SpecCapability::DacOverride,
407            },
408            Testcase {
409                input: CapsCapability::CAP_DAC_READ_SEARCH,
410                want: SpecCapability::DacReadSearch,
411            },
412            Testcase {
413                input: CapsCapability::CAP_FOWNER,
414                want: SpecCapability::Fowner,
415            },
416            Testcase {
417                input: CapsCapability::CAP_FSETID,
418                want: SpecCapability::Fsetid,
419            },
420            Testcase {
421                input: CapsCapability::CAP_IPC_LOCK,
422                want: SpecCapability::IpcLock,
423            },
424            Testcase {
425                input: CapsCapability::CAP_IPC_OWNER,
426                want: SpecCapability::IpcOwner,
427            },
428            Testcase {
429                input: CapsCapability::CAP_KILL,
430                want: SpecCapability::Kill,
431            },
432            Testcase {
433                input: CapsCapability::CAP_LEASE,
434                want: SpecCapability::Lease,
435            },
436            Testcase {
437                input: CapsCapability::CAP_LINUX_IMMUTABLE,
438                want: SpecCapability::LinuxImmutable,
439            },
440            Testcase {
441                input: CapsCapability::CAP_MAC_ADMIN,
442                want: SpecCapability::MacAdmin,
443            },
444            Testcase {
445                input: CapsCapability::CAP_MAC_OVERRIDE,
446                want: SpecCapability::MacOverride,
447            },
448            Testcase {
449                input: CapsCapability::CAP_MKNOD,
450                want: SpecCapability::Mknod,
451            },
452            Testcase {
453                input: CapsCapability::CAP_NET_ADMIN,
454                want: SpecCapability::NetAdmin,
455            },
456            Testcase {
457                input: CapsCapability::CAP_NET_BIND_SERVICE,
458                want: SpecCapability::NetBindService,
459            },
460            Testcase {
461                input: CapsCapability::CAP_NET_BROADCAST,
462                want: SpecCapability::NetBroadcast,
463            },
464            Testcase {
465                input: CapsCapability::CAP_NET_RAW,
466                want: SpecCapability::NetRaw,
467            },
468            Testcase {
469                input: CapsCapability::CAP_PERFMON,
470                want: SpecCapability::Perfmon,
471            },
472            Testcase {
473                input: CapsCapability::CAP_SETGID,
474                want: SpecCapability::Setgid,
475            },
476            Testcase {
477                input: CapsCapability::CAP_SETFCAP,
478                want: SpecCapability::Setfcap,
479            },
480            Testcase {
481                input: CapsCapability::CAP_SETPCAP,
482                want: SpecCapability::Setpcap,
483            },
484            Testcase {
485                input: CapsCapability::CAP_SETUID,
486                want: SpecCapability::Setuid,
487            },
488            Testcase {
489                input: CapsCapability::CAP_SYS_ADMIN,
490                want: SpecCapability::SysAdmin,
491            },
492            Testcase {
493                input: CapsCapability::CAP_SYS_BOOT,
494                want: SpecCapability::SysBoot,
495            },
496            Testcase {
497                input: CapsCapability::CAP_SYS_CHROOT,
498                want: SpecCapability::SysChroot,
499            },
500            Testcase {
501                input: CapsCapability::CAP_SYS_MODULE,
502                want: SpecCapability::SysModule,
503            },
504            Testcase {
505                input: CapsCapability::CAP_SYS_NICE,
506                want: SpecCapability::SysNice,
507            },
508            Testcase {
509                input: CapsCapability::CAP_SYS_PACCT,
510                want: SpecCapability::SysPacct,
511            },
512            Testcase {
513                input: CapsCapability::CAP_SYS_PTRACE,
514                want: SpecCapability::SysPtrace,
515            },
516            Testcase {
517                input: CapsCapability::CAP_SYS_RAWIO,
518                want: SpecCapability::SysRawio,
519            },
520            Testcase {
521                input: CapsCapability::CAP_SYS_RESOURCE,
522                want: SpecCapability::SysResource,
523            },
524            Testcase {
525                input: CapsCapability::CAP_SYS_TIME,
526                want: SpecCapability::SysTime,
527            },
528            Testcase {
529                input: CapsCapability::CAP_SYS_TTY_CONFIG,
530                want: SpecCapability::SysTtyConfig,
531            },
532            Testcase {
533                input: CapsCapability::CAP_SYSLOG,
534                want: SpecCapability::Syslog,
535            },
536            Testcase {
537                input: CapsCapability::CAP_WAKE_ALARM,
538                want: SpecCapability::WakeAlarm,
539            },
540        ];
541
542        for test in tests {
543            let got = SpecCapability::from_cap(test.input);
544            assert_eq!(got, test.want);
545        }
546    }
547
548    #[test]
549    fn test_drop_privileges() {
550        struct Testcase {
551            name: String,
552            input: LinuxCapabilities,
553            // be aware that the calling sequence in the drop_privileges function
554            // will affect the output sequence from test_command.get_set_capability_args()
555            want: Vec<(CapSet, Vec<SpecCapability>)>,
556        }
557
558        let cps = vec![
559            SpecCapability::AuditWrite,
560            SpecCapability::Kill,
561            SpecCapability::NetBindService,
562        ];
563
564        let tests = vec![
565            Testcase {
566                name: format!("all LinuxCapabilities fields with caps: {cps:?}"),
567                input: LinuxCapabilitiesBuilder::default()
568                    .bounding(cps.clone().into_iter().collect::<Capabilities>())
569                    .effective(cps.clone().into_iter().collect::<Capabilities>())
570                    .inheritable(cps.clone().into_iter().collect::<Capabilities>())
571                    .permitted(cps.clone().into_iter().collect::<Capabilities>())
572                    .ambient(cps.clone().into_iter().collect::<Capabilities>())
573                    .build()
574                    .unwrap(),
575                want: vec![
576                    (CapSet::Bounding, cps.clone()),
577                    (CapSet::Effective, cps.clone()),
578                    (CapSet::Permitted, cps.clone()),
579                    (CapSet::Inheritable, cps.clone()),
580                    (CapSet::Ambient, cps.clone()),
581                ],
582            },
583            Testcase {
584                name: format!("partial LinuxCapabilities fields with caps: {cps:?}"),
585                input: LinuxCapabilitiesBuilder::default()
586                    .bounding(cps.clone().into_iter().collect::<Capabilities>())
587                    .effective(cps.clone().into_iter().collect::<Capabilities>())
588                    .permitted(cps.clone().into_iter().collect::<Capabilities>())
589                    .build()
590                    .unwrap(),
591                want: vec![
592                    (CapSet::Bounding, cps.clone()),
593                    (CapSet::Effective, cps.clone()),
594                    (CapSet::Permitted, cps.clone()),
595                    (CapSet::Inheritable, cps.clone()),
596                    (CapSet::Ambient, cps.clone()),
597                ],
598            },
599            Testcase {
600                name: format!("empty LinuxCapabilities fields with caps: {cps:?}"),
601                input: LinuxCapabilitiesBuilder::default()
602                    .bounding(HashSet::new())
603                    .effective(HashSet::new())
604                    .inheritable(HashSet::new())
605                    .permitted(HashSet::new())
606                    .ambient(HashSet::new())
607                    .build()
608                    .unwrap(),
609                want: vec![
610                    (CapSet::Bounding, cps.clone()),
611                    (CapSet::Effective, cps.clone()),
612                    (CapSet::Permitted, cps.clone()),
613                    (CapSet::Inheritable, cps.clone()),
614                    (CapSet::Ambient, cps),
615                ],
616            },
617        ];
618
619        for test in tests {
620            let test_command = TestHelperSyscall::default();
621            assert!(
622                drop_privileges(&test.input, &test_command).is_ok(),
623                "{}, drop_privileges is not ok",
624                test.name
625            );
626
627            let got: Vec<(CapSet, Vec<_>)> = test_command
628                .get_set_capability_args()
629                .into_iter()
630                .map(|(capset, caps)| {
631                    (
632                        capset,
633                        caps.into_iter().map(SpecCapability::from_cap).collect(),
634                    )
635                })
636                .collect();
637            assert_eq!(
638                got.len(),
639                test.want.len(),
640                "{}, len of got:{}, want:{}",
641                test.name,
642                got.len(),
643                test.want.len(),
644            );
645
646            for (i, want) in test.want.iter().enumerate().take(test.want.len()) {
647                // because CapSet has no Eq, PartialEq attributes,
648                // so using String to do the comparison.
649                let want_cap_set = format!("{:?}", want.0);
650                let got_cap_set = format!("{:?}", got[i].0);
651                let want_caps = &want.1;
652                let got_caps = &got[i].1;
653
654                assert_eq!(
655                    got_cap_set, want_cap_set,
656                    "{}, capset of got:{}, want:{}",
657                    test.name, got_cap_set, want_cap_set,
658                );
659                // because get_set_capability_args returns a HasSet of capabilities,
660                // so the ordering is randomized.
661                assert!(
662                    got_caps.iter().all(|cap| want_caps.contains(cap)),
663                    "{}, caps of got:{:?}, want:{:?}",
664                    test.name,
665                    got_caps,
666                    want_caps
667                );
668            }
669        }
670    }
671}