Skip to main content

selinux/
lib.rs

1// Copyright 2024 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5pub mod permission_check;
6pub mod policy;
7pub mod security_server;
8
9pub use security_server::SecurityServer;
10
11mod access_cache;
12mod access_vector_cache;
13mod exceptions_config;
14mod sid_table;
15mod sync;
16
17use policy::arrays::FsUseType;
18
19/// Numeric class Ids are provided to the userspace AVC surfaces (e.g. "create", "access", etc).
20pub use policy::ClassId;
21
22pub use starnix_uapi::selinux::{InitialSid, ReferenceInitialSid, SecurityId, TaskAttrs};
23
24/// Identifies a specific class by its policy-defined Id, or as a kernel object class enum Id.
25#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
26pub enum ObjectClass {
27    /// Refers to a well-known SELinux kernel object class (e.g. "process", "file", "capability").
28    Kernel(KernelClass),
29    /// Refers to a policy-defined class by its policy-defined numeric Id. This is most commonly
30    /// used when handling queries from userspace, which refer to classes by-Id.
31    ClassId(ClassId),
32}
33
34impl From<ClassId> for ObjectClass {
35    fn from(id: ClassId) -> Self {
36        Self::ClassId(id)
37    }
38}
39
40impl<T: Into<KernelClass>> From<T> for ObjectClass {
41    fn from(class: T) -> Self {
42        Self::Kernel(class.into())
43    }
44}
45
46/// Declares an `enum` and implements an `all_variants()` API for it.
47macro_rules! enumerable_enum {
48    ($(#[$meta:meta])* $name:ident $(extends $common_name:ident)? {
49        $($(#[$variant_meta:meta])* $variant:ident,)*
50    }) => {
51        $(#[$meta])*
52        pub enum $name {
53            $($(#[$variant_meta])* $variant,)*
54            $(Common($common_name),)?
55        }
56
57        impl $name {
58            pub fn all_variants() -> impl Iterator<Item=Self> {
59                let iter = [$($name::$variant),*].iter().map(Clone::clone);
60                $(let iter = iter.chain($common_name::all_variants().map($name::Common));)?
61                iter
62            }
63        }
64    }
65}
66
67enumerable_enum! {
68    /// A well-known class in SELinux policy that has a particular meaning in policy enforcement
69    /// hooks.
70    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
71    KernelClass {
72        // keep-sorted start
73        /// The SELinux "anon_inode" object class.
74        AnonFsNode,
75        /// The SELinux "binder" object class.
76        Binder,
77        /// The SELinux "blk_file" object class.
78        Block,
79        /// The SELinux "bpf" object class.
80        Bpf,
81        /// The SELinux "capability" object class.
82        Capability,
83        /// The SELinux "capability2" object class.
84        Capability2,
85        /// The SELinux "chr_file" object class.
86        Character,
87        /// The SELinux "dir" object class.
88        Dir,
89        /// The SELinux "fd" object class.
90        Fd,
91        /// The SELinux "fifo_file" object class.
92        Fifo,
93        /// The SELinux "file" object class.
94        File,
95        /// The SELinux "filesystem" object class.
96        FileSystem,
97        /// "icmp_socket" class enabled via the "extended_socket_class" policy capability.
98        IcmpSocket,
99        /// The SELinux "key_socket" object class.
100        KeySocket,
101        /// The SELinux "lnk_file" object class.
102        Link,
103        /// The SELinux "memfd_file" object class.
104        MemFdFile,
105        /// The SELinux "netlink_audit_socket" object class.
106        NetlinkAuditSocket,
107        /// The SELinux "netlink_connector_socket" object class.
108        NetlinkConnectorSocket,
109        /// The SELinux "netlink_crypto_socket" object class.
110        NetlinkCryptoSocket,
111        /// The SELinux "netlink_dnrt_socket" object class.
112        NetlinkDnrtSocket,
113        /// The SELinux "netlink_fib_lookup_socket" object class.
114        NetlinkFibLookupSocket,
115        /// The SELinux "netlink_firewall_socket" object class.
116        NetlinkFirewallSocket,
117        /// The SELinux "netlink_generic_socket" object class.
118        NetlinkGenericSocket,
119        /// The SELinux "netlink_ip6fw_socket" object class.
120        NetlinkIp6FwSocket,
121        /// The SELinux "netlink_iscsi_socket" object class.
122        NetlinkIscsiSocket,
123        /// The SELinux "netlink_kobject_uevent_socket" object class.
124        NetlinkKobjectUeventSocket,
125        /// The SELinux "netlink_netfilter_socket" object class.
126        NetlinkNetfilterSocket,
127        /// The SELinux "netlink_nflog_socket" object class.
128        NetlinkNflogSocket,
129        /// The SELinux "netlink_rdma_socket" object class.
130        NetlinkRdmaSocket,
131        /// The SELinux "netlink_route_socket" object class.
132        NetlinkRouteSocket,
133        /// The SELinux "netlink_scsitransport_socket" object class.
134        NetlinkScsitransportSocket,
135        /// The SELinux "netlink_selinux_socket" object class.
136        NetlinkSelinuxSocket,
137        /// The SELinux "netlink_socket" object class.
138        NetlinkSocket,
139        /// The SELinux "netlink_tcpdiag_socket" object class.
140        NetlinkTcpDiagSocket,
141        /// The SELinux "netlink_xfrm_socket" object class.
142        NetlinkXfrmSocket,
143        /// The SELinux "packet_socket" object class.
144        PacketSocket,
145        /// The SELinux "perf_event" object class.
146        PerfEvent,
147        /// The SELinux "process" object class.
148        Process,
149        /// The SELinux "process2" object class.
150        Process2,
151        /// The SELinux "qipcrtr_socket" object class.
152        QipcrtrSocket,
153        /// The SELinux "rawip_socket" object class.
154        RawIpSocket,
155        /// "sctp_socket" class enabled via the "extended_socket_class" policy capability.
156        SctpSocket,
157        /// The SELinux "security" object class.
158        Security,
159        /// The SELinux "sock_file" object class.
160        SockFile,
161        /// The SELinux "socket" object class.
162        Socket,
163        /// The SELinux "system" object class.
164        System,
165        /// The SELinux "tcp_socket" object class.
166        TcpSocket,
167        /// The SELinux "tun_socket" object class.
168        TunSocket,
169        /// The SELinux "udp_socket" object class.
170        UdpSocket,
171        /// The SELinux "unix_dgram_socket" object class.
172        UnixDgramSocket,
173        /// The SELinux "unix_stream_socket" object class.
174        UnixStreamSocket,
175        /// "vsock_socket" class enabled via the "extended_socket_class" policy capability.
176        VSockSocket,
177        // keep-sorted end
178    }
179}
180
181impl KernelClass {
182    /// Returns the name used to refer to this object class in the SELinux binary policy.
183    pub fn name(&self) -> &'static str {
184        match self {
185            // keep-sorted start
186            Self::AnonFsNode => "anon_inode",
187            Self::Binder => "binder",
188            Self::Block => "blk_file",
189            Self::Bpf => "bpf",
190            Self::Capability => "capability",
191            Self::Capability2 => "capability2",
192            Self::Character => "chr_file",
193            Self::Dir => "dir",
194            Self::Fd => "fd",
195            Self::Fifo => "fifo_file",
196            Self::File => "file",
197            Self::FileSystem => "filesystem",
198            Self::IcmpSocket => "icmp_socket",
199            Self::KeySocket => "key_socket",
200            Self::Link => "lnk_file",
201            Self::MemFdFile => "memfd_file",
202            Self::NetlinkAuditSocket => "netlink_audit_socket",
203            Self::NetlinkConnectorSocket => "netlink_connector_socket",
204            Self::NetlinkCryptoSocket => "netlink_crypto_socket",
205            Self::NetlinkDnrtSocket => "netlink_dnrt_socket",
206            Self::NetlinkFibLookupSocket => "netlink_fib_lookup_socket",
207            Self::NetlinkFirewallSocket => "netlink_firewall_socket",
208            Self::NetlinkGenericSocket => "netlink_generic_socket",
209            Self::NetlinkIp6FwSocket => "netlink_ip6fw_socket",
210            Self::NetlinkIscsiSocket => "netlink_iscsi_socket",
211            Self::NetlinkKobjectUeventSocket => "netlink_kobject_uevent_socket",
212            Self::NetlinkNetfilterSocket => "netlink_netfilter_socket",
213            Self::NetlinkNflogSocket => "netlink_nflog_socket",
214            Self::NetlinkRdmaSocket => "netlink_rdma_socket",
215            Self::NetlinkRouteSocket => "netlink_route_socket",
216            Self::NetlinkScsitransportSocket => "netlink_scsitransport_socket",
217            Self::NetlinkSelinuxSocket => "netlink_selinux_socket",
218            Self::NetlinkSocket => "netlink_socket",
219            Self::NetlinkTcpDiagSocket => "netlink_tcpdiag_socket",
220            Self::NetlinkXfrmSocket => "netlink_xfrm_socket",
221            Self::PacketSocket => "packet_socket",
222            Self::PerfEvent => "perf_event",
223            Self::Process => "process",
224            Self::Process2 => "process2",
225            Self::QipcrtrSocket => "qipcrtr_socket",
226            Self::RawIpSocket => "rawip_socket",
227            Self::SctpSocket => "sctp_socket",
228            Self::Security => "security",
229            Self::SockFile => "sock_file",
230            Self::Socket => "socket",
231            Self::System => "system",
232            Self::TcpSocket => "tcp_socket",
233            Self::TunSocket => "tun_socket",
234            Self::UdpSocket => "udp_socket",
235            Self::UnixDgramSocket => "unix_dgram_socket",
236            Self::UnixStreamSocket => "unix_stream_socket",
237            Self::VSockSocket => "vsock_socket",
238            // keep-sorted end
239        }
240    }
241}
242
243impl<T: Into<KernelClass>> ForClass<T> for KernelPermission {
244    fn for_class(&self, class: T) -> KernelPermission {
245        assert_eq!(self.class(), class.into());
246        self.clone()
247    }
248}
249
250pub trait ForClass<T> {
251    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
252    /// This is used to allow hooks to resolve e.g. common "sys_nice" permission access based on the
253    /// "allow" rules for the correct target object class.
254    fn for_class(&self, class: T) -> KernelPermission;
255}
256
257enumerable_enum! {
258    /// Covers the set of classes that inherit from the common "cap" symbol (e.g. "capability" for
259    /// now and "cap_userns" after Starnix gains user namespacing support).
260    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
261    CapClass {
262        // keep-sorted start
263        /// The SELinux "capability" object class.
264        Capability,
265        // keep-sorted end
266    }
267}
268
269impl From<CapClass> for KernelClass {
270    fn from(cap_class: CapClass) -> Self {
271        match cap_class {
272            // keep-sorted start
273            CapClass::Capability => Self::Capability,
274            // keep-sorted end
275        }
276    }
277}
278
279enumerable_enum! {
280    /// Covers the set of classes that inherit from the common "cap2" symbol (e.g. "capability2" for
281    /// now and "cap2_userns" after Starnix gains user namespacing support).
282    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
283    Cap2Class {
284        // keep-sorted start
285        /// The SELinux "capability2" object class.
286        Capability2,
287        // keep-sorted end
288    }
289}
290
291impl From<Cap2Class> for KernelClass {
292    fn from(cap2_class: Cap2Class) -> Self {
293        match cap2_class {
294            // keep-sorted start
295            Cap2Class::Capability2 => Self::Capability2,
296            // keep-sorted end
297        }
298    }
299}
300
301enumerable_enum! {
302    /// A well-known file-like class in SELinux policy that has a particular meaning in policy
303    /// enforcement hooks.
304    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
305    FileClass {
306        // keep-sorted start
307        /// The SELinux "anon_inode" object class.
308        AnonFsNode,
309        /// The SELinux "blk_file" object class.
310        Block,
311        /// The SELinux "chr_file" object class.
312        Character,
313        /// The SELinux "dir" object class.
314        Dir,
315        /// The SELinux "fifo_file" object class.
316        Fifo,
317        /// The SELinux "file" object class.
318        File,
319        /// The SELinux "lnk_file" object class.
320        Link,
321        /// The SELinux "memfd_file" object class.
322        MemFdFile,
323        /// The SELinux "sock_file" object class.
324        SockFile,
325        // keep-sorted end
326    }
327}
328
329impl From<FileClass> for KernelClass {
330    fn from(file_class: FileClass) -> Self {
331        match file_class {
332            // keep-sorted start
333            FileClass::AnonFsNode => Self::AnonFsNode,
334            FileClass::Block => Self::Block,
335            FileClass::Character => Self::Character,
336            FileClass::Dir => Self::Dir,
337            FileClass::Fifo => Self::Fifo,
338            FileClass::File => Self::File,
339            FileClass::Link => Self::Link,
340            FileClass::MemFdFile => Self::MemFdFile,
341            FileClass::SockFile => Self::SockFile,
342            // keep-sorted end
343        }
344    }
345}
346
347enumerable_enum! {
348    /// Distinguishes socket-like kernel object classes defined in SELinux policy.
349    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
350    SocketClass {
351        // keep-sorted start
352        Icmp,
353        Key,
354        Netlink,
355        NetlinkAudit,
356        NetlinkConnector,
357        NetlinkCrypto,
358        NetlinkDnrt,
359        NetlinkFibLookup,
360        NetlinkFirewall,
361        NetlinkGeneric,
362        NetlinkIp6Fw,
363        NetlinkIscsi,
364        NetlinkKobjectUevent,
365        NetlinkNetfilter,
366        NetlinkNflog,
367        NetlinkRdma,
368        NetlinkRoute,
369        NetlinkScsitransport,
370        NetlinkSelinux,
371        NetlinkTcpDiag,
372        NetlinkXfrm,
373        Packet,
374        Qipcrtr,
375        RawIp,
376        Sctp,
377        /// Generic socket class applied to all socket-like objects for which no more specific
378        /// class is defined.
379        Socket,
380        Tcp,
381        Tun,
382        Udp,
383        UnixDgram,
384        UnixStream,
385        Vsock,
386        // keep-sorted end
387    }
388}
389
390impl From<SocketClass> for KernelClass {
391    fn from(socket_class: SocketClass) -> Self {
392        match socket_class {
393            // keep-sorted start
394            SocketClass::Icmp => Self::IcmpSocket,
395            SocketClass::Key => Self::KeySocket,
396            SocketClass::Netlink => Self::NetlinkSocket,
397            SocketClass::NetlinkAudit => Self::NetlinkAuditSocket,
398            SocketClass::NetlinkConnector => Self::NetlinkConnectorSocket,
399            SocketClass::NetlinkCrypto => Self::NetlinkCryptoSocket,
400            SocketClass::NetlinkDnrt => Self::NetlinkDnrtSocket,
401            SocketClass::NetlinkFibLookup => Self::NetlinkFibLookupSocket,
402            SocketClass::NetlinkFirewall => Self::NetlinkFirewallSocket,
403            SocketClass::NetlinkGeneric => Self::NetlinkGenericSocket,
404            SocketClass::NetlinkIp6Fw => Self::NetlinkIp6FwSocket,
405            SocketClass::NetlinkIscsi => Self::NetlinkIscsiSocket,
406            SocketClass::NetlinkKobjectUevent => Self::NetlinkKobjectUeventSocket,
407            SocketClass::NetlinkNetfilter => Self::NetlinkNetfilterSocket,
408            SocketClass::NetlinkNflog => Self::NetlinkNflogSocket,
409            SocketClass::NetlinkRdma => Self::NetlinkRdmaSocket,
410            SocketClass::NetlinkRoute => Self::NetlinkRouteSocket,
411            SocketClass::NetlinkScsitransport => Self::NetlinkScsitransportSocket,
412            SocketClass::NetlinkSelinux => Self::NetlinkSelinuxSocket,
413            SocketClass::NetlinkTcpDiag => Self::NetlinkTcpDiagSocket,
414            SocketClass::NetlinkXfrm => Self::NetlinkXfrmSocket,
415            SocketClass::Packet => Self::PacketSocket,
416            SocketClass::Qipcrtr => Self::QipcrtrSocket,
417            SocketClass::RawIp => Self::RawIpSocket,
418            SocketClass::Sctp => Self::SctpSocket,
419            SocketClass::Socket => Self::Socket,
420            SocketClass::Tcp => Self::TcpSocket,
421            SocketClass::Tun => Self::TunSocket,
422            SocketClass::Udp => Self::UdpSocket,
423            SocketClass::UnixDgram => Self::UnixDgramSocket,
424            SocketClass::UnixStream => Self::UnixStreamSocket,
425            SocketClass::Vsock => Self::VSockSocket,
426            // keep-sorted end
427        }
428    }
429}
430
431/// Container for a security class that could be associated with a [`crate::vfs::FsNode`], to allow
432/// permissions common to both file-like and socket-like classes to be generated easily by hooks.
433#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
434pub enum FsNodeClass {
435    File(FileClass),
436    Socket(SocketClass),
437}
438
439impl From<FsNodeClass> for KernelClass {
440    fn from(class: FsNodeClass) -> Self {
441        match class {
442            FsNodeClass::File(file_class) => file_class.into(),
443            FsNodeClass::Socket(sock_class) => sock_class.into(),
444        }
445    }
446}
447
448impl From<FileClass> for FsNodeClass {
449    fn from(file_class: FileClass) -> Self {
450        FsNodeClass::File(file_class)
451    }
452}
453
454impl From<SocketClass> for FsNodeClass {
455    fn from(sock_class: SocketClass) -> Self {
456        FsNodeClass::Socket(sock_class)
457    }
458}
459
460pub trait ClassPermission {
461    fn class(&self) -> KernelClass;
462}
463
464macro_rules! permission_enum {
465    ($(#[$meta:meta])* $name:ident {
466        $($(#[$variant_meta:meta])* $variant:ident($inner:ident)),*,
467    }) => {
468        $(#[$meta])*
469        pub enum $name {
470            $($(#[$variant_meta])* $variant($inner)),*
471        }
472
473        $(impl From<$inner> for $name {
474            fn from(v: $inner) -> Self {
475                Self::$variant(v)
476            }
477        })*
478
479        impl ClassPermission for $name {
480            fn class(&self) -> KernelClass {
481                match self {
482                    $($name::$variant(_) => KernelClass::$variant),*
483                }
484            }
485        }
486
487        impl $name {
488            pub fn name(&self) -> &'static str {
489                match self {
490                    $($name::$variant(v) => v.name()),*
491                }
492            }
493
494            pub fn all_variants() -> impl Iterator<Item=Self> {
495                let iter = [].iter().map(Clone::clone);
496                $(let iter = iter.chain($inner::all_variants().map($name::from));)*
497                iter
498            }
499        }
500    }
501}
502
503permission_enum! {
504    /// A well-known `(class, permission)` pair in SELinux policy that has a particular meaning in
505    /// policy enforcement hooks.
506    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
507    KernelPermission {
508        // keep-sorted start
509        /// Permissions for the well-known SELinux "anon_inode" file-like object class.
510        AnonFsNode(AnonFsNodePermission),
511        /// Permissions for the well-known SELinux "binder" file-like object class.
512        Binder(BinderPermission),
513        /// Permissions for the well-known SELinux "blk_file" file-like object class.
514        Block(BlockFilePermission),
515        /// Permissions for the well-known SELinux "bpf" file-like object class.
516        Bpf(BpfPermission),
517        /// Permissions for the well-known SELinux "capability" object class.
518        Capability(CapabilityPermission),
519        /// Permissions for the well-known SELinux "capability2" object class.
520        Capability2(Capability2Permission),
521        /// Permissions for the well-known SELinux "chr_file" file-like object class.
522        Character(CharacterFilePermission),
523        /// Permissions for the well-known SELinux "dir" file-like object class.
524        Dir(DirPermission),
525        /// Permissions for the well-known SELinux "fd" object class.
526        Fd(FdPermission),
527        /// Permissions for the well-known SELinux "fifo_file" file-like object class.
528        Fifo(FifoFilePermission),
529        /// Permissions for the well-known SELinux "file" object class.
530        File(FilePermission),
531        /// Permissions for the well-known SELinux "filesystem" object class.
532        FileSystem(FileSystemPermission),
533        /// "icmp_socket" class permissions, enabled by "extended_socket_class" policy capability.
534        IcmpSocket(IcmpSocketPermission),
535        /// Permissions for the well-known SELinux "packet_socket" object class.
536        KeySocket(KeySocketPermission),
537        /// Permissions for the well-known SELinux "lnk_file" file-like object class.
538        Link(LinkFilePermission),
539        /// Permissions for the well-known SELinux "memfd_file" file-like object class.
540        MemFdFile(MemFdFilePermission),
541        /// Permissions for the well-known SELinux "netlink_audit_socket" file-like object class.
542        NetlinkAuditSocket(NetlinkAuditSocketPermission),
543        /// Permissions for the well-known SELinux "netlink_connector_socket" file-like object class.
544        NetlinkConnectorSocket(NetlinkConnectorSocketPermission),
545        /// Permissions for the well-known SELinux "netlink_crypto_socket" file-like object class.
546        NetlinkCryptoSocket(NetlinkCryptoSocketPermission),
547        /// Permissions for the well-known SELinux "netlink_dnrt_socket" file-like object class.
548        NetlinkDnrtSocket(NetlinkDnrtSocketPermission),
549        /// Permissions for the well-known SELinux "netlink_fib_lookup_socket" file-like object class.
550        NetlinkFibLookupSocket(NetlinkFibLookupSocketPermission),
551        /// Permissions for the well-known SELinux "netlink_firewall_socket" file-like object class.
552        NetlinkFirewallSocket(NetlinkFirewallSocketPermission),
553        /// Permissions for the well-known SELinux "netlink_generic_socket" file-like object class.
554        NetlinkGenericSocket(NetlinkGenericSocketPermission),
555        /// Permissions for the well-known SELinux "netlink_ip6fw_socket" file-like object class.
556        NetlinkIp6FwSocket(NetlinkIp6FwSocketPermission),
557        /// Permissions for the well-known SELinux "netlink_iscsi_socket" file-like object class.
558        NetlinkIscsiSocket(NetlinkIscsiSocketPermission),
559        /// Permissions for the well-known SELinux "netlink_kobject_uevent_socket" file-like object class.
560        NetlinkKobjectUeventSocket(NetlinkKobjectUeventSocketPermission),
561        /// Permissions for the well-known SELinux "netlink_netfilter_socket" file-like object class.
562        NetlinkNetfilterSocket(NetlinkNetfilterSocketPermission),
563        /// Permissions for the well-known SELinux "netlink_nflog_socket" file-like object class.
564        NetlinkNflogSocket(NetlinkNflogSocketPermission),
565        /// Permissions for the well-known SELinux "netlink_rdma_socket" file-like object class.
566        NetlinkRdmaSocket(NetlinkRdmaSocketPermission),
567        /// Permissions for the well-known SELinux "netlink_route_socket" file-like object class.
568        NetlinkRouteSocket(NetlinkRouteSocketPermission),
569        /// Permissions for the well-known SELinux "netlink_scsitransport_socket" file-like object class.
570        NetlinkScsitransportSocket(NetlinkScsitransportSocketPermission),
571        /// Permissions for the well-known SELinux "netlink_selinux_socket" file-like object class.
572        NetlinkSelinuxSocket(NetlinkSelinuxSocketPermission),
573        /// Permissions for the well-known SELinux "netlink_socket" file-like object class.
574        NetlinkSocket(NetlinkSocketPermission),
575        /// Permissions for the well-known SELinux "netlink_tcpdiag_socket" file-like object class.
576        NetlinkTcpDiagSocket(NetlinkTcpDiagSocketPermission),
577        /// Permissions for the well-known SELinux "netlink_xfrm_socket" file-like object class.
578        NetlinkXfrmSocket(NetlinkXfrmSocketPermission),
579        /// Permissions for the well-known SELinux "packet_socket" object class.
580        PacketSocket(PacketSocketPermission),
581        /// Permissions for the well-known SELinux "perf_event" object class.
582        PerfEvent(PerfEventPermission),
583        /// Permissions for the well-known SELinux "process" object class.
584        Process(ProcessPermission),
585        /// Permissions for the well-known SELinux "process2" object class.
586        Process2(Process2Permission),
587        /// Permissions for the well-known SELinux "qipcrtr_socket" object class.
588        QipcrtrSocket(QipcrtrSocketPermission),
589        /// Permissions for the well-known SELinux "rawip_socket" object class.
590        RawIpSocket(RawIpSocketPermission),
591        /// "sctp_socket" class permissions, enabled by "extended_socket_class" policy capability.
592        SctpSocket(SctpSocketPermission),
593        /// Permissions for access to parts of the "selinuxfs" used to administer and query SELinux.
594        Security(SecurityPermission),
595        /// Permissions for the well-known SELinux "sock_file" file-like object class.
596        SockFile(SockFilePermission),
597        /// Permissions for the well-known SELinux "socket" object class.
598        Socket(SocketPermission),
599        /// Permissions for the well-known SELinux "system" object class.
600        System(SystemPermission),
601        /// Permissions for the well-known SELinux "tcp_socket" object class.
602        TcpSocket(TcpSocketPermission),
603        /// Permissions for the well-known SELinux "tun_socket" object class.
604        TunSocket(TunSocketPermission),
605        /// Permissions for the well-known SELinux "udp_socket" object class.
606        UdpSocket(UdpSocketPermission),
607        /// Permissions for the well-known SELinux "unix_dgram_socket" object class.
608        UnixDgramSocket(UnixDgramSocketPermission),
609        /// Permissions for the well-known SELinux "unix_stream_socket" object class.
610        UnixStreamSocket(UnixStreamSocketPermission),
611        /// "vsock_socket" class permissions, enabled by "extended_socket_class" policy capability.
612        VSockSocket(VsockSocketPermission),
613        // keep-sorted end
614    }
615}
616
617/// Helper used to define an enum of permission values, with specified names.
618/// Uses of this macro should not rely on "extends", which is solely for use to express permission
619/// inheritance in `class_permission_enum`.
620macro_rules! common_permission_enum {
621    ($(#[$meta:meta])* $name:ident $(extends $common_name:ident)? {
622        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
623    }) => {
624        enumerable_enum! {
625            $(#[$meta])* $name $(extends $common_name)? {
626                $($(#[$variant_meta])* $variant,)*
627            }
628        }
629
630        impl $name {
631            fn name(&self) -> &'static str {
632                match self {
633                    $($name::$variant => $variant_name,)*
634                    $(Self::Common(v) => {let v:$common_name = v.clone(); v.name()},)?
635                }
636            }
637        }
638    }
639}
640
641/// Helper used to declare the set of named permissions associated with an SELinux class.
642/// The `ClassType` trait is implemented on the declared `enum`, enabling values to be wrapped into
643/// the generic `KernelPermission` container.
644/// If an "extends" type is specified then a `Common` enum case is added, encapsulating the values
645/// of that underlying permission type. This is used to represent e.g. SELinux "dir" class deriving
646/// a basic set of permissions from the common "file" symbol.
647macro_rules! class_permission_enum {
648    ($(#[$meta:meta])* $name:ident $(extends $common_name:ident)? {
649        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
650    }) => {
651        common_permission_enum! {
652            $(#[$meta])* $name $(extends $common_name)? {
653                $($(#[$variant_meta])* $variant ($variant_name),)*
654            }
655        }
656
657        impl ClassPermission for $name {
658            fn class(&self) -> KernelClass {
659                KernelPermission::from(self.clone()).class()
660            }
661        }
662    }
663}
664
665common_permission_enum! {
666    /// Permissions common to all cap-like object classes (e.g. "capability" for now and
667    /// "cap_userns" after Starnix gains user namespacing support). These are combined with a
668    /// specific `CapabilityClass` by policy enforcement hooks, to obtain class-affine permission
669    /// values to check.
670    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
671    CommonCapPermission {
672        // keep-sorted start
673
674        AuditControl("audit_control"),
675        AuditWrite("audit_write"),
676        Chown("chown"),
677        DacOverride("dac_override"),
678        DacReadSearch("dac_read_search"),
679        Fowner("fowner"),
680        Fsetid("fsetid"),
681        IpcLock("ipc_lock"),
682        IpcOwner("ipc_owner"),
683        Kill("kill"),
684        Lease("lease"),
685        LinuxImmutable("linux_immutable"),
686        Mknod("mknod"),
687        NetAdmin("net_admin"),
688        NetBindService("net_bind_service"),
689        NetBroadcast("net_broadcast"),
690        NetRaw("net_raw"),
691        Setfcap("setfcap"),
692        Setgid("setgid"),
693        Setpcap("setpcap"),
694        Setuid("setuid"),
695        SysAdmin("sys_admin"),
696        SysBoot("sys_boot"),
697        SysChroot("sys_chroot"),
698        SysModule("sys_module"),
699        SysNice("sys_nice"),
700        SysPacct("sys_pacct"),
701        SysPtrace("sys_ptrace"),
702        SysRawio("sys_rawio"),
703        SysResource("sys_resource"),
704        SysTime("sys_time"),
705        SysTtyConfig("sys_tty_config"),
706
707        // keep-sorted end
708    }
709}
710
711class_permission_enum! {
712    /// A well-known "capability" class permission in SELinux policy that has a particular meaning
713    /// in policy enforcement hooks.
714    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
715    CapabilityPermission extends CommonCapPermission {}
716}
717
718impl ForClass<CapClass> for CommonCapPermission {
719    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
720    /// This is used to allow hooks to resolve e.g. common "sys_nice" permission access based on the
721    /// "allow" rules for the correct target object class.
722    fn for_class(&self, class: CapClass) -> KernelPermission {
723        match class {
724            CapClass::Capability => CapabilityPermission::Common(self.clone()).into(),
725        }
726    }
727}
728
729common_permission_enum! {
730    /// Permissions common to all cap2-like object classes (e.g. "capability2" for now and
731    /// "cap2_userns" after Starnix gains user namespacing support). These are combined with a
732    /// specific `Capability2Class` by policy enforcement hooks, to obtain class-affine permission
733    /// values to check.
734    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
735    CommonCap2Permission {
736        // keep-sorted start
737
738        AuditRead("audit_read"),
739        BlockSuspend("block_suspend"),
740        Bpf("bpf"),
741        MacAdmin("mac_admin"),
742        MacOverride("mac_override"),
743        Perfmon("perfmon"),
744        Syslog("syslog"),
745        WakeAlarm("wake_alarm"),
746
747        // keep-sorted end
748    }
749}
750
751class_permission_enum! {
752    /// A well-known "capability2" class permission in SELinux policy that has a particular meaning
753    /// in policy enforcement hooks.
754    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
755    Capability2Permission extends CommonCap2Permission {}
756}
757
758impl ForClass<Cap2Class> for CommonCap2Permission {
759    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
760    /// This is used to allow hooks to resolve e.g. common "mac_admin" permission access based on
761    /// the "allow" rules for the correct target object class.
762    fn for_class(&self, class: Cap2Class) -> KernelPermission {
763        match class {
764            Cap2Class::Capability2 => Capability2Permission::Common(self.clone()).into(),
765        }
766    }
767}
768
769common_permission_enum! {
770    /// Permissions meaningful for all [`crate::vfs::FsNode`]s, whether file- or socket-like.
771    ///
772    /// This extra layer of common permissions is not reflected in the hierarchy defined by the
773    /// SELinux Reference Policy. Because even common permissions are mapped per-class, by name, to
774    /// the policy equivalents, the implementation and policy notions of common permissions need not
775    /// be identical.
776    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
777    CommonFsNodePermission {
778        // keep-sorted start
779        /// Permission to append to a file or socket.
780        Append("append"),
781        /// Pseudo-permission used in `dontaudit` access-rules to allow access checks to be made
782        /// between specific sources & targets without generating audit logs.
783        AuditAccess("audit_access"),
784        /// Permission to create a file or socket.
785        Create("create"),
786        /// Permission to query attributes, including uid, gid and extended attributes.
787        GetAttr("getattr"),
788        /// Permission to execute ioctls on the file or socket.
789        Ioctl("ioctl"),
790        /// Permission to set and unset file or socket locks.
791        Lock("lock"),
792        /// Permission to map a file.
793        Map("map"),
794        /// Permission to read content from a file or socket, as well as reading or following links.
795        Read("read"),
796        /// Permission checked against the existing label when updating a node's security label.
797        RelabelFrom("relabelfrom"),
798        /// Permission checked against the new label when updating a node's security label.
799        RelabelTo("relabelto"),
800        /// Permission to modify attributes, including uid, gid and extended attributes.
801        SetAttr("setattr"),
802        /// Permission to write contents to the file or socket.
803        Write("write"),
804        // keep-sorted end
805    }
806}
807
808impl<T: Into<FsNodeClass>> ForClass<T> for CommonFsNodePermission {
809    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
810    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
811    /// "allow" rules for the correct target object class.
812    fn for_class(&self, class: T) -> KernelPermission {
813        match class.into() {
814            FsNodeClass::File(file_class) => {
815                CommonFilePermission::Common(self.clone()).for_class(file_class)
816            }
817            FsNodeClass::Socket(sock_class) => {
818                CommonSocketPermission::Common(self.clone()).for_class(sock_class)
819            }
820        }
821    }
822}
823common_permission_enum! {
824    /// Permissions common to all socket-like object classes. These are combined with a specific
825    /// `SocketClass` by policy enforcement hooks, to obtain class-affine permission values.
826    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
827    CommonSocketPermission extends CommonFsNodePermission {
828        // keep-sorted start
829        /// Permission to accept a connection.
830        Accept("accept"),
831        /// Permission to bind to a name.
832        Bind("bind"),
833        /// Permission to initiate a connection.
834        Connect("connect"),
835        /// Permission to get socket options.
836        GetOpt("getopt"),
837        /// Permission to listen for connections.
838        Listen("listen"),
839        /// Permission to send datagrams to the socket.
840        SendTo("sendto"),
841        /// Permission to set socket options.
842        SetOpt("setopt"),
843        /// Permission to terminate connection.
844        Shutdown("shutdown"),
845        // keep-sorted end
846    }
847}
848
849impl ForClass<SocketClass> for CommonSocketPermission {
850    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
851    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
852    /// "allow" rules for the correct target object class.
853    fn for_class(&self, class: SocketClass) -> KernelPermission {
854        match class {
855            SocketClass::Key => KeySocketPermission::Common(self.clone()).into(),
856            SocketClass::Netlink => NetlinkSocketPermission::Common(self.clone()).into(),
857            SocketClass::NetlinkAudit => NetlinkAuditSocketPermission::Common(self.clone()).into(),
858            SocketClass::NetlinkConnector => {
859                NetlinkConnectorSocketPermission::Common(self.clone()).into()
860            }
861            SocketClass::NetlinkCrypto => {
862                NetlinkCryptoSocketPermission::Common(self.clone()).into()
863            }
864            SocketClass::NetlinkDnrt => NetlinkDnrtSocketPermission::Common(self.clone()).into(),
865            SocketClass::NetlinkFibLookup => {
866                NetlinkFibLookupSocketPermission::Common(self.clone()).into()
867            }
868            SocketClass::NetlinkFirewall => {
869                NetlinkFirewallSocketPermission::Common(self.clone()).into()
870            }
871            SocketClass::NetlinkGeneric => {
872                NetlinkGenericSocketPermission::Common(self.clone()).into()
873            }
874            SocketClass::NetlinkIp6Fw => NetlinkIp6FwSocketPermission::Common(self.clone()).into(),
875            SocketClass::NetlinkIscsi => NetlinkIscsiSocketPermission::Common(self.clone()).into(),
876            SocketClass::NetlinkKobjectUevent => {
877                NetlinkKobjectUeventSocketPermission::Common(self.clone()).into()
878            }
879            SocketClass::NetlinkNetfilter => {
880                NetlinkNetfilterSocketPermission::Common(self.clone()).into()
881            }
882            SocketClass::NetlinkNflog => NetlinkNflogSocketPermission::Common(self.clone()).into(),
883            SocketClass::NetlinkRdma => NetlinkRdmaSocketPermission::Common(self.clone()).into(),
884            SocketClass::NetlinkRoute => NetlinkRouteSocketPermission::Common(self.clone()).into(),
885            SocketClass::NetlinkScsitransport => {
886                NetlinkScsitransportSocketPermission::Common(self.clone()).into()
887            }
888            SocketClass::NetlinkSelinux => {
889                NetlinkSelinuxSocketPermission::Common(self.clone()).into()
890            }
891            SocketClass::NetlinkTcpDiag => {
892                NetlinkTcpDiagSocketPermission::Common(self.clone()).into()
893            }
894            SocketClass::NetlinkXfrm => NetlinkXfrmSocketPermission::Common(self.clone()).into(),
895            SocketClass::Packet => PacketSocketPermission::Common(self.clone()).into(),
896            SocketClass::Qipcrtr => QipcrtrSocketPermission::Common(self.clone()).into(),
897            SocketClass::RawIp => RawIpSocketPermission::Common(self.clone()).into(),
898            SocketClass::Sctp => SctpSocketPermission::Common(self.clone()).into(),
899            SocketClass::Socket => SocketPermission::Common(self.clone()).into(),
900            SocketClass::Tcp => TcpSocketPermission::Common(self.clone()).into(),
901            SocketClass::Tun => TunSocketPermission::Common(self.clone()).into(),
902            SocketClass::Udp => UdpSocketPermission::Common(self.clone()).into(),
903            SocketClass::UnixDgram => UnixDgramSocketPermission::Common(self.clone()).into(),
904            SocketClass::UnixStream => UnixStreamSocketPermission::Common(self.clone()).into(),
905            SocketClass::Vsock => VsockSocketPermission::Common(self.clone()).into(),
906            SocketClass::Icmp => IcmpSocketPermission::Common(self.clone()).into(),
907        }
908    }
909}
910
911class_permission_enum! {
912    /// A well-known "key_socket" class permission in SELinux policy that has a particular meaning in
913    /// policy enforcement hooks.
914    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
915    KeySocketPermission extends CommonSocketPermission {
916    }
917}
918class_permission_enum! {
919    /// A well-known "netlink_socket" class permission in SELinux policy that has a particular meaning in
920    /// policy enforcement hooks.
921    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
922    NetlinkSocketPermission extends CommonSocketPermission {
923    }
924}
925
926class_permission_enum! {
927    /// A well-known "netlink_route_socket" class permission in SELinux policy that has a particular meaning in
928    /// policy enforcement hooks.
929    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
930    NetlinkRouteSocketPermission extends CommonSocketPermission {
931        // keep-sorted start
932        /// Permission for nlmsg xperms.
933        Nlmsg("nlmsg"),
934        /// Permission to read the kernel routing table.
935        NlmsgRead("nlmsg_read"),
936        /// Permission to write to the kernel routing table.
937        NlmsgWrite("nlmsg_write"),
938        // keep-sorted end
939    }
940}
941
942class_permission_enum! {
943    /// A well-known "netlink_firewall_socket" class permission in SELinux policy that has a particular meaning in
944    /// policy enforcement hooks.
945    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
946    NetlinkFirewallSocketPermission extends CommonSocketPermission {
947    }
948}
949
950class_permission_enum! {
951    /// A well-known "netlink_tcpdiag_socket" class permission in SELinux policy that has a particular meaning in
952    /// policy enforcement hooks.
953    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
954    NetlinkTcpDiagSocketPermission extends CommonSocketPermission {
955        // keep-sorted start
956        /// Permission for nlmsg xperms.
957        Nlmsg("nlmsg"),
958        /// Permission to request information about a protocol.
959        NlmsgRead("nlmsg_read"),
960        /// Permission to write netlink message.
961        NlmsgWrite("nlmsg_write"),
962        // keep-sorted end
963    }
964}
965
966class_permission_enum! {
967    /// A well-known "netlink_nflog_socket" class permission in SELinux policy that has a particular meaning in
968    /// policy enforcement hooks.
969    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
970    NetlinkNflogSocketPermission extends CommonSocketPermission {
971    }
972}
973
974class_permission_enum! {
975    /// A well-known "netlink_xfrm_socket" class permission in SELinux policy that has a particular meaning in
976    /// policy enforcement hooks.
977    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
978    NetlinkXfrmSocketPermission extends CommonSocketPermission {
979        // keep-sorted start
980        /// Permission for nlmsg xperms.
981        Nlmsg("nlmsg"),
982        /// Permission to get IPSec configuration information.
983        NlmsgRead("nlmsg_read"),
984        /// Permission to set IPSec configuration information.
985        NlmsgWrite("nlmsg_write"),
986        // keep-sorted end
987    }
988}
989
990class_permission_enum! {
991    /// A well-known "netlink_selinux_socket" class permission in SELinux policy that has a particular meaning in
992    /// policy enforcement hooks.
993    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
994    NetlinkSelinuxSocketPermission extends CommonSocketPermission {
995    }
996}
997
998class_permission_enum! {
999    /// A well-known "netlink_iscsi_socket" class permission in SELinux policy that has a particular meaning in
1000    /// policy enforcement hooks.
1001    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1002    NetlinkIscsiSocketPermission extends CommonSocketPermission {
1003    }
1004}
1005
1006class_permission_enum! {
1007    /// A well-known "netlink_audit_socket" class permission in SELinux policy that has a particular meaning in
1008    /// policy enforcement hooks.
1009    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1010    NetlinkAuditSocketPermission extends CommonSocketPermission {
1011        // keep-sorted start
1012        /// Permission for nlmsg xperms.
1013        Nlmsg("nlmsg"),
1014        /// Permission to query status of audit service.
1015        NlmsgRead("nlmsg_read"),
1016        /// Permission to list auditing configuration rules.
1017        NlmsgReadPriv("nlmsg_readpriv"),
1018        /// Permission to send userspace audit messages to the audit service.
1019        NlmsgRelay("nlmsg_relay"),
1020        /// Permission to control TTY auditing.
1021        NlmsgTtyAudit("nlmsg_tty_audit"),
1022        /// Permission to update the audit service configuration.
1023        NlmsgWrite("nlmsg_write"),
1024        // keep-sorted end
1025    }
1026}
1027
1028class_permission_enum! {
1029    /// A well-known "netlink_fib_lookup_socket" class permission in SELinux policy that has a particular meaning in
1030    /// policy enforcement hooks.
1031    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1032    NetlinkFibLookupSocketPermission extends CommonSocketPermission {
1033    }
1034}
1035
1036class_permission_enum! {
1037    /// A well-known "netlink_connector_socket" class permission in SELinux policy that has a particular meaning in
1038    /// policy enforcement hooks.
1039    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1040    NetlinkConnectorSocketPermission extends CommonSocketPermission {
1041    }
1042}
1043
1044class_permission_enum! {
1045    /// A well-known "netlink_netfilter_socket" class permission in SELinux policy that has a particular meaning in
1046    /// policy enforcement hooks.
1047    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1048    NetlinkNetfilterSocketPermission extends CommonSocketPermission {
1049    }
1050}
1051
1052class_permission_enum! {
1053    /// A well-known "netlink_ip6fw_socket" class permission in SELinux policy that has a particular meaning in
1054    /// policy enforcement hooks.
1055    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1056    NetlinkIp6FwSocketPermission extends CommonSocketPermission {
1057    }
1058}
1059
1060class_permission_enum! {
1061    /// A well-known "netlink_dnrt_socket" class permission in SELinux policy that has a particular meaning in
1062    /// policy enforcement hooks.
1063    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1064    NetlinkDnrtSocketPermission extends CommonSocketPermission {
1065    }
1066}
1067
1068class_permission_enum! {
1069    /// A well-known "netlink_kobject_uevent_socket" class permission in SELinux policy that has a particular meaning in
1070    /// policy enforcement hooks.
1071    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1072    NetlinkKobjectUeventSocketPermission extends CommonSocketPermission {
1073    }
1074}
1075
1076class_permission_enum! {
1077    /// A well-known "netlink_generic_socket" class permission in SELinux policy that has a particular meaning in
1078    /// policy enforcement hooks.
1079    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1080    NetlinkGenericSocketPermission extends CommonSocketPermission {
1081    }
1082}
1083
1084class_permission_enum! {
1085    /// A well-known "netlink_scsitransport_socket" class permission in SELinux policy that has a particular meaning in
1086    /// policy enforcement hooks.
1087    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1088    NetlinkScsitransportSocketPermission extends CommonSocketPermission {
1089    }
1090}
1091
1092class_permission_enum! {
1093    /// A well-known "netlink_rdma_socket" class permission in SELinux policy that has a particular meaning in
1094    /// policy enforcement hooks.
1095    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1096    NetlinkRdmaSocketPermission extends CommonSocketPermission {
1097    }
1098}
1099
1100class_permission_enum! {
1101    /// A well-known "netlink_crypto_socket" class permission in SELinux policy that has a particular meaning in
1102    /// policy enforcement hooks.
1103    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1104    NetlinkCryptoSocketPermission extends CommonSocketPermission {
1105    }
1106}
1107
1108class_permission_enum! {
1109    /// A well-known "packet_socket" class permission in SELinux policy that has a particular meaning in
1110    /// policy enforcement hooks.
1111    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1112    PacketSocketPermission extends CommonSocketPermission {
1113    }
1114}
1115
1116class_permission_enum! {
1117    /// A well-known "qipcrtr_socket" class permission in SELinux policy that has a particular meaning in
1118    /// policy enforcement hooks.
1119    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1120    QipcrtrSocketPermission extends CommonSocketPermission {
1121    }
1122}
1123
1124class_permission_enum! {
1125    /// A well-known "rawip_socket" class permission in SELinux policy that has a particular meaning in
1126    /// policy enforcement hooks.
1127    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1128    RawIpSocketPermission extends CommonSocketPermission {
1129    }
1130}
1131
1132class_permission_enum! {
1133    /// A well-known "sctp_socket" class permission in SELinux policy that has a particular meaning in
1134    /// policy enforcement hooks.
1135    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1136    SctpSocketPermission extends CommonSocketPermission {
1137        // keep-sorted start
1138        /// Permission to create an SCTP association.
1139        Associate("associate"),
1140        /// Permission to `connect()` or `connectx()` an SCTP socket.
1141        NameConnect("name_connect"),
1142        /// Permission to `bind()` or `bindx()` an SCTP socket.
1143        NodeBind("node_bind"),
1144        // keep-sorted end
1145    }
1146}
1147
1148class_permission_enum! {
1149    /// A well-known "socket" class permission in SELinux policy that has a particular meaning in
1150    /// policy enforcement hooks.
1151    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1152    SocketPermission extends CommonSocketPermission {
1153    }
1154}
1155
1156class_permission_enum! {
1157    /// A well-known "tcp_socket" class permission in SELinux policy that has a particular meaning in
1158    /// policy enforcement hooks.
1159    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1160    TcpSocketPermission extends CommonSocketPermission {
1161    }
1162}
1163
1164class_permission_enum! {
1165    /// A well-known "tun_socket" class permission in SELinux policy that has a particular meaning in
1166    /// policy enforcement hooks.
1167    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1168    TunSocketPermission extends CommonSocketPermission {
1169    }
1170}
1171
1172class_permission_enum! {
1173    /// A well-known "udp_socket" class permission in SELinux policy that has a particular meaning in
1174    /// policy enforcement hooks.
1175    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1176    UdpSocketPermission extends CommonSocketPermission {
1177    }
1178}
1179
1180class_permission_enum! {
1181    /// A well-known "unix_stream_socket" class permission in SELinux policy that has a particular meaning in
1182    /// policy enforcement hooks.
1183    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1184    UnixStreamSocketPermission extends CommonSocketPermission {
1185        // keep-sorted start
1186        /// Permission to connect a streaming Unix-domain socket.
1187        ConnectTo("connectto"),
1188        // keep-sorted end
1189    }
1190}
1191
1192class_permission_enum! {
1193    /// A well-known "unix_dgram_socket" class permission in SELinux policy that has a particular meaning in
1194    /// policy enforcement hooks.
1195    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1196    UnixDgramSocketPermission extends CommonSocketPermission {
1197    }
1198}
1199
1200class_permission_enum! {
1201    /// A well-known "vsock_socket" class permission in SELinux policy that has a particular meaning in
1202    /// policy enforcement hooks.
1203    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1204    VsockSocketPermission extends CommonSocketPermission {
1205    }
1206}
1207
1208class_permission_enum! {
1209    /// A well-known "icmp_socket" class permission in SELinux policy that has a particular meaning in
1210    /// policy enforcement hooks.
1211    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1212    IcmpSocketPermission extends CommonSocketPermission {
1213        // keep-sorted start
1214        /// Permission to `bind()` an ICMP socket.
1215        NodeBind("node_bind"),
1216        // keep-sorted end
1217    }
1218}
1219
1220common_permission_enum! {
1221    /// Permissions common to all file-like object classes (e.g. "lnk_file", "dir"). These are
1222    /// combined with a specific `FileClass` by policy enforcement hooks, to obtain class-affine
1223    /// permission values to check.
1224    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1225    CommonFilePermission extends CommonFsNodePermission {
1226        // keep-sorted start
1227        /// Permission to execute a file with domain transition.
1228        Execute("execute"),
1229        /// Permissions to create hard link.
1230        Link("link"),
1231        /// Permission to use as mount point; only useful for directories and files.
1232        MountOn("mounton"),
1233        /// Permission to open a file.
1234        Open("open"),
1235        /// Permission to rename a file.
1236        Rename("rename"),
1237        /// Permission to delete a file or remove a hard link.
1238        Unlink("unlink"),
1239        // keep-sorted end
1240    }
1241}
1242
1243impl ForClass<FileClass> for CommonFilePermission {
1244    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
1245    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
1246    /// "allow" rules for the correct target object class.
1247    fn for_class(&self, class: FileClass) -> KernelPermission {
1248        match class {
1249            FileClass::AnonFsNode => AnonFsNodePermission::Common(self.clone()).into(),
1250            FileClass::Block => BlockFilePermission::Common(self.clone()).into(),
1251            FileClass::Character => CharacterFilePermission::Common(self.clone()).into(),
1252            FileClass::Dir => DirPermission::Common(self.clone()).into(),
1253            FileClass::Fifo => FifoFilePermission::Common(self.clone()).into(),
1254            FileClass::File => FilePermission::Common(self.clone()).into(),
1255            FileClass::Link => LinkFilePermission::Common(self.clone()).into(),
1256            FileClass::SockFile => SockFilePermission::Common(self.clone()).into(),
1257            FileClass::MemFdFile => MemFdFilePermission::Common(self.clone()).into(),
1258        }
1259    }
1260}
1261
1262class_permission_enum! {
1263    /// A well-known "anon_file" class permission used to manage special file-like nodes not linked
1264    /// into any directory structures.
1265    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1266    AnonFsNodePermission extends CommonFilePermission {
1267    }
1268}
1269
1270class_permission_enum! {
1271    /// A well-known "binder" class permission in SELinux policy that has a particular meaning in
1272    /// policy enforcement hooks.
1273    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1274    BinderPermission {
1275        // keep-sorted start
1276        /// Permission to perform a binder IPC to a given target process.
1277        Call("call"),
1278        /// Permission to use a Binder connection created with a different security context.
1279        Impersonate("impersonate"),
1280        /// Permission to set oneself as a context manager.
1281        SetContextMgr("set_context_mgr"),
1282        /// Permission to transfer Binder objects as part of a Binder transaction.
1283        Transfer("transfer"),
1284        // keep-sorted end
1285    }
1286}
1287
1288class_permission_enum! {
1289    /// A well-known "blk_file" class permission in SELinux policy that has a particular meaning in
1290    /// policy enforcement hooks.
1291    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1292    BlockFilePermission extends CommonFilePermission {
1293    }
1294}
1295
1296class_permission_enum! {
1297    /// A well-known "chr_file" class permission in SELinux policy that has a particular meaning in
1298    /// policy enforcement hooks.
1299    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1300    CharacterFilePermission extends CommonFilePermission {
1301    }
1302}
1303
1304class_permission_enum! {
1305    /// A well-known "dir" class permission in SELinux policy that has a particular meaning in
1306    /// policy enforcement hooks.
1307    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1308    DirPermission extends CommonFilePermission {
1309        // keep-sorted start
1310        /// Permission to add a file to the directory.
1311        AddName("add_name"),
1312        /// Permission to remove a directory.
1313        RemoveDir("rmdir"),
1314        /// Permission to remove an entry from a directory.
1315        RemoveName("remove_name"),
1316        /// Permission to change parent directory.
1317        Reparent("reparent"),
1318        /// Search access to the directory.
1319        Search("search"),
1320        // keep-sorted end
1321    }
1322}
1323
1324class_permission_enum! {
1325    /// A well-known "fd" class permission in SELinux policy that has a particular meaning in policy
1326    /// enforcement hooks.
1327    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1328    FdPermission {
1329        // keep-sorted start
1330        /// Permission to use file descriptors copied/retained/inherited from another security
1331        /// context. This permission is generally used to control whether an `exec*()` call from a
1332        /// cloned process that retained a copy of the file descriptor table should succeed.
1333        Use("use"),
1334        // keep-sorted end
1335    }
1336}
1337
1338class_permission_enum! {
1339    /// A well-known "bpf" class permission in SELinux policy that has a particular meaning in
1340    /// policy enforcement hooks.
1341    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1342    BpfPermission {
1343        // keep-sorted start
1344        /// Permission to create a map.
1345        MapCreate("map_create"),
1346        /// Permission to read from a map.
1347        MapRead("map_read"),
1348        /// Permission to write on a map.
1349        MapWrite("map_write"),
1350        /// Permission to load a program.
1351        ProgLoad("prog_load"),
1352        /// Permission to run a program.
1353        ProgRun("prog_run"),
1354        // keep-sorted end
1355    }
1356}
1357
1358class_permission_enum! {
1359    /// A well-known "perf_event" class permission in SELinux policy that has a particular meaning
1360    /// in policy hooks.
1361    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1362    PerfEventPermission {
1363        // keep-sorted start
1364        /// Permission to monitor the cpu.
1365        Cpu("cpu"),
1366        /// Permission to monitor the kernel.
1367        Kernel("kernel"),
1368        /// Permission to open a perf event.
1369        Open("open"),
1370        /// Permission to read a perf event.
1371        Read("read"),
1372        /// Permission to set tracepoints.
1373        Tracepoint("tracepoint"),
1374        /// Permission to write a perf event.
1375        Write("write"),
1376        // keep-sorted end
1377    }
1378}
1379
1380class_permission_enum! {
1381    /// A well-known "fifo_file" class permission in SELinux policy that has a particular meaning in
1382    /// policy enforcement hooks.
1383    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1384    FifoFilePermission extends CommonFilePermission {
1385    }
1386}
1387
1388class_permission_enum! {
1389    /// A well-known "file" class permission in SELinux policy that has a particular meaning in
1390    /// policy enforcement hooks.
1391    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1392    FilePermission extends CommonFilePermission {
1393        // keep-sorted start
1394        /// Permission to use a file as an entry point into the new domain on transition.
1395        Entrypoint("entrypoint"),
1396        /// Permission to use a file as an entry point to the calling domain without performing a
1397        /// transition.
1398        ExecuteNoTrans("execute_no_trans"),
1399        // keep-sorted end
1400    }
1401}
1402
1403class_permission_enum! {
1404    /// A well-known "filesystem" class permission in SELinux policy that has a particular meaning in
1405    /// policy enforcement hooks.
1406    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1407    FileSystemPermission {
1408        // keep-sorted start
1409        /// Permission to associate a file to the filesystem.
1410        Associate("associate"),
1411        /// Permission to get filesystem attributes.
1412        GetAttr("getattr"),
1413        /// Permission mount a filesystem.
1414        Mount("mount"),
1415        /// Permission to remount a filesystem with different flags.
1416        Remount("remount"),
1417        /// Permission to unmount a filesystem.
1418        Unmount("unmount"),
1419        // keep-sorted end
1420    }
1421}
1422
1423class_permission_enum! {
1424    /// A well-known "lnk_file" class permission in SELinux policy that has a particular meaning in
1425    /// policy enforcement hooks.
1426    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1427    LinkFilePermission extends CommonFilePermission {
1428    }
1429}
1430
1431class_permission_enum! {
1432    /// A well-known "mem_file" class permission in SELinux policy that has a particular meaning in
1433    /// policy enforcement hooks.
1434    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1435    MemFdFilePermission extends CommonFilePermission {
1436    }
1437}
1438
1439class_permission_enum! {
1440    /// A well-known "sock_file" class permission in SELinux policy that has a particular meaning in
1441    /// policy enforcement hooks.
1442    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1443    SockFilePermission extends CommonFilePermission {
1444    }
1445}
1446
1447class_permission_enum! {
1448    /// A well-known "process" class permission in SELinux policy that has a particular meaning in
1449    /// policy enforcement hooks.
1450    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1451    ProcessPermission {
1452        // keep-sorted start
1453        /// Permission to dynamically transition a process to a different security domain.
1454        DynTransition("dyntransition"),
1455        /// Permission to execute arbitrary code from the heap.
1456        ExecHeap("execheap"),
1457        /// Permission to execute arbitrary code from memory.
1458        ExecMem("execmem"),
1459        /// Permission to execute arbitrary code from the stack.
1460        ExecStack("execstack"),
1461        /// Permission to fork the current running process.
1462        Fork("fork"),
1463        /// Permission to get Linux capabilities of a process.
1464        GetCap("getcap"),
1465        /// Permission to get the process group ID.
1466        GetPgid("getpgid"),
1467        /// Permission to get the resource limits on a process.
1468        GetRlimit("getrlimit"),
1469        /// Permission to get scheduling policy currently applied to a process.
1470        GetSched("getsched"),
1471        /// Permission to get the session ID.
1472        GetSession("getsession"),
1473        /// Permission to exec into a new security domain without setting the AT_SECURE entry in the
1474        /// executable's auxiliary vector.
1475        NoAtSecure("noatsecure"),
1476        /// Permission to trace a process.
1477        Ptrace("ptrace"),
1478        /// Permission to inherit the parent process's resource limits on exec.
1479        RlimitInh("rlimitinh"),
1480        /// Permission to set Linux capabilities of a process.
1481        SetCap("setcap"),
1482        /// Permission to set the calling task's current Security Context.
1483        /// The "dyntransition" permission separately limits which Contexts "setcurrent" may be used to transition to.
1484        SetCurrent("setcurrent"),
1485        /// Permission to set the Security Context used by `exec()`.
1486        SetExec("setexec"),
1487        /// Permission to set the Security Context used when creating filesystem objects.
1488        SetFsCreate("setfscreate"),
1489        /// Permission to set the Security Context used when creating kernel keyrings.
1490        SetKeyCreate("setkeycreate"),
1491        /// Permission to set the process group ID.
1492        SetPgid("setpgid"),
1493        /// Permission to set the resource limits on a process.
1494        SetRlimit("setrlimit"),
1495        /// Permission to set scheduling policy for a process.
1496        SetSched("setsched"),
1497        /// Permission to set the Security Context used when creating new labeled sockets.
1498        SetSockCreate("setsockcreate"),
1499        /// Permission to share resources (e.g. FD table, address-space, etc) with a process.
1500        Share("share"),
1501        /// Permission to send SIGCHLD to a process.
1502        SigChld("sigchld"),
1503        /// Permission to inherit the parent process's signal state.
1504        SigInh("siginh"),
1505        /// Permission to send SIGKILL to a process.
1506        SigKill("sigkill"),
1507        /// Permission to send SIGSTOP to a process.
1508        SigStop("sigstop"),
1509        /// Permission to send a signal other than SIGKILL, SIGSTOP, or SIGCHLD to a process.
1510        Signal("signal"),
1511        /// Permission to transition to a different security domain.
1512        Transition("transition"),
1513        // keep-sorted end
1514    }
1515}
1516
1517class_permission_enum! {
1518    /// A well-known "process2" class permission in SELinux policy that has a particular meaning in
1519    /// policy enforcement hooks.
1520    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1521    Process2Permission {
1522        // keep-sorted start
1523        /// Permission to transition to an unbounded domain when no-new-privileges is set.
1524        NnpTransition("nnp_transition"),
1525        /// Permission to transition domain when executing from a no-SUID mounted filesystem.
1526        NosuidTransition("nosuid_transition"),
1527        // keep-sorted end
1528    }
1529}
1530
1531class_permission_enum! {
1532    /// A well-known "security" class permission in SELinux policy, used to control access to
1533    /// sensitive administrative and query API surfaces in the "selinuxfs".
1534    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1535    SecurityPermission {
1536        // keep-sorted start
1537        /// Permission to validate Security Context using the "context" API.
1538        CheckContext("check_context"),
1539        /// Permission to compute access vectors via the "access" API.
1540        ComputeAv("compute_av"),
1541        /// Permission to compute security contexts based on `type_transition` rules via "create".
1542        ComputeCreate("compute_create"),
1543        /// Permission to compute security contexts based on `type_member` rules via "member".
1544        ComputeMember("compute_member"),
1545        /// Permission to compute security contexts based on `type_change` rules via "relabel".
1546        ComputeRelabel("compute_relabel"),
1547        /// Permission to compute user decisions via "user".
1548        ComputeUser("compute_user"),
1549        /// Permission to load a new binary policy into the kernel via the "load" API.
1550        LoadPolicy("load_policy"),
1551        /// Permission to commit booleans to control conditional elements of the policy.
1552        SetBool("setbool"),
1553        /// Permission to change the way permissions are validated for `mmap()` operations.
1554        SetCheckReqProt("setcheckreqprot"),
1555        /// Permission to switch the system between permissive and enforcing modes, via "enforce".
1556        SetEnforce("setenforce"),
1557        // keep-sorted end
1558     }
1559}
1560
1561class_permission_enum! {
1562    /// A well-known "system" class permission in SELinux policy, used to control access to
1563    /// sensitive administrative and query API surfaces in the "selinuxfs".
1564    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1565    SystemPermission {
1566        // keep-sorted start
1567        /// Permission to use the syslog(2) CONSOLE action types.
1568        SyslogConsole("syslog_console"),
1569        /// Permission to use other syslog(2) action types.
1570        SyslogMod("syslog_mod"),
1571        /// Permission to use the syslog(2) READ_ALL related action types.
1572        SyslogRead("syslog_read"),
1573        // keep-sorted end
1574     }
1575}
1576
1577/// A borrowed byte slice that contains no `NUL` characters by truncating the input slice at the
1578/// first `NUL` (if any) upon construction.
1579#[derive(Clone, Copy, Debug, PartialEq)]
1580pub struct NullessByteStr<'a>(&'a [u8]);
1581
1582impl<'a> NullessByteStr<'a> {
1583    /// Returns a non-null-terminated representation of the security context string.
1584    pub fn as_bytes(&self) -> &[u8] {
1585        &self.0
1586    }
1587}
1588
1589impl<'a, S: AsRef<[u8]> + ?Sized> From<&'a S> for NullessByteStr<'a> {
1590    /// Any `AsRef<[u8]>` can be processed into a [`NullessByteStr`]. The [`NullessByteStr`] will
1591    /// retain everything up to (but not including) a null character, or else the complete byte
1592    /// string.
1593    fn from(s: &'a S) -> Self {
1594        let value = s.as_ref();
1595        match value.iter().position(|c| *c == 0) {
1596            Some(end) => Self(&value[..end]),
1597            None => Self(value),
1598        }
1599    }
1600}
1601
1602#[derive(Clone, Debug, PartialEq)]
1603pub struct FileSystemMountSids {
1604    pub context: Option<SecurityId>,
1605    pub fs_context: Option<SecurityId>,
1606    pub def_context: Option<SecurityId>,
1607    pub root_context: Option<SecurityId>,
1608}
1609
1610#[derive(Clone, Debug, PartialEq)]
1611pub struct FileSystemLabel {
1612    pub sid: SecurityId,
1613    pub scheme: FileSystemLabelingScheme,
1614    // Sids obtained by parsing the mount options of the FileSystem.
1615    pub mount_sids: FileSystemMountSids,
1616}
1617
1618#[derive(Clone, Debug, PartialEq)]
1619pub enum FileSystemLabelingScheme {
1620    /// This filesystem was mounted with "context=".
1621    Mountpoint { sid: SecurityId },
1622    /// This filesystem has an "fs_use_xattr", "fs_use_task", or "fs_use_trans" entry in the
1623    /// policy. If the `fs_use_type` is "fs_use_xattr" then the `default_sid` specifies the SID
1624    /// with which to label `FsNode`s of files that do not have the "security.selinux" xattr.
1625    FsUse { fs_use_type: FsUseType, default_sid: SecurityId },
1626    /// This filesystem has one or more "genfscon" statements associated with it in the policy.
1627    /// If `supports_seclabel` is true then nodes in the filesystem may be dynamically relabeled.
1628    GenFsCon { supports_seclabel: bool },
1629}
1630
1631/// SELinux security context-related filesystem mount options. These options are documented in the
1632/// `context=context, fscontext=context, defcontext=context, and rootcontext=context` section of
1633/// the `mount(8)` manpage.
1634#[derive(Clone, Debug, Default, PartialEq)]
1635pub struct FileSystemMountOptions {
1636    /// Specifies the effective security context to use for all nodes in the filesystem, and the
1637    /// filesystem itself. If the filesystem already contains security attributes then these are
1638    /// ignored. May not be combined with any of the other options.
1639    pub context: Option<Vec<u8>>,
1640    /// Specifies an effective security context to use for un-labeled nodes in the filesystem,
1641    /// rather than falling-back to the policy-defined "file" context.
1642    pub def_context: Option<Vec<u8>>,
1643    /// The value of the `fscontext=[security-context]` mount option. This option is used to
1644    /// label the filesystem (superblock) itself.
1645    pub fs_context: Option<Vec<u8>>,
1646    /// The value of the `rootcontext=[security-context]` mount option. This option is used to
1647    /// (re)label the inode located at the filesystem mountpoint.
1648    pub root_context: Option<Vec<u8>>,
1649}
1650
1651/// Status information parameter for the [`SeLinuxStatusPublisher`] interface.
1652pub struct SeLinuxStatus {
1653    /// SELinux-wide enforcing vs. permissive mode  bit.
1654    pub is_enforcing: bool,
1655    /// Number of times the policy has been changed since SELinux started.
1656    pub change_count: u32,
1657    /// Bit indicating whether operations unknown SELinux abstractions will be denied.
1658    pub deny_unknown: bool,
1659}
1660
1661/// Interface for security server to interact with selinuxfs status file.
1662pub trait SeLinuxStatusPublisher: Send + Sync {
1663    /// Sets the value part of the associated selinuxfs status file.
1664    fn set_status(&mut self, policy_status: SeLinuxStatus);
1665}
1666
1667/// Reference policy capability Ids.
1668#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1669pub enum PolicyCap {
1670    NetworkPeerControls = 0,
1671    OpenPerms = 1,
1672    ExtendedSocketClass = 2,
1673    AlwaysCheckNetwork = 3,
1674    CgroupSeclabel = 4,
1675    NnpNosuidTransition = 5,
1676    GenfsSeclabelSymlinks = 6,
1677    IoctlSkipCloexec = 7,
1678    UserspaceInitialContext = 8,
1679    NetlinkXperm = 9,
1680    NetifWildcard = 10,
1681    GenfsSeclabelWildcard = 11,
1682    FunctionfsSeclabel = 12,
1683    MemfdClass = 13,
1684}
1685
1686impl PolicyCap {
1687    pub fn all_values() -> &'static [Self] {
1688        &[
1689            Self::NetworkPeerControls,
1690            Self::OpenPerms,
1691            Self::ExtendedSocketClass,
1692            Self::AlwaysCheckNetwork,
1693            Self::CgroupSeclabel,
1694            Self::NnpNosuidTransition,
1695            Self::GenfsSeclabelSymlinks,
1696            Self::IoctlSkipCloexec,
1697            Self::UserspaceInitialContext,
1698            Self::NetlinkXperm,
1699            Self::NetifWildcard,
1700            Self::GenfsSeclabelWildcard,
1701            Self::FunctionfsSeclabel,
1702            Self::MemfdClass,
1703        ]
1704    }
1705
1706    pub fn name(&self) -> &str {
1707        match self {
1708            Self::NetworkPeerControls => "network_peer_controls",
1709            Self::OpenPerms => "open_perms",
1710            Self::ExtendedSocketClass => "extended_socket_class",
1711            Self::AlwaysCheckNetwork => "always_check_network",
1712            Self::CgroupSeclabel => "cgroup_seclabel",
1713            Self::NnpNosuidTransition => "nnp_nosuid_transition",
1714            Self::GenfsSeclabelSymlinks => "genfs_seclabel_symlinks",
1715            Self::IoctlSkipCloexec => "ioctl_skip_cloexec",
1716            Self::UserspaceInitialContext => "userspace_initial_context",
1717            Self::NetlinkXperm => "netlink_xperm",
1718            Self::NetifWildcard => "netif_wildcard",
1719            Self::GenfsSeclabelWildcard => "genfs_seclabel_wildcard",
1720            Self::FunctionfsSeclabel => "functionfs_seclabel",
1721            Self::MemfdClass => "memfd_class",
1722        }
1723    }
1724
1725    pub fn by_name(name: &str) -> Option<Self> {
1726        Self::all_values().iter().find(|x| x.name() == name).copied()
1727    }
1728}
1729
1730/// The SELinux security structure for `ThreadGroup`.
1731
1732#[cfg(test)]
1733mod tests {
1734    use super::*;
1735    use std::num::NonZeroU32;
1736
1737    #[test]
1738    fn object_class_permissions() {
1739        let test_class_id = ClassId::new(NonZeroU32::new(20).unwrap());
1740        assert_eq!(ObjectClass::ClassId(test_class_id), test_class_id.into());
1741        for variant in ProcessPermission::all_variants() {
1742            assert_eq!(KernelClass::Process, variant.class());
1743            assert_eq!("process", variant.class().name());
1744            let permission: KernelPermission = variant.clone().into();
1745            assert_eq!(KernelPermission::Process(variant.clone()), permission);
1746            assert_eq!(ObjectClass::Kernel(KernelClass::Process), variant.class().into());
1747        }
1748    }
1749
1750    #[test]
1751    fn policy_capabilities() {
1752        for capability in PolicyCap::all_values() {
1753            assert_eq!(Some(*capability), PolicyCap::by_name(capability.name()));
1754        }
1755    }
1756
1757    #[test]
1758    fn nulless_byte_str_equivalence() {
1759        let unterminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0".into();
1760        let nul_terminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0\0".into();
1761        let nul_containing: NullessByteStr<'_> =
1762            b"u:object_r:test_valid_t:s0\0IGNORE THIS\0!\0".into();
1763
1764        for context in [nul_terminated, nul_containing] {
1765            assert_eq!(unterminated, context);
1766            assert_eq!(unterminated.as_bytes(), context.as_bytes());
1767        }
1768    }
1769}