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        Perfmon("perfmon"),
716        Syslog("syslog"),
717        WakeAlarm("wake_alarm"),
718
719        // keep-sorted end
720    }
721}
722
723class_permission_enum! {
724    /// A well-known "capability2" class permission in SELinux policy that has a particular meaning
725    /// in policy enforcement hooks.
726    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
727    Capability2Permission extends CommonCap2Permission {}
728}
729
730impl ForClass<Cap2Class> for CommonCap2Permission {
731    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
732    /// This is used to allow hooks to resolve e.g. common "mac_admin" permission access based on
733    /// the "allow" rules for the correct target object class.
734    fn for_class(&self, class: Cap2Class) -> KernelPermission {
735        match class {
736            Cap2Class::Capability2 => Capability2Permission::Common(self.clone()).into(),
737        }
738    }
739}
740
741common_permission_enum! {
742    /// Permissions meaningful for all [`crate::vfs::FsNode`]s, whether file- or socket-like.
743    ///
744    /// This extra layer of common permissions is not reflected in the hierarchy defined by the
745    /// SELinux Reference Policy. Because even common permissions are mapped per-class, by name, to
746    /// the policy equivalents, the implementation and policy notions of common permissions need not
747    /// be identical.
748    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
749    CommonFsNodePermission {
750        // keep-sorted start
751        /// Permission to append to a file or socket.
752        Append("append"),
753        /// Pseudo-permission used in `dontaudit` access-rules to allow access checks to be made
754        /// between specific sources & targets without generating audit logs.
755        AuditAccess("audit_access"),
756        /// Permission to create a file or socket.
757        Create("create"),
758        /// Permission to query attributes, including uid, gid and extended attributes.
759        GetAttr("getattr"),
760        /// Permission to execute ioctls on the file or socket.
761        Ioctl("ioctl"),
762        /// Permission to set and unset file or socket locks.
763        Lock("lock"),
764        /// Permission to map a file.
765        Map("map"),
766        /// Permission to read content from a file or socket, as well as reading or following links.
767        Read("read"),
768        /// Permission checked against the existing label when updating a node's security label.
769        RelabelFrom("relabelfrom"),
770        /// Permission checked against the new label when updating a node's security label.
771        RelabelTo("relabelto"),
772        /// Permission to modify attributes, including uid, gid and extended attributes.
773        SetAttr("setattr"),
774        /// Permission to write contents to the file or socket.
775        Write("write"),
776        // keep-sorted end
777    }
778}
779
780impl<T: Into<FsNodeClass>> ForClass<T> for CommonFsNodePermission {
781    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
782    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
783    /// "allow" rules for the correct target object class.
784    fn for_class(&self, class: T) -> KernelPermission {
785        match class.into() {
786            FsNodeClass::File(file_class) => {
787                CommonFilePermission::Common(self.clone()).for_class(file_class)
788            }
789            FsNodeClass::Socket(sock_class) => {
790                CommonSocketPermission::Common(self.clone()).for_class(sock_class)
791            }
792        }
793    }
794}
795common_permission_enum! {
796    /// Permissions common to all socket-like object classes. These are combined with a specific
797    /// `SocketClass` by policy enforcement hooks, to obtain class-affine permission values.
798    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
799    CommonSocketPermission extends CommonFsNodePermission {
800        // keep-sorted start
801        /// Permission to accept a connection.
802        Accept("accept"),
803        /// Permission to bind to a name.
804        Bind("bind"),
805        /// Permission to initiate a connection.
806        Connect("connect"),
807        /// Permission to get socket options.
808        GetOpt("getopt"),
809        /// Permission to listen for connections.
810        Listen("listen"),
811        /// Permission to send datagrams to the socket.
812        SendTo("sendto"),
813        /// Permission to set socket options.
814        SetOpt("setopt"),
815        /// Permission to terminate connection.
816        Shutdown("shutdown"),
817        // keep-sorted end
818    }
819}
820
821impl ForClass<SocketClass> for CommonSocketPermission {
822    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
823    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
824    /// "allow" rules for the correct target object class.
825    fn for_class(&self, class: SocketClass) -> KernelPermission {
826        match class {
827            SocketClass::Key => KeySocketPermission::Common(self.clone()).into(),
828            SocketClass::Netlink => NetlinkSocketPermission::Common(self.clone()).into(),
829            SocketClass::NetlinkAudit => NetlinkAuditSocketPermission::Common(self.clone()).into(),
830            SocketClass::NetlinkConnector => {
831                NetlinkConnectorSocketPermission::Common(self.clone()).into()
832            }
833            SocketClass::NetlinkCrypto => {
834                NetlinkCryptoSocketPermission::Common(self.clone()).into()
835            }
836            SocketClass::NetlinkDnrt => NetlinkDnrtSocketPermission::Common(self.clone()).into(),
837            SocketClass::NetlinkFibLookup => {
838                NetlinkFibLookupSocketPermission::Common(self.clone()).into()
839            }
840            SocketClass::NetlinkFirewall => {
841                NetlinkFirewallSocketPermission::Common(self.clone()).into()
842            }
843            SocketClass::NetlinkGeneric => {
844                NetlinkGenericSocketPermission::Common(self.clone()).into()
845            }
846            SocketClass::NetlinkIp6Fw => NetlinkIp6FwSocketPermission::Common(self.clone()).into(),
847            SocketClass::NetlinkIscsi => NetlinkIscsiSocketPermission::Common(self.clone()).into(),
848            SocketClass::NetlinkKobjectUevent => {
849                NetlinkKobjectUeventSocketPermission::Common(self.clone()).into()
850            }
851            SocketClass::NetlinkNetfilter => {
852                NetlinkNetfilterSocketPermission::Common(self.clone()).into()
853            }
854            SocketClass::NetlinkNflog => NetlinkNflogSocketPermission::Common(self.clone()).into(),
855            SocketClass::NetlinkRdma => NetlinkRdmaSocketPermission::Common(self.clone()).into(),
856            SocketClass::NetlinkRoute => NetlinkRouteSocketPermission::Common(self.clone()).into(),
857            SocketClass::NetlinkScsitransport => {
858                NetlinkScsitransportSocketPermission::Common(self.clone()).into()
859            }
860            SocketClass::NetlinkSelinux => {
861                NetlinkSelinuxSocketPermission::Common(self.clone()).into()
862            }
863            SocketClass::NetlinkTcpDiag => {
864                NetlinkTcpDiagSocketPermission::Common(self.clone()).into()
865            }
866            SocketClass::NetlinkXfrm => NetlinkXfrmSocketPermission::Common(self.clone()).into(),
867            SocketClass::Packet => PacketSocketPermission::Common(self.clone()).into(),
868            SocketClass::RawIp => RawIpSocketPermission::Common(self.clone()).into(),
869            SocketClass::Socket => SocketPermission::Common(self.clone()).into(),
870            SocketClass::Tcp => TcpSocketPermission::Common(self.clone()).into(),
871            SocketClass::Udp => UdpSocketPermission::Common(self.clone()).into(),
872            SocketClass::UnixDgram => UnixDgramSocketPermission::Common(self.clone()).into(),
873            SocketClass::UnixStream => UnixStreamSocketPermission::Common(self.clone()).into(),
874            SocketClass::Vsock => VsockSocketPermission::Common(self.clone()).into(),
875        }
876    }
877}
878
879class_permission_enum! {
880    /// A well-known "key_socket" class permission in SELinux policy that has a particular meaning in
881    /// policy enforcement hooks.
882    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
883    KeySocketPermission extends CommonSocketPermission {
884    }
885}
886class_permission_enum! {
887    /// A well-known "netlink_socket" class permission in SELinux policy that has a particular meaning in
888    /// policy enforcement hooks.
889    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
890    NetlinkSocketPermission extends CommonSocketPermission {
891    }
892}
893
894class_permission_enum! {
895    /// A well-known "netlink_route_socket" class permission in SELinux policy that has a particular meaning in
896    /// policy enforcement hooks.
897    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
898    NetlinkRouteSocketPermission extends CommonSocketPermission {
899        // keep-sorted start
900        /// Permission for nlmsg xperms.
901        Nlmsg("nlmsg"),
902        /// Permission to read the kernel routing table.
903        NlmsgRead("nlmsg_read"),
904        /// Permission to write to the kernel routing table.
905        NlmsgWrite("nlmsg_write"),
906        // keep-sorted end
907    }
908}
909
910class_permission_enum! {
911    /// A well-known "netlink_firewall_socket" class permission in SELinux policy that has a particular meaning in
912    /// policy enforcement hooks.
913    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
914    NetlinkFirewallSocketPermission extends CommonSocketPermission {
915    }
916}
917
918class_permission_enum! {
919    /// A well-known "netlink_tcpdiag_socket" class permission in SELinux policy that has a particular meaning in
920    /// policy enforcement hooks.
921    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
922    NetlinkTcpDiagSocketPermission extends CommonSocketPermission {
923        // keep-sorted start
924        /// Permission for nlmsg xperms.
925        Nlmsg("nlmsg"),
926        /// Permission to request information about a protocol.
927        NlmsgRead("nlmsg_read"),
928        /// Permission to write netlink message.
929        NlmsgWrite("nlmsg_write"),
930        // keep-sorted end
931    }
932}
933
934class_permission_enum! {
935    /// A well-known "netlink_nflog_socket" class permission in SELinux policy that has a particular meaning in
936    /// policy enforcement hooks.
937    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
938    NetlinkNflogSocketPermission extends CommonSocketPermission {
939    }
940}
941
942class_permission_enum! {
943    /// A well-known "netlink_xfrm_socket" class permission in SELinux policy that has a particular meaning in
944    /// policy enforcement hooks.
945    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
946    NetlinkXfrmSocketPermission extends CommonSocketPermission {
947        // keep-sorted start
948        /// Permission for nlmsg xperms.
949        Nlmsg("nlmsg"),
950        /// Permission to get IPSec configuration information.
951        NlmsgRead("nlmsg_read"),
952        /// Permission to set IPSec configuration information.
953        NlmsgWrite("nlmsg_write"),
954        // keep-sorted end
955    }
956}
957
958class_permission_enum! {
959    /// A well-known "netlink_selinux_socket" class permission in SELinux policy that has a particular meaning in
960    /// policy enforcement hooks.
961    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
962    NetlinkSelinuxSocketPermission extends CommonSocketPermission {
963    }
964}
965
966class_permission_enum! {
967    /// A well-known "netlink_iscsi_socket" class permission in SELinux policy that has a particular meaning in
968    /// policy enforcement hooks.
969    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
970    NetlinkIscsiSocketPermission extends CommonSocketPermission {
971    }
972}
973
974class_permission_enum! {
975    /// A well-known "netlink_audit_socket" class permission in SELinux policy that has a particular meaning in
976    /// policy enforcement hooks.
977    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
978    NetlinkAuditSocketPermission extends CommonSocketPermission {
979        // keep-sorted start
980        /// Permission for nlmsg xperms.
981        Nlmsg("nlmsg"),
982        /// Permission to query status of audit service.
983        NlmsgRead("nlmsg_read"),
984        /// Permission to list auditing configuration rules.
985        NlmsgReadPriv("nlmsg_readpriv"),
986        /// Permission to send userspace audit messages to the audit service.
987        NlmsgRelay("nlmsg_relay"),
988        /// Permission to control TTY auditing.
989        NlmsgTtyAudit("nlmsg_tty_audit"),
990        /// Permission to update the audit service configuration.
991        NlmsgWrite("nlmsg_write"),
992        // keep-sorted end
993    }
994}
995
996class_permission_enum! {
997    /// A well-known "netlink_fib_lookup_socket" class permission in SELinux policy that has a particular meaning in
998    /// policy enforcement hooks.
999    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1000    NetlinkFibLookupSocketPermission extends CommonSocketPermission {
1001    }
1002}
1003
1004class_permission_enum! {
1005    /// A well-known "netlink_connector_socket" class permission in SELinux policy that has a particular meaning in
1006    /// policy enforcement hooks.
1007    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1008    NetlinkConnectorSocketPermission extends CommonSocketPermission {
1009    }
1010}
1011
1012class_permission_enum! {
1013    /// A well-known "netlink_netfilter_socket" class permission in SELinux policy that has a particular meaning in
1014    /// policy enforcement hooks.
1015    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1016    NetlinkNetfilterSocketPermission extends CommonSocketPermission {
1017    }
1018}
1019
1020class_permission_enum! {
1021    /// A well-known "netlink_ip6fw_socket" class permission in SELinux policy that has a particular meaning in
1022    /// policy enforcement hooks.
1023    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1024    NetlinkIp6FwSocketPermission extends CommonSocketPermission {
1025    }
1026}
1027
1028class_permission_enum! {
1029    /// A well-known "netlink_dnrt_socket" class permission in SELinux policy that has a particular meaning in
1030    /// policy enforcement hooks.
1031    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1032    NetlinkDnrtSocketPermission extends CommonSocketPermission {
1033    }
1034}
1035
1036class_permission_enum! {
1037    /// A well-known "netlink_kobject_uevent_socket" class permission in SELinux policy that has a particular meaning in
1038    /// policy enforcement hooks.
1039    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1040    NetlinkKobjectUeventSocketPermission extends CommonSocketPermission {
1041    }
1042}
1043
1044class_permission_enum! {
1045    /// A well-known "netlink_generic_socket" class permission in SELinux policy that has a particular meaning in
1046    /// policy enforcement hooks.
1047    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1048    NetlinkGenericSocketPermission extends CommonSocketPermission {
1049    }
1050}
1051
1052class_permission_enum! {
1053    /// A well-known "netlink_scsitransport_socket" class permission in SELinux policy that has a particular meaning in
1054    /// policy enforcement hooks.
1055    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1056    NetlinkScsitransportSocketPermission extends CommonSocketPermission {
1057    }
1058}
1059
1060class_permission_enum! {
1061    /// A well-known "netlink_rdma_socket" class permission in SELinux policy that has a particular meaning in
1062    /// policy enforcement hooks.
1063    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1064    NetlinkRdmaSocketPermission extends CommonSocketPermission {
1065    }
1066}
1067
1068class_permission_enum! {
1069    /// A well-known "netlink_crypto_socket" class permission in SELinux policy that has a particular meaning in
1070    /// policy enforcement hooks.
1071    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1072    NetlinkCryptoSocketPermission extends CommonSocketPermission {
1073    }
1074}
1075
1076class_permission_enum! {
1077    /// A well-known "packet_socket" class permission in SELinux policy that has a particular meaning in
1078    /// policy enforcement hooks.
1079    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1080    PacketSocketPermission extends CommonSocketPermission {
1081    }
1082}
1083
1084class_permission_enum! {
1085    /// A well-known "rawip_socket" class permission in SELinux policy that has a particular meaning in
1086    /// policy enforcement hooks.
1087    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1088    RawIpSocketPermission extends CommonSocketPermission {
1089    }
1090}
1091
1092class_permission_enum! {
1093    /// A well-known "socket" class permission in SELinux policy that has a particular meaning in
1094    /// policy enforcement hooks.
1095    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1096    SocketPermission extends CommonSocketPermission {
1097    }
1098}
1099
1100class_permission_enum! {
1101    /// A well-known "tcp_socket" class permission in SELinux policy that has a particular meaning in
1102    /// policy enforcement hooks.
1103    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1104    TcpSocketPermission extends CommonSocketPermission {
1105    }
1106}
1107
1108class_permission_enum! {
1109    /// A well-known "udp_socket" class permission in SELinux policy that has a particular meaning in
1110    /// policy enforcement hooks.
1111    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1112    UdpSocketPermission extends CommonSocketPermission {
1113    }
1114}
1115
1116class_permission_enum! {
1117    /// A well-known "unix_stream_socket" class permission in SELinux policy that has a particular meaning in
1118    /// policy enforcement hooks.
1119    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1120    UnixStreamSocketPermission extends CommonSocketPermission {
1121        // keep-sorted start
1122        /// Permission to connect a streaming Unix-domain socket.
1123        ConnectTo("connectto"),
1124        // keep-sorted end
1125    }
1126}
1127
1128class_permission_enum! {
1129    /// A well-known "unix_dgram_socket" class permission in SELinux policy that has a particular meaning in
1130    /// policy enforcement hooks.
1131    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1132    UnixDgramSocketPermission extends CommonSocketPermission {
1133    }
1134}
1135
1136class_permission_enum! {
1137    /// A well-known "vsock_socket" class permission in SELinux policy that has a particular meaning in
1138    /// policy enforcement hooks.
1139    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1140    VsockSocketPermission extends CommonSocketPermission {
1141    }
1142}
1143
1144common_permission_enum! {
1145    /// Permissions common to all file-like object classes (e.g. "lnk_file", "dir"). These are
1146    /// combined with a specific `FileClass` by policy enforcement hooks, to obtain class-affine
1147    /// permission values to check.
1148    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1149    CommonFilePermission extends CommonFsNodePermission {
1150        // keep-sorted start
1151        /// Permission to execute a file with domain transition.
1152        Execute("execute"),
1153        /// Permissions to create hard link.
1154        Link("link"),
1155        /// Permission to use as mount point; only useful for directories and files.
1156        MountOn("mounton"),
1157        /// Permission to open a file.
1158        Open("open"),
1159        /// Permission to rename a file.
1160        Rename("rename"),
1161        /// Permission to delete a file or remove a hard link.
1162        Unlink("unlink"),
1163        // keep-sorted end
1164    }
1165}
1166
1167impl ForClass<FileClass> for CommonFilePermission {
1168    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
1169    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
1170    /// "allow" rules for the correct target object class.
1171    fn for_class(&self, class: FileClass) -> KernelPermission {
1172        match class {
1173            FileClass::AnonFsNode => AnonFsNodePermission::Common(self.clone()).into(),
1174            FileClass::Block => BlockFilePermission::Common(self.clone()).into(),
1175            FileClass::Character => CharacterFilePermission::Common(self.clone()).into(),
1176            FileClass::Dir => DirPermission::Common(self.clone()).into(),
1177            FileClass::Fifo => FifoFilePermission::Common(self.clone()).into(),
1178            FileClass::File => FilePermission::Common(self.clone()).into(),
1179            FileClass::Link => LinkFilePermission::Common(self.clone()).into(),
1180            FileClass::SockFile => SockFilePermission::Common(self.clone()).into(),
1181        }
1182    }
1183}
1184
1185class_permission_enum! {
1186    /// A well-known "anon_file" class permission used to manage special file-like nodes not linked
1187    /// into any directory structures.
1188    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1189    AnonFsNodePermission extends CommonFilePermission {
1190    }
1191}
1192
1193class_permission_enum! {
1194    /// A well-known "binder" class permission in SELinux policy that has a particular meaning in
1195    /// policy enforcement hooks.
1196    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1197    BinderPermission {
1198        // keep-sorted start
1199        /// Permission to perform a binder IPC to a given target process.
1200        Call("call"),
1201        /// Permission to use a Binder connection created with a different security context.
1202        Impersonate("impersonate"),
1203        /// Permission to set oneself as a context manager.
1204        SetContextMgr("set_context_mgr"),
1205        /// Permission to transfer Binder objects as part of a Binder transaction.
1206        Transfer("transfer"),
1207        // keep-sorted end
1208    }
1209}
1210
1211class_permission_enum! {
1212    /// A well-known "blk_file" class permission in SELinux policy that has a particular meaning in
1213    /// policy enforcement hooks.
1214    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1215    BlockFilePermission extends CommonFilePermission {
1216    }
1217}
1218
1219class_permission_enum! {
1220    /// A well-known "chr_file" class permission in SELinux policy that has a particular meaning in
1221    /// policy enforcement hooks.
1222    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1223    CharacterFilePermission extends CommonFilePermission {
1224    }
1225}
1226
1227class_permission_enum! {
1228    /// A well-known "dir" class permission in SELinux policy that has a particular meaning in
1229    /// policy enforcement hooks.
1230    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1231    DirPermission extends CommonFilePermission {
1232        // keep-sorted start
1233        /// Permission to add a file to the directory.
1234        AddName("add_name"),
1235        /// Permission to remove a directory.
1236        RemoveDir("rmdir"),
1237        /// Permission to remove an entry from a directory.
1238        RemoveName("remove_name"),
1239        /// Permission to change parent directory.
1240        Reparent("reparent"),
1241        /// Search access to the directory.
1242        Search("search"),
1243        // keep-sorted end
1244    }
1245}
1246
1247class_permission_enum! {
1248    /// A well-known "fd" class permission in SELinux policy that has a particular meaning in policy
1249    /// enforcement hooks.
1250    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1251    FdPermission {
1252        // keep-sorted start
1253        /// Permission to use file descriptors copied/retained/inherited from another security
1254        /// context. This permission is generally used to control whether an `exec*()` call from a
1255        /// cloned process that retained a copy of the file descriptor table should succeed.
1256        Use("use"),
1257        // keep-sorted end
1258    }
1259}
1260
1261class_permission_enum! {
1262    /// A well-known "bpf" class permission in SELinux policy that has a particular meaning in
1263    /// policy enforcement hooks.
1264    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1265    BpfPermission {
1266        // keep-sorted start
1267        /// Permission to create a map.
1268        MapCreate("map_create"),
1269        /// Permission to read from a map.
1270        MapRead("map_read"),
1271        /// Permission to write on a map.
1272        MapWrite("map_write"),
1273        /// Permission to load a program.
1274        ProgLoad("prog_load"),
1275        /// Permission to run a program.
1276        ProgRun("prog_run"),
1277        // keep-sorted end
1278    }
1279}
1280
1281class_permission_enum! {
1282    /// A well-known "perf_event" class permission in SELinux policy that has a particular meaning
1283    /// in policy hooks.
1284    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1285    PerfEventPermission {
1286        // keep-sorted start
1287        /// Permission to monitor the cpu.
1288        Cpu("cpu"),
1289        /// Permission to monitor the kernel.
1290        Kernel("kernel"),
1291        /// Permission to open a perf event.
1292        Open("open"),
1293        /// Permission to read a perf event.
1294        Read("read"),
1295        /// Permission to set tracepoints.
1296        Tracepoint("tracepoint"),
1297        /// Permission to write a perf event.
1298        Write("write"),
1299        // keep-sorted end
1300    }
1301}
1302
1303class_permission_enum! {
1304    /// A well-known "fifo_file" class permission in SELinux policy that has a particular meaning in
1305    /// policy enforcement hooks.
1306    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1307    FifoFilePermission extends CommonFilePermission {
1308    }
1309}
1310
1311class_permission_enum! {
1312    /// A well-known "file" class permission in SELinux policy that has a particular meaning in
1313    /// policy enforcement hooks.
1314    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1315    FilePermission extends CommonFilePermission {
1316        // keep-sorted start
1317        /// Permission to use a file as an entry point into the new domain on transition.
1318        Entrypoint("entrypoint"),
1319        /// Permission to use a file as an entry point to the calling domain without performing a
1320        /// transition.
1321        ExecuteNoTrans("execute_no_trans"),
1322        // keep-sorted end
1323    }
1324}
1325
1326class_permission_enum! {
1327    /// A well-known "filesystem" class permission in SELinux policy that has a particular meaning in
1328    /// policy enforcement hooks.
1329    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1330    FileSystemPermission {
1331        // keep-sorted start
1332        /// Permission to associate a file to the filesystem.
1333        Associate("associate"),
1334        /// Permission to get filesystem attributes.
1335        GetAttr("getattr"),
1336        /// Permission mount a filesystem.
1337        Mount("mount"),
1338        /// Permission to remount a filesystem with different flags.
1339        Remount("remount"),
1340        /// Permission to unmount a filesystem.
1341        Unmount("unmount"),
1342        // keep-sorted end
1343    }
1344}
1345
1346class_permission_enum! {
1347    /// A well-known "lnk_file" class permission in SELinux policy that has a particular meaning in
1348    /// policy enforcement hooks.
1349    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1350    LinkFilePermission extends CommonFilePermission {
1351    }
1352}
1353
1354class_permission_enum! {
1355    /// A well-known "sock_file" class permission in SELinux policy that has a particular meaning in
1356    /// policy enforcement hooks.
1357    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1358    SockFilePermission extends CommonFilePermission {
1359    }
1360}
1361
1362class_permission_enum! {
1363    /// A well-known "process" class permission in SELinux policy that has a particular meaning in
1364    /// policy enforcement hooks.
1365    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1366    ProcessPermission {
1367        // keep-sorted start
1368        /// Permission to dynamically transition a process to a different security domain.
1369        DynTransition("dyntransition"),
1370        /// Permission to execute arbitrary code from the heap.
1371        ExecHeap("execheap"),
1372        /// Permission to execute arbitrary code from memory.
1373        ExecMem("execmem"),
1374        /// Permission to execute arbitrary code from the stack.
1375        ExecStack("execstack"),
1376        /// Permission to fork the current running process.
1377        Fork("fork"),
1378        /// Permission to get the process group ID.
1379        GetPgid("getpgid"),
1380        /// Permission to get the resource limits on a process.
1381        GetRlimit("getrlimit"),
1382        /// Permission to get scheduling policy currently applied to a process.
1383        GetSched("getsched"),
1384        /// Permission to get the session ID.
1385        GetSession("getsession"),
1386        /// Permission to trace a process.
1387        Ptrace("ptrace"),
1388        /// Permission to inherit the parent process's resource limits on exec.
1389        RlimitInh("rlimitinh"),
1390        /// Permission to set the calling task's current Security Context.
1391        /// The "dyntransition" permission separately limits which Contexts "setcurrent" may be used to transition to.
1392        SetCurrent("setcurrent"),
1393        /// Permission to set the Security Context used by `exec()`.
1394        SetExec("setexec"),
1395        /// Permission to set the Security Context used when creating filesystem objects.
1396        SetFsCreate("setfscreate"),
1397        /// Permission to set the Security Context used when creating kernel keyrings.
1398        SetKeyCreate("setkeycreate"),
1399        /// Permission to set the process group ID.
1400        SetPgid("setpgid"),
1401        /// Permission to set the resource limits on a process.
1402        SetRlimit("setrlimit"),
1403        /// Permission to set scheduling policy for a process.
1404        SetSched("setsched"),
1405        /// Permission to set the Security Context used when creating new labeled sockets.
1406        SetSockCreate("setsockcreate"),
1407        /// Permission to share resources (e.g. FD table, address-space, etc) with a process.
1408        Share("share"),
1409        /// Permission to send SIGCHLD to a process.
1410        SigChld("sigchld"),
1411        /// Permission to inherit the parent process's signal state.
1412        SigInh("siginh"),
1413        /// Permission to send SIGKILL to a process.
1414        SigKill("sigkill"),
1415        /// Permission to send SIGSTOP to a process.
1416        SigStop("sigstop"),
1417        /// Permission to send a signal other than SIGKILL, SIGSTOP, or SIGCHLD to a process.
1418        Signal("signal"),
1419        /// Permission to transition to a different security domain.
1420        Transition("transition"),
1421        // keep-sorted end
1422    }
1423}
1424
1425class_permission_enum! {
1426    /// A well-known "security" class permission in SELinux policy, used to control access to
1427    /// sensitive administrative and query API surfaces in the "selinuxfs".
1428    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1429    SecurityPermission {
1430        // keep-sorted start
1431        /// Permission to validate Security Context using the "context" API.
1432        CheckContext("check_context"),
1433        /// Permission to compute access vectors via the "access" API.
1434        ComputeAv("compute_av"),
1435        /// Permission to compute security contexts based on `type_transition` rules via "create".
1436        ComputeCreate("compute_create"),
1437        /// Permission to compute security contexts based on `type_member` rules via "member".
1438        ComputeMember("compute_member"),
1439        /// Permission to compute security contexts based on `type_change` rules via "relabel".
1440        ComputeRelabel("compute_relabel"),
1441        /// Permission to compute user decisions via "user".
1442        ComputeUser("compute_user"),
1443        /// Permission to load a new binary policy into the kernel via the "load" API.
1444        LoadPolicy("load_policy"),
1445        /// Permission to commit booleans to control conditional elements of the policy.
1446        SetBool("setbool"),
1447        /// Permission to change the way permissions are validated for `mmap()` operations.
1448        SetCheckReqProt("setcheckreqprot"),
1449        /// Permission to switch the system between permissive and enforcing modes, via "enforce".
1450        SetEnforce("setenforce"),
1451        // keep-sorted end
1452     }
1453}
1454
1455class_permission_enum! {
1456    /// A well-known "system" class permission in SELinux policy, used to control access to
1457    /// sensitive administrative and query API surfaces in the "selinuxfs".
1458    #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1459    SystemPermission {
1460        // keep-sorted start
1461        /// Permission to use the syslog(2) CONSOLE action types.
1462        SyslogConsole("syslog_console"),
1463        /// Permission to use other syslog(2) action types.
1464        SyslogMod("syslog_mod"),
1465        /// Permission to use the syslog(2) READ_ALL related action types.
1466        SyslogRead("syslog_read"),
1467        // keep-sorted end
1468     }
1469}
1470
1471/// Initial Security Identifier (SID) values defined by the SELinux Reference Policy.
1472/// Where the SELinux Reference Policy retains definitions for some deprecated initial SIDs, this
1473/// enum omits deprecated entries for clarity.
1474#[repr(u64)]
1475enum ReferenceInitialSid {
1476    Kernel = 1,
1477    Security = 2,
1478    Unlabeled = 3,
1479    _Fs = 4,
1480    File = 5,
1481    _Port = 9,
1482    _Netif = 10,
1483    _Netmsg = 11,
1484    _Node = 12,
1485    _Sysctl = 17,
1486    Devnull = 27,
1487
1488    FirstUnused,
1489}
1490
1491/// Lowest Security Identifier value guaranteed not to be used by this
1492/// implementation to refer to an initial Security Context.
1493pub const FIRST_UNUSED_SID: u32 = ReferenceInitialSid::FirstUnused as u32;
1494
1495macro_rules! initial_sid_enum {
1496    ($(#[$meta:meta])* $name:ident {
1497        $($(#[$variant_meta:meta])* $variant:ident ($variant_name: literal)),*,
1498    }) => {
1499        $(#[$meta])*
1500        pub enum $name {
1501            $($(#[$variant_meta])* $variant = ReferenceInitialSid::$variant as isize),*
1502        }
1503
1504        impl $name {
1505            pub fn all_variants() -> &'static [Self] {
1506                &[
1507                    $($name::$variant),*
1508                ]
1509            }
1510
1511            pub fn name(&self) -> &'static str {
1512                match self {
1513                    $($name::$variant => $variant_name),*
1514                }
1515            }
1516        }
1517    }
1518}
1519
1520initial_sid_enum! {
1521/// Initial Security Identifier (SID) values actually used by this implementation.
1522/// These must be present in the policy, for it to be valid.
1523#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1524    InitialSid {
1525        // keep-sorted start
1526        Devnull("devnull"),
1527        File("file"),
1528        Kernel("kernel"),
1529        Security("security"),
1530        Unlabeled("unlabeled"),
1531        // keep-sorted end
1532    }
1533}
1534
1535/// A borrowed byte slice that contains no `NUL` characters by truncating the input slice at the
1536/// first `NUL` (if any) upon construction.
1537#[derive(Clone, Copy, Debug, PartialEq)]
1538pub struct NullessByteStr<'a>(&'a [u8]);
1539
1540impl<'a> NullessByteStr<'a> {
1541    /// Returns a non-null-terminated representation of the security context string.
1542    pub fn as_bytes(&self) -> &[u8] {
1543        &self.0
1544    }
1545}
1546
1547impl<'a, S: AsRef<[u8]> + ?Sized> From<&'a S> for NullessByteStr<'a> {
1548    /// Any `AsRef<[u8]>` can be processed into a [`NullessByteStr`]. The [`NullessByteStr`] will
1549    /// retain everything up to (but not including) a null character, or else the complete byte
1550    /// string.
1551    fn from(s: &'a S) -> Self {
1552        let value = s.as_ref();
1553        match value.iter().position(|c| *c == 0) {
1554            Some(end) => Self(&value[..end]),
1555            None => Self(value),
1556        }
1557    }
1558}
1559
1560#[derive(Clone, Debug, PartialEq)]
1561pub struct FileSystemMountSids {
1562    pub context: Option<SecurityId>,
1563    pub fs_context: Option<SecurityId>,
1564    pub def_context: Option<SecurityId>,
1565    pub root_context: Option<SecurityId>,
1566}
1567
1568#[derive(Clone, Debug, PartialEq)]
1569pub struct FileSystemLabel {
1570    pub sid: SecurityId,
1571    pub scheme: FileSystemLabelingScheme,
1572    // Sids obtained by parsing the mount options of the FileSystem.
1573    pub mount_sids: FileSystemMountSids,
1574}
1575
1576#[derive(Clone, Debug, PartialEq)]
1577pub enum FileSystemLabelingScheme {
1578    /// This filesystem was mounted with "context=".
1579    Mountpoint { sid: SecurityId },
1580    /// This filesystem has an "fs_use_xattr", "fs_use_task", or "fs_use_trans" entry in the
1581    /// policy. If the `fs_use_type` is "fs_use_xattr" then the `default_sid` specifies the SID
1582    /// with which to label `FsNode`s of files that do not have the "security.selinux" xattr.
1583    FsUse { fs_use_type: FsUseType, default_sid: SecurityId },
1584    /// This filesystem has one or more "genfscon" statements associated with it in the policy.
1585    GenFsCon,
1586}
1587
1588/// SELinux security context-related filesystem mount options. These options are documented in the
1589/// `context=context, fscontext=context, defcontext=context, and rootcontext=context` section of
1590/// the `mount(8)` manpage.
1591#[derive(Clone, Debug, Default, PartialEq)]
1592pub struct FileSystemMountOptions {
1593    /// Specifies the effective security context to use for all nodes in the filesystem, and the
1594    /// filesystem itself. If the filesystem already contains security attributes then these are
1595    /// ignored. May not be combined with any of the other options.
1596    pub context: Option<Vec<u8>>,
1597    /// Specifies an effective security context to use for un-labeled nodes in the filesystem,
1598    /// rather than falling-back to the policy-defined "file" context.
1599    pub def_context: Option<Vec<u8>>,
1600    /// The value of the `fscontext=[security-context]` mount option. This option is used to
1601    /// label the filesystem (superblock) itself.
1602    pub fs_context: Option<Vec<u8>>,
1603    /// The value of the `rootcontext=[security-context]` mount option. This option is used to
1604    /// (re)label the inode located at the filesystem mountpoint.
1605    pub root_context: Option<Vec<u8>>,
1606}
1607
1608/// Status information parameter for the [`SeLinuxStatusPublisher`] interface.
1609pub struct SeLinuxStatus {
1610    /// SELinux-wide enforcing vs. permissive mode  bit.
1611    pub is_enforcing: bool,
1612    /// Number of times the policy has been changed since SELinux started.
1613    pub change_count: u32,
1614    /// Bit indicating whether operations unknown SELinux abstractions will be denied.
1615    pub deny_unknown: bool,
1616}
1617
1618/// Interface for security server to interact with selinuxfs status file.
1619pub trait SeLinuxStatusPublisher: Send + Sync {
1620    /// Sets the value part of the associated selinuxfs status file.
1621    fn set_status(&mut self, policy_status: SeLinuxStatus);
1622}
1623
1624#[cfg(test)]
1625mod tests {
1626    use super::*;
1627
1628    #[test]
1629    fn object_class_permissions() {
1630        let test_class_id = ClassId::new(NonZeroU32::new(20).unwrap());
1631        assert_eq!(ObjectClass::ClassId(test_class_id), test_class_id.into());
1632        for variant in ProcessPermission::all_variants().into_iter() {
1633            assert_eq!(KernelClass::Process, variant.class());
1634            assert_eq!("process", variant.class().name());
1635            let permission: KernelPermission = variant.clone().into();
1636            assert_eq!(KernelPermission::Process(variant.clone()), permission);
1637            assert_eq!(ObjectClass::Kernel(KernelClass::Process), variant.class().into());
1638        }
1639    }
1640
1641    #[test]
1642    fn nulless_byte_str_equivalence() {
1643        let unterminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0".into();
1644        let nul_terminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0\0".into();
1645        let nul_containing: NullessByteStr<'_> =
1646            b"u:object_r:test_valid_t:s0\0IGNORE THIS\0!\0".into();
1647
1648        for context in [nul_terminated, nul_containing] {
1649            assert_eq!(unterminated, context);
1650            assert_eq!(unterminated.as_bytes(), context.as_bytes());
1651        }
1652    }
1653}