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 read content from a file or socket, as well as reading or following links.
758        Read("read"),
759        /// Permission checked against the existing label when updating a node's security label.
760        RelabelFrom("relabelfrom"),
761        /// Permission checked against the new label when updating a node's security label.
762        RelabelTo("relabelto"),
763        /// Permission to modify attributes, including uid, gid and extended attributes.
764        SetAttr("setattr"),
765        /// Permission to write contents to the file or socket.
766        Write("write"),
767        // keep-sorted end
768    }
769}
770
771impl CommonFsNodePermission {
772    /// Returns the `class`-affine `Permission` value corresponding to this common permission.
773    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
774    /// "allow" rules for the correct target object class.
775    pub fn for_class(&self, class: impl Into<FsNodeClass>) -> Permission {
776        match class.into() {
777            FsNodeClass::File(file_class) => {
778                CommonFilePermission::Common(self.clone()).for_class(file_class)
779            }
780            FsNodeClass::Socket(sock_class) => {
781                CommonSocketPermission::Common(self.clone()).for_class(sock_class)
782            }
783        }
784    }
785}
786common_permission_enum! {
787    /// Permissions common to all socket-like object classes. These are combined with a specific
788    /// `SocketClass` by policy enforcement hooks, to obtain class-affine permission values.
789    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
790    CommonSocketPermission extends CommonFsNodePermission {
791        // keep-sorted start
792        // keep-sorted end
793    }
794}
795
796impl CommonSocketPermission {
797    /// Returns the `class`-affine `Permission` value corresponding to this common permission.
798    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
799    /// "allow" rules for the correct target object class.
800    pub fn for_class(&self, class: SocketClass) -> Permission {
801        match class {
802            SocketClass::Key => KeySocketPermission::Common(self.clone()).into(),
803            SocketClass::Netlink => NetlinkSocketPermission::Common(self.clone()).into(),
804            SocketClass::NetlinkAudit => NetlinkAuditSocketPermission::Common(self.clone()).into(),
805            SocketClass::NetlinkConnector => {
806                NetlinkConnectorSocketPermission::Common(self.clone()).into()
807            }
808            SocketClass::NetlinkCrypto => {
809                NetlinkCryptoSocketPermission::Common(self.clone()).into()
810            }
811            SocketClass::NetlinkDnrt => NetlinkDnrtSocketPermission::Common(self.clone()).into(),
812            SocketClass::NetlinkFibLookup => {
813                NetlinkFibLookupSocketPermission::Common(self.clone()).into()
814            }
815            SocketClass::NetlinkFirewall => {
816                NetlinkFirewallSocketPermission::Common(self.clone()).into()
817            }
818            SocketClass::NetlinkGeneric => {
819                NetlinkGenericSocketPermission::Common(self.clone()).into()
820            }
821            SocketClass::NetlinkIp6Fw => NetlinkIp6FwSocketPermission::Common(self.clone()).into(),
822            SocketClass::NetlinkIscsi => NetlinkIscsiSocketPermission::Common(self.clone()).into(),
823            SocketClass::NetlinkKobjectUevent => {
824                NetlinkKobjectUeventSocketPermission::Common(self.clone()).into()
825            }
826            SocketClass::NetlinkNetfilter => {
827                NetlinkNetfilterSocketPermission::Common(self.clone()).into()
828            }
829            SocketClass::NetlinkNflog => NetlinkNflogSocketPermission::Common(self.clone()).into(),
830            SocketClass::NetlinkRdma => NetlinkRdmaSocketPermission::Common(self.clone()).into(),
831            SocketClass::NetlinkRoute => NetlinkRouteSocketPermission::Common(self.clone()).into(),
832            SocketClass::NetlinkScsitransport => {
833                NetlinkScsitransportSocketPermission::Common(self.clone()).into()
834            }
835            SocketClass::NetlinkSelinux => {
836                NetlinkSelinuxSocketPermission::Common(self.clone()).into()
837            }
838            SocketClass::NetlinkTcpDiag => {
839                NetlinkTcpDiagSocketPermission::Common(self.clone()).into()
840            }
841            SocketClass::NetlinkXfrm => NetlinkXfrmSocketPermission::Common(self.clone()).into(),
842            SocketClass::Packet => PacketSocketPermission::Common(self.clone()).into(),
843            SocketClass::RawIp => RawIpSocketPermission::Common(self.clone()).into(),
844            SocketClass::Socket => SocketPermission::Common(self.clone()).into(),
845            SocketClass::Tcp => TcpSocketPermission::Common(self.clone()).into(),
846            SocketClass::Udp => UdpSocketPermission::Common(self.clone()).into(),
847            SocketClass::UnixDgram => UnixDgramSocketPermission::Common(self.clone()).into(),
848            SocketClass::UnixStream => UnixStreamSocketPermission::Common(self.clone()).into(),
849            SocketClass::Vsock => VsockSocketPermission::Common(self.clone()).into(),
850        }
851    }
852}
853
854class_permission_enum! {
855    /// A well-known "key_socket" class permission in SELinux policy that has a particular meaning in
856    /// policy enforcement hooks.
857    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
858    KeySocketPermission extends CommonSocketPermission {
859    }
860}
861class_permission_enum! {
862    /// A well-known "netlink_socket" class permission in SELinux policy that has a particular meaning in
863    /// policy enforcement hooks.
864    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
865    NetlinkSocketPermission extends CommonSocketPermission {
866    }
867}
868
869class_permission_enum! {
870    /// A well-known "netlink_route_socket" class permission in SELinux policy that has a particular meaning in
871    /// policy enforcement hooks.
872    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
873    NetlinkRouteSocketPermission extends CommonSocketPermission {
874    }
875}
876
877class_permission_enum! {
878    /// A well-known "netlink_firewall_socket" class permission in SELinux policy that has a particular meaning in
879    /// policy enforcement hooks.
880    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
881    NetlinkFirewallSocketPermission extends CommonSocketPermission {
882    }
883}
884
885class_permission_enum! {
886    /// A well-known "netlink_tcpdiag_socket" class permission in SELinux policy that has a particular meaning in
887    /// policy enforcement hooks.
888    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
889    NetlinkTcpDiagSocketPermission extends CommonSocketPermission {
890    }
891}
892
893class_permission_enum! {
894    /// A well-known "netlink_nflog_socket" class permission in SELinux policy that has a particular meaning in
895    /// policy enforcement hooks.
896    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
897    NetlinkNflogSocketPermission extends CommonSocketPermission {
898    }
899}
900
901class_permission_enum! {
902    /// A well-known "netlink_xfrm_socket" class permission in SELinux policy that has a particular meaning in
903    /// policy enforcement hooks.
904    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
905    NetlinkXfrmSocketPermission extends CommonSocketPermission {
906    }
907}
908
909class_permission_enum! {
910    /// A well-known "netlink_selinux_socket" class permission in SELinux policy that has a particular meaning in
911    /// policy enforcement hooks.
912    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
913    NetlinkSelinuxSocketPermission extends CommonSocketPermission {
914    }
915}
916
917class_permission_enum! {
918    /// A well-known "netlink_iscsi_socket" class permission in SELinux policy that has a particular meaning in
919    /// policy enforcement hooks.
920    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
921    NetlinkIscsiSocketPermission extends CommonSocketPermission {
922    }
923}
924
925class_permission_enum! {
926    /// A well-known "netlink_audit_socket" class permission in SELinux policy that has a particular meaning in
927    /// policy enforcement hooks.
928    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
929    NetlinkAuditSocketPermission extends CommonSocketPermission {
930    }
931}
932
933class_permission_enum! {
934    /// A well-known "netlink_fib_lookup_socket" class permission in SELinux policy that has a particular meaning in
935    /// policy enforcement hooks.
936    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
937    NetlinkFibLookupSocketPermission extends CommonSocketPermission {
938    }
939}
940
941class_permission_enum! {
942    /// A well-known "netlink_connector_socket" class permission in SELinux policy that has a particular meaning in
943    /// policy enforcement hooks.
944    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
945    NetlinkConnectorSocketPermission extends CommonSocketPermission {
946    }
947}
948
949class_permission_enum! {
950    /// A well-known "netlink_netfilter_socket" class permission in SELinux policy that has a particular meaning in
951    /// policy enforcement hooks.
952    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
953    NetlinkNetfilterSocketPermission extends CommonSocketPermission {
954    }
955}
956
957class_permission_enum! {
958    /// A well-known "netlink_ip6fw_socket" class permission in SELinux policy that has a particular meaning in
959    /// policy enforcement hooks.
960    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
961    NetlinkIp6FwSocketPermission extends CommonSocketPermission {
962    }
963}
964
965class_permission_enum! {
966    /// A well-known "netlink_dnrt_socket" class permission in SELinux policy that has a particular meaning in
967    /// policy enforcement hooks.
968    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
969    NetlinkDnrtSocketPermission extends CommonSocketPermission {
970    }
971}
972
973class_permission_enum! {
974    /// A well-known "netlink_kobject_uevent_socket" class permission in SELinux policy that has a particular meaning in
975    /// policy enforcement hooks.
976    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
977    NetlinkKobjectUeventSocketPermission extends CommonSocketPermission {
978    }
979}
980
981class_permission_enum! {
982    /// A well-known "netlink_generic_socket" class permission in SELinux policy that has a particular meaning in
983    /// policy enforcement hooks.
984    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
985    NetlinkGenericSocketPermission extends CommonSocketPermission {
986    }
987}
988
989class_permission_enum! {
990    /// A well-known "netlink_scsitransport_socket" class permission in SELinux policy that has a particular meaning in
991    /// policy enforcement hooks.
992    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
993    NetlinkScsitransportSocketPermission extends CommonSocketPermission {
994    }
995}
996
997class_permission_enum! {
998    /// A well-known "netlink_rdma_socket" class permission in SELinux policy that has a particular meaning in
999    /// policy enforcement hooks.
1000    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1001    NetlinkRdmaSocketPermission extends CommonSocketPermission {
1002    }
1003}
1004
1005class_permission_enum! {
1006    /// A well-known "netlink_crypto_socket" class permission in SELinux policy that has a particular meaning in
1007    /// policy enforcement hooks.
1008    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1009    NetlinkCryptoSocketPermission extends CommonSocketPermission {
1010    }
1011}
1012
1013class_permission_enum! {
1014    /// A well-known "packet_socket" class permission in SELinux policy that has a particular meaning in
1015    /// policy enforcement hooks.
1016    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1017    PacketSocketPermission extends CommonSocketPermission {
1018    }
1019}
1020
1021class_permission_enum! {
1022    /// A well-known "rawip_socket" class permission in SELinux policy that has a particular meaning in
1023    /// policy enforcement hooks.
1024    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1025    RawIpSocketPermission extends CommonSocketPermission {
1026    }
1027}
1028
1029class_permission_enum! {
1030    /// A well-known "socket" class permission in SELinux policy that has a particular meaning in
1031    /// policy enforcement hooks.
1032    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1033    SocketPermission extends CommonSocketPermission {
1034    }
1035}
1036
1037class_permission_enum! {
1038    /// A well-known "tcp_socket" class permission in SELinux policy that has a particular meaning in
1039    /// policy enforcement hooks.
1040    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1041    TcpSocketPermission extends CommonSocketPermission {
1042    }
1043}
1044
1045class_permission_enum! {
1046    /// A well-known "udp_socket" class permission in SELinux policy that has a particular meaning in
1047    /// policy enforcement hooks.
1048    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1049    UdpSocketPermission extends CommonSocketPermission {
1050    }
1051}
1052
1053class_permission_enum! {
1054    /// A well-known "unix_stream_socket" class permission in SELinux policy that has a particular meaning in
1055    /// policy enforcement hooks.
1056    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1057    UnixStreamSocketPermission extends CommonSocketPermission {
1058    }
1059}
1060
1061class_permission_enum! {
1062    /// A well-known "unix_dgram_socket" class permission in SELinux policy that has a particular meaning in
1063    /// policy enforcement hooks.
1064    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1065    UnixDgramSocketPermission extends CommonSocketPermission {
1066    }
1067}
1068
1069class_permission_enum! {
1070    /// A well-known "vsock_socket" class permission in SELinux policy that has a particular meaning in
1071    /// policy enforcement hooks.
1072    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1073    VsockSocketPermission extends CommonSocketPermission {
1074    }
1075}
1076
1077common_permission_enum! {
1078    /// Permissions common to all file-like object classes (e.g. "lnk_file", "dir"). These are
1079    /// combined with a specific `FileClass` by policy enforcement hooks, to obtain class-affine
1080    /// permission values to check.
1081    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1082    CommonFilePermission extends CommonFsNodePermission {
1083        // keep-sorted start
1084        /// Permission to execute a file with domain transition.
1085        Execute("execute"),
1086        /// Permissions to create hard link.
1087        Link("link"),
1088        /// Permission to use as mount point; only useful for directories and files.
1089        MountOn("mounton"),
1090        /// Permission to open a file.
1091        Open("open"),
1092        /// Permission to rename a file.
1093        Rename("rename"),
1094        /// Permission to delete a file or remove a hard link.
1095        Unlink("unlink"),
1096        // keep-sorted end
1097    }
1098}
1099
1100impl CommonFilePermission {
1101    /// Returns the `class`-affine `Permission` value corresponding to this common permission.
1102    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
1103    /// "allow" rules for the correct target object class.
1104    pub fn for_class(&self, class: FileClass) -> Permission {
1105        match class {
1106            FileClass::AnonFsNode => AnonFsNodePermission::Common(self.clone()).into(),
1107            FileClass::Block => BlockFilePermission::Common(self.clone()).into(),
1108            FileClass::Character => CharacterFilePermission::Common(self.clone()).into(),
1109            FileClass::Dir => DirPermission::Common(self.clone()).into(),
1110            FileClass::Fifo => FifoFilePermission::Common(self.clone()).into(),
1111            FileClass::File => FilePermission::Common(self.clone()).into(),
1112            FileClass::Link => LinkFilePermission::Common(self.clone()).into(),
1113            FileClass::SockFile => SockFilePermission::Common(self.clone()).into(),
1114        }
1115    }
1116}
1117
1118class_permission_enum! {
1119    /// A well-known "anon_file" class permission used to manage special file-like nodes not linked
1120    /// into any directory structures.
1121    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1122    AnonFsNodePermission extends CommonFilePermission {
1123    }
1124}
1125
1126class_permission_enum! {
1127    /// A well-known "blk_file" class permission in SELinux policy that has a particular meaning in
1128    /// policy enforcement hooks.
1129    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1130    BlockFilePermission extends CommonFilePermission {
1131    }
1132}
1133
1134class_permission_enum! {
1135    /// A well-known "chr_file" class permission in SELinux policy that has a particular meaning in
1136    /// policy enforcement hooks.
1137    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1138    CharacterFilePermission extends CommonFilePermission {
1139    }
1140}
1141
1142class_permission_enum! {
1143    /// A well-known "dir" class permission in SELinux policy that has a particular meaning in
1144    /// policy enforcement hooks.
1145    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1146    DirPermission extends CommonFilePermission {
1147        // keep-sorted start
1148        /// Permission to add a file to the directory.
1149        AddName("add_name"),
1150        /// Permission to remove a directory.
1151        RemoveDir("rmdir"),
1152        /// Permission to remove an entry from a directory.
1153        RemoveName("remove_name"),
1154        /// Permission to change parent directory.
1155        Reparent("reparent"),
1156        /// Search access to the directory.
1157        Search("search"),
1158        // keep-sorted end
1159    }
1160}
1161
1162class_permission_enum! {
1163    /// A well-known "fd" class permission in SELinux policy that has a particular meaning in policy
1164    /// enforcement hooks.
1165    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1166    FdPermission {
1167        // keep-sorted start
1168        /// Permission to use file descriptors copied/retained/inherited from another security
1169        /// context. This permission is generally used to control whether an `exec*()` call from a
1170        /// cloned process that retained a copy of the file descriptor table should succeed.
1171        Use("use"),
1172        // keep-sorted end
1173    }
1174}
1175
1176class_permission_enum! {
1177    /// A well-known "bpf" class permission in SELinux policy that has a particular meaning in
1178    /// policy enforcement hooks.
1179    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1180    BpfPermission {
1181        // keep-sorted start
1182        /// Permission to create a map.
1183        MapCreate("map_create"),
1184        /// Permission to read from a map.
1185        MapRead("map_read"),
1186        /// Permission to write on a map.
1187        MapWrite("map_write"),
1188        /// Permission to load a program.
1189        ProgLoad("prog_load"),
1190        /// Permission to run a program.
1191        ProgRun("prog_run"),
1192        // keep-sorted end
1193    }
1194}
1195
1196class_permission_enum! {
1197    /// A well-known "fifo_file" class permission in SELinux policy that has a particular meaning in
1198    /// policy enforcement hooks.
1199    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1200    FifoFilePermission extends CommonFilePermission {
1201    }
1202}
1203
1204class_permission_enum! {
1205    /// A well-known "file" class permission in SELinux policy that has a particular meaning in
1206    /// policy enforcement hooks.
1207    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1208    FilePermission extends CommonFilePermission {
1209        // keep-sorted start
1210        /// Permission to use a file as an entry point into the new domain on transition.
1211        Entrypoint("entrypoint"),
1212        /// Permission to use a file as an entry point to the calling domain without performing a
1213        /// transition.
1214        ExecuteNoTrans("execute_no_trans"),
1215        // keep-sorted end
1216    }
1217}
1218
1219class_permission_enum! {
1220    /// A well-known "filesystem" class permission in SELinux policy that has a particular meaning in
1221    /// policy enforcement hooks.
1222    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1223    FileSystemPermission {
1224        // keep-sorted start
1225        /// Permission to associate a file to the filesystem.
1226        Associate("associate"),
1227        /// Permission to get filesystem attributes.
1228        GetAttr("getattr"),
1229        /// Permission mount a filesystem.
1230        Mount("mount"),
1231        /// Permission to remount a filesystem with different flags.
1232        Remount("remount"),
1233        /// Permission to unmount a filesystem.
1234        Unmount("unmount"),
1235        // keep-sorted end
1236    }
1237}
1238
1239class_permission_enum! {
1240    /// A well-known "lnk_file" class permission in SELinux policy that has a particular meaning in
1241    /// policy enforcement hooks.
1242    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1243    LinkFilePermission extends CommonFilePermission {
1244    }
1245}
1246
1247class_permission_enum! {
1248    /// A well-known "sock_file" class permission in SELinux policy that has a particular meaning in
1249    /// policy enforcement hooks.
1250    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1251    SockFilePermission extends CommonFilePermission {
1252    }
1253}
1254
1255class_permission_enum! {
1256    /// A well-known "process" class permission in SELinux policy that has a particular meaning in
1257    /// policy enforcement hooks.
1258    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1259    ProcessPermission {
1260        // keep-sorted start
1261        /// Permission to dynamically transition a process to a different security domain.
1262        DynTransition("dyntransition"),
1263        /// Permission to fork the current running process.
1264        Fork("fork"),
1265        /// Permission to get the process group ID.
1266        GetPgid("getpgid"),
1267        /// Permission to get the resource limits on a process.
1268        GetRlimit("getrlimit"),
1269        /// Permission to get scheduling policy currently applied to a process.
1270        GetSched("getsched"),
1271        /// Permission to get the session ID.
1272        GetSession("getsession"),
1273        /// Permission to trace a process.
1274        Ptrace("ptrace"),
1275        /// Permission to inherit the parent process's resource limits on exec.
1276        RlimitInh("rlimitinh"),
1277        /// Permission to set the calling task's current Security Context.
1278        /// The "dyntransition" permission separately limits which Contexts "setcurrent" may be used to transition to.
1279        SetCurrent("setcurrent"),
1280        /// Permission to set the Security Context used by `exec()`.
1281        SetExec("setexec"),
1282        /// Permission to set the Security Context used when creating filesystem objects.
1283        SetFsCreate("setfscreate"),
1284        /// Permission to set the Security Context used when creating kernel keyrings.
1285        SetKeyCreate("setkeycreate"),
1286        /// Permission to set the process group ID.
1287        SetPgid("setpgid"),
1288        /// Permission to set the resource limits on a process.
1289        SetRlimit("setrlimit"),
1290        /// Permission to set scheduling policy for a process.
1291        SetSched("setsched"),
1292        /// Permission to set the Security Context used when creating new labeled sockets.
1293        SetSockCreate("setsockcreate"),
1294        /// Permission to share resources (e.g. FD table, address-space, etc) with a process.
1295        Share("share"),
1296        /// Permission to send SIGCHLD to a process.
1297        SigChld("sigchld"),
1298        /// Permission to send SIGKILL to a process.
1299        SigKill("sigkill"),
1300        /// Permission to send SIGSTOP to a process.
1301        SigStop("sigstop"),
1302        /// Permission to send a signal other than SIGKILL, SIGSTOP, or SIGCHLD to a process.
1303        Signal("signal"),
1304        /// Permission to transition to a different security domain.
1305        Transition("transition"),
1306        // keep-sorted end
1307    }
1308}
1309
1310class_permission_enum! {
1311    /// A well-known "security" class permission in SELinux policy, used to control access to
1312    /// sensitive administrative and query API surfaces in the "selinuxfs".
1313    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1314    SecurityPermission {
1315        // keep-sorted start
1316        /// Permission to validate Security Context using the "context" API.
1317        CheckContext("check_context"),
1318        /// Permission to compute access vectors via the "access" API.
1319        ComputeAv("compute_av"),
1320        /// Permission to compute security contexts for newly created objects via "create".
1321        ComputeCreate("compute_create"),
1322        /// Permission to load a new binary policy into the kernel via the "load" API.
1323        LoadPolicy("load_policy"),
1324        /// Permission to commit booleans to control conditional elements of the policy.
1325        SetBool("setbool"),
1326        /// Permission to change the way permissions are validated for `mmap()` operations.
1327        SetCheckReqProt("setcheckreqprot"),
1328        /// Permission to switch the system between permissive and enforcing modes, via "enforce".
1329        SetEnforce("setenforce"),
1330        // keep-sorted end
1331     }
1332}
1333
1334/// Initial Security Identifier (SID) values defined by the SELinux Reference Policy.
1335/// Where the SELinux Reference Policy retains definitions for some deprecated initial SIDs, this
1336/// enum omits deprecated entries for clarity.
1337#[repr(u64)]
1338enum ReferenceInitialSid {
1339    Kernel = 1,
1340    Security = 2,
1341    Unlabeled = 3,
1342    _Fs = 4,
1343    File = 5,
1344    _AnySocket = 6,
1345    _Port = 7,
1346    _Netif = 8,
1347    _Netmsg = 9,
1348    _Node = 10,
1349    _Sysctl = 15,
1350    _Devnull = 25,
1351
1352    FirstUnused,
1353}
1354
1355/// Lowest Security Identifier value guaranteed not to be used by this
1356/// implementation to refer to an initial Security Context.
1357pub const FIRST_UNUSED_SID: u32 = ReferenceInitialSid::FirstUnused as u32;
1358
1359macro_rules! initial_sid_enum {
1360    ($(#[$meta:meta])* $name:ident {
1361        $($(#[$variant_meta:meta])* $variant:ident ($variant_name: literal)),*,
1362    }) => {
1363        $(#[$meta])*
1364        pub enum $name {
1365            $($(#[$variant_meta])* $variant = ReferenceInitialSid::$variant as isize),*
1366        }
1367
1368        impl $name {
1369            pub fn all_variants() -> Vec<Self> {
1370                vec![
1371                    $($name::$variant),*
1372                ]
1373            }
1374
1375            pub fn name(&self) -> &'static str {
1376                match self {
1377                    $($name::$variant => $variant_name),*
1378                }
1379            }
1380        }
1381    }
1382}
1383
1384initial_sid_enum! {
1385/// Initial Security Identifier (SID) values actually used by this implementation.
1386/// These must be present in the policy, for it to be valid.
1387#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1388    InitialSid {
1389        // keep-sorted start
1390        File("file"),
1391        Kernel("kernel"),
1392        Security("security"),
1393        Unlabeled("unlabeled"),
1394        // keep-sorted end
1395    }
1396}
1397
1398/// A borrowed byte slice that contains no `NUL` characters by truncating the input slice at the
1399/// first `NUL` (if any) upon construction.
1400#[derive(Clone, Copy, Debug, PartialEq)]
1401pub struct NullessByteStr<'a>(&'a [u8]);
1402
1403impl<'a> NullessByteStr<'a> {
1404    /// Returns a non-null-terminated representation of the security context string.
1405    pub fn as_bytes(&self) -> &[u8] {
1406        &self.0
1407    }
1408}
1409
1410impl<'a, S: AsRef<[u8]> + ?Sized> From<&'a S> for NullessByteStr<'a> {
1411    /// Any `AsRef<[u8]>` can be processed into a [`NullessByteStr`]. The [`NullessByteStr`] will
1412    /// retain everything up to (but not including) a null character, or else the complete byte
1413    /// string.
1414    fn from(s: &'a S) -> Self {
1415        let value = s.as_ref();
1416        match value.iter().position(|c| *c == 0) {
1417            Some(end) => Self(&value[..end]),
1418            None => Self(value),
1419        }
1420    }
1421}
1422
1423#[derive(Clone, Debug, PartialEq)]
1424pub struct FileSystemMountSids {
1425    pub context: Option<SecurityId>,
1426    pub fs_context: Option<SecurityId>,
1427    pub def_context: Option<SecurityId>,
1428    pub root_context: Option<SecurityId>,
1429}
1430
1431#[derive(Clone, Debug, PartialEq)]
1432pub struct FileSystemLabel {
1433    pub sid: SecurityId,
1434    pub scheme: FileSystemLabelingScheme,
1435    // Sids obtained by parsing the mount options of the FileSystem.
1436    pub mount_sids: FileSystemMountSids,
1437}
1438
1439#[derive(Clone, Debug, PartialEq)]
1440pub enum FileSystemLabelingScheme {
1441    /// This filesystem was mounted with "context=".
1442    Mountpoint { sid: SecurityId },
1443    /// This filesystem has an "fs_use_xattr", "fs_use_task", or "fs_use_trans" entry in the
1444    /// policy. `root_sid` identifies the context for the root of the filesystem and
1445    /// `computed_def_sid`  identifies the context to use for unlabeled files in the filesystem
1446    /// (the "default context").
1447    FsUse { fs_use_type: FsUseType, computed_def_sid: SecurityId },
1448    /// This filesystem has one or more "genfscon" statements associated with it in the policy.
1449    GenFsCon,
1450}
1451
1452/// SELinux security context-related filesystem mount options. These options are documented in the
1453/// `context=context, fscontext=context, defcontext=context, and rootcontext=context` section of
1454/// the `mount(8)` manpage.
1455#[derive(Clone, Debug, Default, PartialEq)]
1456pub struct FileSystemMountOptions {
1457    /// Specifies the effective security context to use for all nodes in the filesystem, and the
1458    /// filesystem itself. If the filesystem already contains security attributes then these are
1459    /// ignored. May not be combined with any of the other options.
1460    pub context: Option<Vec<u8>>,
1461    /// Specifies an effective security context to use for un-labeled nodes in the filesystem,
1462    /// rather than falling-back to the policy-defined "file" context.
1463    pub def_context: Option<Vec<u8>>,
1464    /// The value of the `fscontext=[security-context]` mount option. This option is used to
1465    /// label the filesystem (superblock) itself.
1466    pub fs_context: Option<Vec<u8>>,
1467    /// The value of the `rootcontext=[security-context]` mount option. This option is used to
1468    /// (re)label the inode located at the filesystem mountpoint.
1469    pub root_context: Option<Vec<u8>>,
1470}
1471
1472/// Status information parameter for the [`SeLinuxStatusPublisher`] interface.
1473pub struct SeLinuxStatus {
1474    /// SELinux-wide enforcing vs. permissive mode  bit.
1475    pub is_enforcing: bool,
1476    /// Number of times the policy has been changed since SELinux started.
1477    pub change_count: u32,
1478    /// Bit indicating whether operations unknown SELinux abstractions will be denied.
1479    pub deny_unknown: bool,
1480}
1481
1482/// Interface for security server to interact with selinuxfs status file.
1483pub trait SeLinuxStatusPublisher: Send {
1484    /// Sets the value part of the associated selinuxfs status file.
1485    fn set_status(&mut self, policy_status: SeLinuxStatus);
1486}
1487
1488#[cfg(test)]
1489mod tests {
1490    use super::*;
1491
1492    #[test]
1493    fn object_class_permissions() {
1494        assert_eq!(AbstractObjectClass::Unspecified, AbstractObjectClass::default());
1495        assert_eq!(
1496            AbstractObjectClass::Custom(String::from("my_class")),
1497            String::from("my_class").into()
1498        );
1499        for variant in ProcessPermission::all_variants().into_iter() {
1500            assert_eq!(ObjectClass::Process, variant.class());
1501            assert_eq!("process", variant.class().name());
1502            let permission: Permission = variant.clone().into();
1503            assert_eq!(Permission::Process(variant.clone()), permission);
1504            assert_eq!(
1505                AbstractPermission::System(Permission::Process(variant.clone())),
1506                permission.into()
1507            );
1508            assert_eq!(AbstractObjectClass::System(ObjectClass::Process), variant.class().into());
1509        }
1510    }
1511
1512    #[test]
1513    fn nulless_byte_str_equivalence() {
1514        let unterminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0".into();
1515        let nul_terminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0\0".into();
1516        let nul_containing: NullessByteStr<'_> =
1517            b"u:object_r:test_valid_t:s0\0IGNORE THIS\0!\0".into();
1518
1519        for context in [nul_terminated, nul_containing] {
1520            assert_eq!(unterminated, context);
1521            assert_eq!(unterminated.as_bytes(), context.as_bytes());
1522        }
1523    }
1524}