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