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