selinux/
lib.rs

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