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