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