selinux/
lib.rs

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