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