Skip to main content

selinux/
kernel_permissions.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
5use crate::policy::AccessVector;
6use paste::paste;
7use strum_macros::VariantArray;
8
9/// Declares an `enum` with a `name()` method that returns the name for the given variant.
10macro_rules! named_enum {
11    ($(#[$meta:meta])* $name:ident {
12        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
13    }) => {
14        $(#[$meta])*
15        pub enum $name  {
16            $($(#[$variant_meta])* $variant,)*
17        }
18
19        impl $name {
20            pub fn name(&self) -> &'static str {
21                match self {
22                    $($name::$variant => $variant_name,)*
23                }
24            }
25        }
26    }
27}
28
29/// Declares an `enum` with the specified subset of values from an existing enum.
30macro_rules! subset_enum {
31    ($(#[$meta:meta])* $name:ident from $existing_enum:ident {
32        $($(#[$variant_meta:meta])* $variant:ident,)*
33    }) => {
34        $(#[$meta])*
35        pub enum $name {
36            $($(#[$variant_meta])* $variant = $existing_enum::$variant as isize,)*
37        }
38
39        impl From<$name> for $existing_enum {
40            fn from(other: $name) -> Self {
41                match other {
42                    $($name::$variant => Self::$variant,)*
43                }
44            }
45        }
46    }
47}
48
49macro_rules! declare_kernel_classes {
50    ($(#[$meta:meta])* {
51        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
52    }) => {
53        named_enum! {
54            #[derive(VariantArray, zerocopy::IntoBytes, zerocopy::Immutable)]
55            $(#[$meta])* KernelClass {
56                $($(#[$variant_meta])* $variant ($variant_name),)*
57            }
58        }
59
60        paste! {
61            $(#[$meta])*
62            pub enum KernelPermission {
63                $($(#[$variant_meta])* $variant([<$variant Permission>]),)*
64            }
65
66            $(impl From<[<$variant Permission>]> for KernelPermission {
67                fn from(v: [<$variant Permission>]) -> Self {
68                    Self::$variant(v)
69                }
70            }
71            )*
72
73            impl ClassPermission for KernelPermission {
74                fn class(&self) -> KernelClass {
75                    match self {
76                        $(KernelPermission::$variant(_) => KernelClass::$variant),*
77                    }
78                }
79                fn id(&self) -> u8 {
80                    match self {
81                        $(KernelPermission::$variant(v) => v.id()),*
82                    }
83                }
84            }
85
86            impl KernelPermission {
87                pub fn name(&self) -> &'static str {
88                    match self {
89                        $(KernelPermission::$variant(v) => v.name()),*
90                    }
91                }
92
93                pub fn all_variants() -> impl Iterator<Item = Self> {
94                    let iter = [].iter().map(Clone::clone);
95                    $(
96                        let iter = iter.chain([<$variant Permission>]::PERMISSIONS.iter().map(Clone::clone));
97                    )*
98                    iter
99                }
100            }
101
102            impl KernelClass {
103                pub const fn permissions(&self) -> &'static [KernelPermission] {
104                    match *self {
105                        $(KernelClass::$variant => [<$variant Permission>]::PERMISSIONS,)*
106                    }
107                }
108            }
109        }
110    }
111}
112
113declare_kernel_classes! {
114    /// A well-known class in SELinux policy that has a particular meaning in policy enforcement
115    /// hooks.
116    #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
117    #[repr(u32)]
118    {
119        // keep-sorted start
120        /// The SELinux "anon_inode" object class.
121        AnonFsNode("anon_inode"),
122        /// The SELinux "binder" object class.
123        Binder("binder"),
124        /// The SELinux "blk_file" object class.
125        BlkFile("blk_file"),
126        /// The SELinux "bpf" object class.
127        Bpf("bpf"),
128        /// The SELinux "capability" object class.
129        Capability("capability"),
130        /// The SELinux "capability2" object class.
131        Capability2("capability2"),
132        /// The SELinux "chr_file" object class.
133        ChrFile("chr_file"),
134        /// The SELinux "dir" object class.
135        Dir("dir"),
136        /// The SELinux "fd" object class.
137        Fd("fd"),
138        /// The SELinux "fifo_file" object class.
139        FifoFile("fifo_file"),
140        /// The SELinux "file" object class.
141        File("file"),
142        /// The SELinux "filesystem" object class.
143        FileSystem("filesystem"),
144        /// "icmp_socket" class enabled via the "extended_socket_class" policy capability.
145        IcmpSocket("icmp_socket"),
146        /// The SELinux "key_socket" object class.
147        KeySocket("key_socket"),
148        /// The SELinux "lnk_file" object class.
149        LnkFile("lnk_file"),
150        /// The SELinux "memfd_file" object class.
151        MemFdFile("memfd_file"),
152        /// The SELinux "netlink_audit_socket" object class.
153        NetlinkAuditSocket("netlink_audit_socket"),
154        /// The SELinux "netlink_connector_socket" object class.
155        NetlinkConnectorSocket("netlink_connector_socket"),
156        /// The SELinux "netlink_crypto_socket" object class.
157        NetlinkCryptoSocket("netlink_crypto_socket"),
158        /// The SELinux "netlink_dnrt_socket" object class.
159        NetlinkDnrtSocket("netlink_dnrt_socket"),
160        /// The SELinux "netlink_fib_lookup_socket" object class.
161        NetlinkFibLookupSocket("netlink_fib_lookup_socket"),
162        /// The SELinux "netlink_firewall_socket" object class.
163        NetlinkFirewallSocket("netlink_firewall_socket"),
164        /// The SELinux "netlink_generic_socket" object class.
165        NetlinkGenericSocket("netlink_generic_socket"),
166        /// The SELinux "netlink_ip6fw_socket" object class.
167        NetlinkIp6FwSocket("netlink_ip6fw_socket"),
168        /// The SELinux "netlink_iscsi_socket" object class.
169        NetlinkIscsiSocket("netlink_iscsi_socket"),
170        /// The SELinux "netlink_kobject_uevent_socket" object class.
171        NetlinkKobjectUeventSocket("netlink_kobject_uevent_socket"),
172        /// The SELinux "netlink_netfilter_socket" object class.
173        NetlinkNetfilterSocket("netlink_netfilter_socket"),
174        /// The SELinux "netlink_nflog_socket" object class.
175        NetlinkNflogSocket("netlink_nflog_socket"),
176        /// The SELinux "netlink_rdma_socket" object class.
177        NetlinkRdmaSocket("netlink_rdma_socket"),
178        /// The SELinux "netlink_route_socket" object class.
179        NetlinkRouteSocket("netlink_route_socket"),
180        /// The SELinux "netlink_scsitransport_socket" object class.
181        NetlinkScsitransportSocket("netlink_scsitransport_socket"),
182        /// The SELinux "netlink_selinux_socket" object class.
183        NetlinkSelinuxSocket("netlink_selinux_socket"),
184        /// The SELinux "netlink_socket" object class.
185        NetlinkSocket("netlink_socket"),
186        /// The SELinux "netlink_tcpdiag_socket" object class.
187        NetlinkTcpDiagSocket("netlink_tcpdiag_socket"),
188        /// The SELinux "netlink_xfrm_socket" object class.
189        NetlinkXfrmSocket("netlink_xfrm_socket"),
190        /// The SELinux "packet_socket" object class.
191        PacketSocket("packet_socket"),
192        /// The SELinux "perf_event" object class.
193        PerfEvent("perf_event"),
194        /// The SELinux "process" object class.
195        Process("process"),
196        /// The SELinux "process2" object class.
197        Process2("process2"),
198        /// The SELinux "qipcrtr_socket" object class.
199        QipcrtrSocket("qipcrtr_socket"),
200        /// The SELinux "rawip_socket" object class.
201        RawIpSocket("rawip_socket"),
202        /// "sctp_socket" class enabled via the "extended_socket_class" policy capability.
203        SctpSocket("sctp_socket"),
204        /// The SELinux "security" object class.
205        Security("security"),
206        /// The SELinux "sock_file" object class.
207        SockFile("sock_file"),
208        /// The SELinux "socket" object class.
209        Socket("socket"),
210        /// The SELinux "system" object class.
211        System("system"),
212        /// The SELinux "tcp_socket" object class.
213        TcpSocket("tcp_socket"),
214        /// The SELinux "tun_socket" object class.
215        TunSocket("tun_socket"),
216        /// The SELinux "udp_socket" object class.
217        UdpSocket("udp_socket"),
218        /// The SELinux "unix_dgram_socket" object class.
219        UnixDgramSocket("unix_dgram_socket"),
220        /// The SELinux "unix_stream_socket" object class.
221        UnixStreamSocket("unix_stream_socket"),
222        /// "vsock_socket" class enabled via the "extended_socket_class" policy capability.
223        VsockSocket("vsock_socket"),
224        // keep-sorted end
225    }
226}
227
228impl From<FsNodeClass> for KernelClass {
229    fn from(class: FsNodeClass) -> Self {
230        match class {
231            FsNodeClass::File(file_class) => file_class.into(),
232            FsNodeClass::Socket(sock_class) => sock_class.into(),
233        }
234    }
235}
236pub trait ForClass<T> {
237    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
238    /// This is used to allow hooks to resolve e.g. common "sys_nice" permission access based on the
239    /// "allow" rules for the correct target object class.
240    fn for_class(&self, class: T) -> KernelPermission;
241}
242
243subset_enum! {
244    /// Covers the set of classes that inherit from the common "cap" symbol (e.g. "capability" for
245    /// now and "cap_userns" after Starnix gains user namespacing support).
246    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
247    CapClass from KernelClass {
248        // keep-sorted start
249        /// The SELinux "capability" object class.
250        Capability,
251        // keep-sorted end
252    }
253}
254
255subset_enum! {
256    /// Covers the set of classes that inherit from the common "cap2" symbol (e.g. "capability2" for
257    /// now and "cap2_userns" after Starnix gains user namespacing support).
258    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
259    Cap2Class from KernelClass {
260        // keep-sorted start
261        /// The SELinux "capability2" object class.
262        Capability2,
263        // keep-sorted end
264    }
265}
266
267subset_enum! {
268    /// A well-known file-like class in SELinux policy that has a particular meaning in policy
269    /// enforcement hooks.
270    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
271    FileClass from KernelClass {
272        // keep-sorted start
273        /// The SELinux "anon_inode" object class.
274        AnonFsNode,
275        /// The SELinux "blk_file" object class.
276        BlkFile,
277        /// The SELinux "chr_file" object class.
278        ChrFile,
279        /// The SELinux "dir" object class.
280        Dir,
281        /// The SELinux "fifo_file" object class.
282        FifoFile,
283        /// The SELinux "file" object class.
284        File,
285        /// The SELinux "lnk_file" object class.
286        LnkFile,
287        /// The SELinux "memfd_file" object class.
288        MemFdFile,
289        /// The SELinux "sock_file" object class.
290        SockFile,
291        // keep-sorted end
292    }
293}
294
295subset_enum! {
296    /// Distinguishes socket-like kernel object classes defined in SELinux policy.
297    #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
298    SocketClass from KernelClass {
299        // keep-sorted start
300        IcmpSocket,
301        KeySocket,
302        NetlinkAuditSocket,
303        NetlinkConnectorSocket,
304        NetlinkCryptoSocket,
305        NetlinkDnrtSocket,
306        NetlinkFibLookupSocket,
307        NetlinkFirewallSocket,
308        NetlinkGenericSocket,
309        NetlinkIp6FwSocket,
310        NetlinkIscsiSocket,
311        NetlinkKobjectUeventSocket,
312        NetlinkNetfilterSocket,
313        NetlinkNflogSocket,
314        NetlinkRdmaSocket,
315        NetlinkRouteSocket,
316        NetlinkScsitransportSocket,
317        NetlinkSelinuxSocket,
318        NetlinkSocket,
319        NetlinkTcpDiagSocket,
320        NetlinkXfrmSocket,
321        PacketSocket,
322        QipcrtrSocket,
323        RawIpSocket,
324        SctpSocket,
325        /// Generic socket class applied to all socket-like objects for which no more specific
326        /// class is defined.
327        Socket,
328        TcpSocket,
329        TunSocket,
330        UdpSocket,
331        UnixDgramSocket,
332        UnixStreamSocket,
333        VsockSocket,
334        // keep-sorted end
335    }
336}
337
338/// Container for a security class that could be associated with a [`crate::vfs::FsNode`], to allow
339/// permissions common to both file-like and socket-like classes to be generated easily by hooks.
340#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
341pub enum FsNodeClass {
342    File(FileClass),
343    Socket(SocketClass),
344}
345
346impl From<FileClass> for FsNodeClass {
347    fn from(file_class: FileClass) -> Self {
348        FsNodeClass::File(file_class)
349    }
350}
351
352impl From<SocketClass> for FsNodeClass {
353    fn from(sock_class: SocketClass) -> Self {
354        FsNodeClass::Socket(sock_class)
355    }
356}
357
358pub trait ClassPermission {
359    fn class(&self) -> KernelClass;
360    fn id(&self) -> u8;
361    fn as_access_vector(&self) -> AccessVector {
362        AccessVector::from(1u32 << self.id())
363    }
364}
365
366impl<T: Into<KernelClass>> ForClass<T> for KernelPermission {
367    fn for_class(&self, class: T) -> KernelPermission {
368        assert_eq!(self.class(), class.into());
369        *self
370    }
371}
372
373/// Helper used to declare the set of named permissions associated with an SELinux class.
374/// The `ClassType` trait is implemented on the declared `enum`, enabling values to be wrapped into
375/// the generic `KernelPermission` container.
376/// If an "extends" type is specified then a `Common` enum case is added, encapsulating the values
377/// of that underlying permission type. This is used to represent e.g. SELinux "dir" class deriving
378/// a basic set of permissions from the common "file" symbol.
379macro_rules! class_permission_enum {
380    ($(#[$meta:meta])* $name:ident for $kernel_class:ident {
381        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
382    }) => {
383        named_enum! {
384            #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
385            #[repr(u8)]
386            $(#[$meta])* $name {
387                $($(#[$variant_meta])* $variant ($variant_name),)*
388            }
389        }
390
391
392        impl ClassPermission for $name {
393            fn class(&self) -> KernelClass {
394                KernelClass::$kernel_class
395            }
396            fn id(&self) -> u8 {
397                *self as u8
398            }
399        }
400
401        impl $name {
402            pub const PERMISSIONS: &[KernelPermission] = &[$(KernelPermission::$kernel_class(Self::$variant)),*];
403        }
404    };
405    ($(#[$meta:meta])* $name:ident {
406        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
407    }) => {
408        named_enum! {
409            #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
410            #[repr(u8)]
411            $(#[$meta])* $name {
412                $($(#[$variant_meta])* $variant ($variant_name),)*
413            }
414        }
415    }
416}
417
418/// Permissions common to all cap-like object classes (e.g. "capability" for now and
419/// "cap_userns" after Starnix gains user namespacing support). These are combined with a
420/// specific `CapabilityClass` by policy enforcement hooks, to obtain class-affine permission
421/// values to check.
422macro_rules! cap_class_permission_enum {
423    ($(#[$meta:meta])* $name:ident $(for $kernel_class:ident)? {
424        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
425    }) => {
426        class_permission_enum! {
427            $(#[$meta])* $name $(for $kernel_class)? {
428                // keep-sorted start
429
430                AuditControl("audit_control"),
431                AuditWrite("audit_write"),
432                Chown("chown"),
433                DacOverride("dac_override"),
434                DacReadSearch("dac_read_search"),
435                Fowner("fowner"),
436                Fsetid("fsetid"),
437                IpcLock("ipc_lock"),
438                IpcOwner("ipc_owner"),
439                Kill("kill"),
440                Lease("lease"),
441                LinuxImmutable("linux_immutable"),
442                Mknod("mknod"),
443                NetAdmin("net_admin"),
444                NetBindService("net_bind_service"),
445                NetBroadcast("net_broadcast"),
446                NetRaw("net_raw"),
447                Setfcap("setfcap"),
448                Setgid("setgid"),
449                Setpcap("setpcap"),
450                Setuid("setuid"),
451                SysAdmin("sys_admin"),
452                SysBoot("sys_boot"),
453                SysChroot("sys_chroot"),
454                SysModule("sys_module"),
455                SysNice("sys_nice"),
456                SysPacct("sys_pacct"),
457                SysPtrace("sys_ptrace"),
458                SysRawio("sys_rawio"),
459                SysResource("sys_resource"),
460                SysTime("sys_time"),
461                SysTtyConfig("sys_tty_config"),
462
463                // keep-sorted end
464
465                // Additional permissions specific to the derived class.
466                $($(#[$variant_meta])* $variant ($variant_name),)*
467            }
468        }
469    }
470}
471
472cap_class_permission_enum! {
473    CapabilityPermission for Capability {}
474}
475
476cap_class_permission_enum! {
477    CommonCapPermission {}
478}
479
480impl ForClass<CapClass> for CommonCapPermission {
481    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
482    /// This is used to allow hooks to resolve e.g. common "sys_nice" permission access based on the
483    /// "allow" rules for the correct target object class.
484    fn for_class(&self, class: CapClass) -> KernelPermission {
485        match class {
486            CapClass::Capability => CapabilityPermission::from(*self).into(),
487        }
488    }
489}
490
491impl From<CommonCapPermission> for CapabilityPermission {
492    fn from(other: CommonCapPermission) -> Self {
493        // SAFETY: CapabilityPermission's values include all of CommonCapPermission.
494        unsafe { std::mem::transmute(other) }
495    }
496}
497
498/// Permissions common to all cap2-like object classes (e.g. "capability2" for now and
499/// "cap2_userns" after Starnix gains user namespacing support). These are combined with a
500/// specific `Capability2Class` by policy enforcement hooks, to obtain class-affine permission
501/// values to check.
502macro_rules! cap2_class_permission_enum {
503    ($(#[$meta:meta])* $name:ident $(for $kernel_class:ident)? {
504        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
505    }) => {
506        class_permission_enum! {
507            $(#[$meta])* $ name $(for $kernel_class)? {
508                // keep-sorted start
509
510                AuditRead("audit_read"),
511                BlockSuspend("block_suspend"),
512                Bpf("bpf"),
513                MacAdmin("mac_admin"),
514                MacOverride("mac_override"),
515                Perfmon("perfmon"),
516                Syslog("syslog"),
517                WakeAlarm("wake_alarm"),
518
519                // keep-sorted end
520
521                // Additional permissions specific to the derived class.
522                $($(#[$variant_meta])* $variant ($variant_name),)*
523            }
524        }
525    }
526}
527
528cap2_class_permission_enum! {
529    /// Permissions for the kernel "capability" class.
530    Capability2Permission for Capability2 {}
531}
532
533cap2_class_permission_enum! {
534    /// Common symbol inherited by "capability2" and "capuser2" classes.
535    CommonCap2Permission {}
536}
537
538impl ForClass<Cap2Class> for CommonCap2Permission {
539    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
540    /// This is used to allow hooks to resolve e.g. common "mac_admin" permission access based on
541    /// the "allow" rules for the correct target object class.
542    fn for_class(&self, class: Cap2Class) -> KernelPermission {
543        match class {
544            Cap2Class::Capability2 => Capability2Permission::from(*self).into(),
545        }
546    }
547}
548
549impl From<CommonCap2Permission> for Capability2Permission {
550    fn from(other: CommonCap2Permission) -> Self {
551        // SAFETY: Capability2Permission's values include all of CommonCap2Permission.
552        unsafe { std::mem::transmute(other) }
553    }
554}
555
556/// Permissions meaningful for all [`crate::vfs::FsNode`]s, whether file- or socket-like.
557///
558/// This extra layer of common permissions is not reflected in the hierarchy defined by the
559/// SELinux Reference Policy. Because even common permissions are mapped per-class, by name, to
560/// the policy equivalents, the implementation and policy notions of common permissions need not
561/// be identical.
562macro_rules! fs_node_class_permission_enum {
563    ($(#[$meta:meta])* $name:ident $(for $kernel_class:ident)? {
564        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
565    }) => {
566        class_permission_enum! {
567            $(#[$meta])* $name $(for $kernel_class)? {
568                // keep-sorted start
569                /// Permission to append to a file or socket.
570                Append("append"),
571                /// Pseudo-permission used in `dontaudit` access-rules to allow access checks to be made
572                /// between specific sources & targets without generating audit logs.
573                AuditAccess("audit_access"),
574                /// Permission to create a file or socket.
575                Create("create"),
576                /// Permission to query attributes, including uid, gid and extended attributes.
577                GetAttr("getattr"),
578                /// Permission to execute ioctls on the file or socket.
579                Ioctl("ioctl"),
580                /// Permission to set and unset file or socket locks.
581                Lock("lock"),
582                /// Permission to map a file.
583                Map("map"),
584                /// Permission to read content from a file or socket, as well as reading or following links.
585                Read("read"),
586                /// Permission checked against the existing label when updating a node's security label.
587                RelabelFrom("relabelfrom"),
588                /// Permission checked against the new label when updating a node's security label.
589                RelabelTo("relabelto"),
590                /// Permission to modify attributes, including uid, gid and extended attributes.
591                SetAttr("setattr"),
592                /// Permission to write contents to the file or socket.
593                Write("write"),
594                // keep-sorted end
595
596                // Additional permissions specific to the derived class.
597                $($(#[$variant_meta])* $variant ($variant_name),)*
598            }
599        }
600    }
601}
602
603fs_node_class_permission_enum! {
604    CommonFsNodePermission {}
605}
606
607impl<T: Into<FsNodeClass>> ForClass<T> for CommonFsNodePermission {
608    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
609    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
610    /// "allow" rules for the correct target object class.
611    fn for_class(&self, class: T) -> KernelPermission {
612        match class.into() {
613            FsNodeClass::File(file_class) => {
614                CommonFilePermission::from(*self).for_class(file_class)
615            }
616            FsNodeClass::Socket(sock_class) => {
617                CommonSocketPermission::from(*self).for_class(sock_class)
618            }
619        }
620    }
621}
622
623impl From<CommonFsNodePermission> for CommonFilePermission {
624    fn from(other: CommonFsNodePermission) -> Self {
625        // SAFETY: CommonFilePermission's values include all of CommonFsNodePermission.
626        unsafe { std::mem::transmute(other) }
627    }
628}
629
630impl From<CommonFsNodePermission> for CommonSocketPermission {
631    fn from(other: CommonFsNodePermission) -> Self {
632        // SAFETY: CommonSocketPermission's values include all of CommonFsNodePermission.
633        unsafe { std::mem::transmute(other) }
634    }
635}
636
637/// Permissions common to all socket-like object classes. These are combined with a specific
638/// `SocketClass` by policy enforcement hooks, to obtain class-affine permission values.
639macro_rules! socket_class_permission_enum {
640    ($(#[$meta:meta])* $name:ident $(for $kernel_class:ident)? {
641        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
642    }) => {
643        fs_node_class_permission_enum! {
644            $(#[$meta])* $name $(for $kernel_class)? {
645                // keep-sorted start
646                /// Permission to accept a connection.
647                Accept("accept"),
648                /// Permission to bind to a name.
649                Bind("bind"),
650                /// Permission to initiate a connection.
651                Connect("connect"),
652                /// Permission to get socket options.
653                GetOpt("getopt"),
654                /// Permission to listen for connections.
655                Listen("listen"),
656                /// Permission to send datagrams to the socket.
657                SendTo("sendto"),
658                /// Permission to set socket options.
659                SetOpt("setopt"),
660                /// Permission to terminate connection.
661                Shutdown("shutdown"),
662                // keep-sorted end
663
664                // Additional permissions specific to the derived class.
665                $($(#[$variant_meta])* $variant ($variant_name),)*
666            }
667        }
668
669        $(impl From<CommonSocketPermission> for $name {
670            fn from(other: CommonSocketPermission) -> Self {
671                // SAFETY: $name's values include all of CommonSocketPermission.
672                let result: $name = unsafe { std::mem::transmute(other) };
673                debug_assert_eq!(result.class(), KernelClass::$kernel_class);
674                result
675            }
676        })?
677    }
678}
679
680socket_class_permission_enum! {
681    CommonSocketPermission {}
682}
683
684impl ForClass<SocketClass> for CommonSocketPermission {
685    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
686    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
687    /// "allow" rules for the correct target object class.
688    fn for_class(&self, class: SocketClass) -> KernelPermission {
689        match class {
690            SocketClass::KeySocket => KeySocketPermission::from(*self).into(),
691            SocketClass::NetlinkSocket => NetlinkSocketPermission::from(*self).into(),
692            SocketClass::NetlinkAuditSocket => NetlinkAuditSocketPermission::from(*self).into(),
693            SocketClass::NetlinkConnectorSocket => {
694                NetlinkConnectorSocketPermission::from(*self).into()
695            }
696            SocketClass::NetlinkCryptoSocket => NetlinkCryptoSocketPermission::from(*self).into(),
697            SocketClass::NetlinkDnrtSocket => NetlinkDnrtSocketPermission::from(*self).into(),
698            SocketClass::NetlinkFibLookupSocket => {
699                NetlinkFibLookupSocketPermission::from(*self).into()
700            }
701            SocketClass::NetlinkFirewallSocket => {
702                NetlinkFirewallSocketPermission::from(*self).into()
703            }
704            SocketClass::NetlinkGenericSocket => NetlinkGenericSocketPermission::from(*self).into(),
705            SocketClass::NetlinkIp6FwSocket => NetlinkIp6FwSocketPermission::from(*self).into(),
706            SocketClass::NetlinkIscsiSocket => NetlinkIscsiSocketPermission::from(*self).into(),
707            SocketClass::NetlinkKobjectUeventSocket => {
708                NetlinkKobjectUeventSocketPermission::from(*self).into()
709            }
710            SocketClass::NetlinkNetfilterSocket => {
711                NetlinkNetfilterSocketPermission::from(*self).into()
712            }
713            SocketClass::NetlinkNflogSocket => NetlinkNflogSocketPermission::from(*self).into(),
714            SocketClass::NetlinkRdmaSocket => NetlinkRdmaSocketPermission::from(*self).into(),
715            SocketClass::NetlinkRouteSocket => NetlinkRouteSocketPermission::from(*self).into(),
716            SocketClass::NetlinkScsitransportSocket => {
717                NetlinkScsitransportSocketPermission::from(*self).into()
718            }
719            SocketClass::NetlinkSelinuxSocket => NetlinkSelinuxSocketPermission::from(*self).into(),
720            SocketClass::NetlinkTcpDiagSocket => NetlinkTcpDiagSocketPermission::from(*self).into(),
721            SocketClass::NetlinkXfrmSocket => NetlinkXfrmSocketPermission::from(*self).into(),
722            SocketClass::PacketSocket => PacketSocketPermission::from(*self).into(),
723            SocketClass::QipcrtrSocket => QipcrtrSocketPermission::from(*self).into(),
724            SocketClass::RawIpSocket => RawIpSocketPermission::from(*self).into(),
725            SocketClass::SctpSocket => SctpSocketPermission::from(*self).into(),
726            SocketClass::Socket => SocketPermission::from(*self).into(),
727            SocketClass::TcpSocket => TcpSocketPermission::from(*self).into(),
728            SocketClass::TunSocket => TunSocketPermission::from(*self).into(),
729            SocketClass::UdpSocket => UdpSocketPermission::from(*self).into(),
730            SocketClass::UnixDgramSocket => UnixDgramSocketPermission::from(*self).into(),
731            SocketClass::UnixStreamSocket => UnixStreamSocketPermission::from(*self).into(),
732            SocketClass::VsockSocket => VsockSocketPermission::from(*self).into(),
733            SocketClass::IcmpSocket => IcmpSocketPermission::from(*self).into(),
734        }
735    }
736}
737
738socket_class_permission_enum! {
739    KeySocketPermission for KeySocket {
740    }
741}
742
743socket_class_permission_enum! {
744    NetlinkSocketPermission for NetlinkSocket {}
745}
746
747socket_class_permission_enum! {
748    NetlinkRouteSocketPermission for NetlinkRouteSocket {
749        // keep-sorted start
750        /// Permission for nlmsg xperms.
751        Nlmsg("nlmsg"),
752        /// Permission to read the kernel neighbor table.
753        NlmsgGetNeigh("nlmsg_getneigh"),
754        /// Permission to read the kernel routing table.
755        NlmsgRead("nlmsg_read"),
756        /// Permission to read privileged netlink messages.
757        NlmsgReadPriv("nlmsg_readpriv"),
758        /// Permission to write to the kernel routing table.
759        NlmsgWrite("nlmsg_write"),
760        // keep-sorted end
761    }
762}
763
764socket_class_permission_enum! {
765    NetlinkFirewallSocketPermission for NetlinkFirewallSocket {
766    }
767}
768
769socket_class_permission_enum! {
770    NetlinkTcpDiagSocketPermission for NetlinkTcpDiagSocket {
771        // keep-sorted start
772        /// Permission for nlmsg xperms.
773        Nlmsg("nlmsg"),
774        /// Permission to request information about a protocol.
775        NlmsgRead("nlmsg_read"),
776        /// Permission to write netlink message.
777        NlmsgWrite("nlmsg_write"),
778        // keep-sorted end
779    }
780}
781
782socket_class_permission_enum! {
783    NetlinkNflogSocketPermission for NetlinkNflogSocket {
784    }
785}
786
787socket_class_permission_enum! {
788    NetlinkXfrmSocketPermission  for NetlinkXfrmSocket {
789        // keep-sorted start
790        /// Permission for nlmsg xperms.
791        Nlmsg("nlmsg"),
792        /// Permission to get IPSec configuration information.
793        NlmsgRead("nlmsg_read"),
794        /// Permission to set IPSec configuration information.
795        NlmsgWrite("nlmsg_write"),
796        // keep-sorted end
797    }
798}
799
800socket_class_permission_enum! {
801    NetlinkSelinuxSocketPermission for NetlinkSelinuxSocket {
802    }
803}
804
805socket_class_permission_enum! {
806    NetlinkIscsiSocketPermission for NetlinkIscsiSocket {
807    }
808}
809
810socket_class_permission_enum! {
811    NetlinkAuditSocketPermission for NetlinkAuditSocket {
812        // keep-sorted start
813        /// Permission for nlmsg xperms.
814        Nlmsg("nlmsg"),
815        /// Permission to query status of audit service.
816        NlmsgRead("nlmsg_read"),
817        /// Permission to list auditing configuration rules.
818        NlmsgReadPriv("nlmsg_readpriv"),
819        /// Permission to send userspace audit messages to the audit service.
820        NlmsgRelay("nlmsg_relay"),
821        /// Permission to control TTY auditing.
822        NlmsgTtyAudit("nlmsg_tty_audit"),
823        /// Permission to update the audit service configuration.
824        NlmsgWrite("nlmsg_write"),
825        // keep-sorted end
826    }
827}
828
829socket_class_permission_enum! {
830    NetlinkFibLookupSocketPermission for NetlinkFibLookupSocket {
831    }
832}
833
834socket_class_permission_enum! {
835    NetlinkConnectorSocketPermission for NetlinkConnectorSocket {
836    }
837}
838
839socket_class_permission_enum! {
840    NetlinkNetfilterSocketPermission for NetlinkNetfilterSocket {
841    }
842}
843
844socket_class_permission_enum! {
845    NetlinkIp6FwSocketPermission for NetlinkIp6FwSocket {
846    }
847}
848
849socket_class_permission_enum! {
850    NetlinkDnrtSocketPermission for NetlinkDnrtSocket {
851    }
852}
853
854socket_class_permission_enum! {
855    NetlinkKobjectUeventSocketPermission for NetlinkKobjectUeventSocket {
856    }
857}
858
859socket_class_permission_enum! {
860    NetlinkGenericSocketPermission for NetlinkGenericSocket {
861    }
862}
863
864socket_class_permission_enum! {
865    NetlinkScsitransportSocketPermission for NetlinkScsitransportSocket {
866    }
867}
868
869socket_class_permission_enum! {
870    NetlinkRdmaSocketPermission for NetlinkRdmaSocket {
871    }
872}
873
874socket_class_permission_enum! {
875    NetlinkCryptoSocketPermission for NetlinkCryptoSocket {
876    }
877}
878
879socket_class_permission_enum! {
880    PacketSocketPermission for PacketSocket {
881    }
882}
883
884socket_class_permission_enum! {
885    QipcrtrSocketPermission for QipcrtrSocket {
886    }
887}
888
889socket_class_permission_enum! {
890    RawIpSocketPermission for RawIpSocket {
891    }
892}
893
894socket_class_permission_enum! {
895    SctpSocketPermission for SctpSocket {
896        // keep-sorted start
897        /// Permission to create an SCTP association.
898        Associate("associate"),
899        /// Permission to `connect()` or `connectx()` an SCTP socket.
900        NameConnect("name_connect"),
901        /// Permission to `bind()` or `bindx()` an SCTP socket.
902        NodeBind("node_bind"),
903        // keep-sorted end
904    }
905}
906
907socket_class_permission_enum! {
908    SocketPermission for Socket {
909    }
910}
911
912socket_class_permission_enum! {
913    TcpSocketPermission for TcpSocket {
914    }
915}
916
917socket_class_permission_enum! {
918    TunSocketPermission for TunSocket {
919    }
920}
921
922socket_class_permission_enum! {
923    UdpSocketPermission for UdpSocket {
924    }
925}
926
927socket_class_permission_enum! {
928    UnixStreamSocketPermission for UnixStreamSocket {
929        // keep-sorted start
930        /// Permission to connect a streaming Unix-domain socket.
931        ConnectTo("connectto"),
932        // keep-sorted end
933    }
934}
935
936socket_class_permission_enum! {
937    UnixDgramSocketPermission for UnixDgramSocket {
938    }
939}
940
941socket_class_permission_enum! {
942    VsockSocketPermission for VsockSocket {
943    }
944}
945
946socket_class_permission_enum! {
947    IcmpSocketPermission for IcmpSocket {
948        // keep-sorted start
949        /// Permission to `bind()` an ICMP socket.
950        NodeBind("node_bind"),
951        // keep-sorted end
952    }
953}
954
955/// Permissions common to all file-like object classes (e.g. "lnk_file", "dir"). These are
956/// combined with a specific `FileClass` by policy enforcement hooks, to obtain class-affine
957/// permission values to check.
958macro_rules! file_class_permission_enum {
959    ($(#[$meta:meta])* $name:ident $(for $kernel_class:ident)? {
960        $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
961    }) => {
962        fs_node_class_permission_enum! {
963        $(#[$meta])* $name $(for $kernel_class)? {
964            // keep-sorted start
965
966            /// Permission to execute a file with domain transition.
967            Execute("execute"),
968            /// Permissions to create hard link.
969            Link("link"),
970            /// Permission to use as mount point; only useful for directories and files.
971            MountOn("mounton"),
972            /// Permission to open a file.
973            Open("open"),
974            /// Permission to rename a file.
975            Rename("rename"),
976            /// Permission to delete a file or remove a hard link.
977            Unlink("unlink"),
978            // keep-sorted end
979
980            // Additional permissions specific to the derived class.
981            $($(#[$variant_meta])* $variant ($variant_name),)*
982        }}
983
984        $(impl From<CommonFilePermission> for $name {
985            fn from(other: CommonFilePermission) -> Self {
986                // SAFETY: $name's values include all of CommonFilePermission.
987                let result: $name = unsafe { std::mem::transmute(other) };
988                debug_assert_eq!(result.class(), KernelClass::$kernel_class);
989                result
990            }
991        })?
992    }
993}
994
995file_class_permission_enum! {
996    CommonFilePermission {}
997}
998
999impl ForClass<FileClass> for CommonFilePermission {
1000    /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
1001    /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
1002    /// "allow" rules for the correct target object class.
1003    fn for_class(&self, class: FileClass) -> KernelPermission {
1004        match class {
1005            FileClass::AnonFsNode => AnonFsNodePermission::from(*self).into(),
1006            FileClass::BlkFile => BlkFilePermission::from(*self).into(),
1007            FileClass::ChrFile => ChrFilePermission::from(*self).into(),
1008            FileClass::Dir => DirPermission::from(*self).into(),
1009            FileClass::FifoFile => FifoFilePermission::from(*self).into(),
1010            FileClass::File => FilePermission::from(*self).into(),
1011            FileClass::LnkFile => LnkFilePermission::from(*self).into(),
1012            FileClass::SockFile => SockFilePermission::from(*self).into(),
1013            FileClass::MemFdFile => MemFdFilePermission::from(*self).into(),
1014        }
1015    }
1016}
1017
1018file_class_permission_enum! {
1019    AnonFsNodePermission for AnonFsNode {
1020    }
1021}
1022
1023class_permission_enum! {
1024    BinderPermission for Binder {
1025        // keep-sorted start
1026        /// Permission to perform a binder IPC to a given target process.
1027        Call("call"),
1028        /// Permission to use a Binder connection created with a different security context.
1029        Impersonate("impersonate"),
1030        /// Permission to set oneself as a context manager.
1031        SetContextMgr("set_context_mgr"),
1032        /// Permission to transfer Binder objects as part of a Binder transaction.
1033        Transfer("transfer"),
1034        // keep-sorted end
1035    }
1036}
1037
1038file_class_permission_enum! {
1039    BlkFilePermission for BlkFile {
1040    }
1041}
1042
1043file_class_permission_enum! {
1044    ChrFilePermission for ChrFile {
1045    }
1046}
1047
1048file_class_permission_enum! {
1049    DirPermission for Dir {
1050        // keep-sorted start
1051        /// Permission to add a file to the directory.
1052        AddName("add_name"),
1053        /// Permission to remove a directory.
1054        RemoveDir("rmdir"),
1055        /// Permission to remove an entry from a directory.
1056        RemoveName("remove_name"),
1057        /// Permission to change parent directory.
1058        Reparent("reparent"),
1059        /// Search access to the directory.
1060        Search("search"),
1061        // keep-sorted end
1062    }
1063}
1064
1065class_permission_enum! {
1066    FdPermission for Fd {
1067        // keep-sorted start
1068        /// Permission to use file descriptors copied/retained/inherited from another security
1069        /// context. This permission is generally used to control whether an `exec*()` call from a
1070        /// cloned process that retained a copy of the file descriptor table should succeed.
1071        Use("use"),
1072        // keep-sorted end
1073    }
1074}
1075
1076class_permission_enum! {
1077    BpfPermission for Bpf {
1078        // keep-sorted start
1079        /// Permission to create a map.
1080        MapCreate("map_create"),
1081        /// Permission to read from a map.
1082        MapRead("map_read"),
1083        /// Permission to write on a map.
1084        MapWrite("map_write"),
1085        /// Permission to load a program.
1086        ProgLoad("prog_load"),
1087        /// Permission to run a program.
1088        ProgRun("prog_run"),
1089        // keep-sorted end
1090    }
1091}
1092
1093class_permission_enum! {
1094    PerfEventPermission for PerfEvent {
1095        // keep-sorted start
1096        /// Permission to monitor the cpu.
1097        Cpu("cpu"),
1098        /// Permission to monitor the kernel.
1099        Kernel("kernel"),
1100        /// Permission to open a perf event.
1101        Open("open"),
1102        /// Permission to read a perf event.
1103        Read("read"),
1104        /// Permission to set tracepoints.
1105        Tracepoint("tracepoint"),
1106        /// Permission to write a perf event.
1107        Write("write"),
1108        // keep-sorted end
1109    }
1110}
1111
1112file_class_permission_enum! {
1113    FifoFilePermission for FifoFile {
1114    }
1115}
1116
1117file_class_permission_enum! {
1118    FilePermission for File {
1119        // keep-sorted start
1120        /// Permission to use a file as an entry point into the new domain on transition.
1121        Entrypoint("entrypoint"),
1122        /// Permission to use a file as an entry point to the calling domain without performing a
1123        /// transition.
1124        ExecuteNoTrans("execute_no_trans"),
1125        // keep-sorted end
1126    }
1127}
1128
1129class_permission_enum! {
1130    FileSystemPermission for FileSystem {
1131        // keep-sorted start
1132        /// Permission to associate a file to the filesystem.
1133        Associate("associate"),
1134        /// Permission to get filesystem attributes.
1135        GetAttr("getattr"),
1136        /// Permission mount a filesystem.
1137        Mount("mount"),
1138        /// Permission to remount a filesystem with different flags.
1139        Remount("remount"),
1140        /// Permission to unmount a filesystem.
1141        Unmount("unmount"),
1142        // keep-sorted end
1143    }
1144}
1145
1146file_class_permission_enum! {
1147    LnkFilePermission for LnkFile {
1148    }
1149}
1150
1151file_class_permission_enum! {
1152    MemFdFilePermission for MemFdFile {
1153    }
1154}
1155
1156file_class_permission_enum! {
1157    SockFilePermission for SockFile {
1158    }
1159}
1160
1161class_permission_enum! {
1162    ProcessPermission for Process {
1163        // keep-sorted start
1164        /// Permission to dynamically transition a process to a different security domain.
1165        DynTransition("dyntransition"),
1166        /// Permission to execute arbitrary code from the heap.
1167        ExecHeap("execheap"),
1168        /// Permission to execute arbitrary code from memory.
1169        ExecMem("execmem"),
1170        /// Permission to execute arbitrary code from the stack.
1171        ExecStack("execstack"),
1172        /// Permission to fork the current running process.
1173        Fork("fork"),
1174        /// Permission to get Linux capabilities of a process.
1175        GetCap("getcap"),
1176        /// Permission to get the process group ID.
1177        GetPgid("getpgid"),
1178        /// Permission to get the resource limits on a process.
1179        GetRlimit("getrlimit"),
1180        /// Permission to get scheduling policy currently applied to a process.
1181        GetSched("getsched"),
1182        /// Permission to get the session ID.
1183        GetSession("getsession"),
1184        /// Permission to exec into a new security domain without setting the AT_SECURE entry in the
1185        /// executable's auxiliary vector.
1186        NoAtSecure("noatsecure"),
1187        /// Permission to trace a process.
1188        Ptrace("ptrace"),
1189        /// Permission to inherit the parent process's resource limits on exec.
1190        RlimitInh("rlimitinh"),
1191        /// Permission to set Linux capabilities of a process.
1192        SetCap("setcap"),
1193        /// Permission to set the calling task's current Security Context.
1194        /// The "dyntransition" permission separately limits which Contexts "setcurrent" may be used to transition to.
1195        SetCurrent("setcurrent"),
1196        /// Permission to set the Security Context used by `exec()`.
1197        SetExec("setexec"),
1198        /// Permission to set the Security Context used when creating filesystem objects.
1199        SetFsCreate("setfscreate"),
1200        /// Permission to set the Security Context used when creating kernel keyrings.
1201        SetKeyCreate("setkeycreate"),
1202        /// Permission to set the process group ID.
1203        SetPgid("setpgid"),
1204        /// Permission to set the resource limits on a process.
1205        SetRlimit("setrlimit"),
1206        /// Permission to set scheduling policy for a process.
1207        SetSched("setsched"),
1208        /// Permission to set the Security Context used when creating new labeled sockets.
1209        SetSockCreate("setsockcreate"),
1210        /// Permission to share resources (e.g. FD table, address-space, etc) with a process.
1211        Share("share"),
1212        /// Permission to send SIGCHLD to a process.
1213        SigChld("sigchld"),
1214        /// Permission to inherit the parent process's signal state.
1215        SigInh("siginh"),
1216        /// Permission to send SIGKILL to a process.
1217        SigKill("sigkill"),
1218        /// Permission to send SIGSTOP to a process.
1219        SigStop("sigstop"),
1220        /// Permission to send a signal other than SIGKILL, SIGSTOP, or SIGCHLD to a process.
1221        Signal("signal"),
1222        /// Permission to transition to a different security domain.
1223        Transition("transition"),
1224        // keep-sorted end
1225    }
1226}
1227
1228class_permission_enum! {
1229    Process2Permission for Process2 {
1230        // keep-sorted start
1231        /// Permission to transition to an unbounded domain when no-new-privileges is set.
1232        NnpTransition("nnp_transition"),
1233        /// Permission to transition domain when executing from a no-SUID mounted filesystem.
1234        NosuidTransition("nosuid_transition"),
1235        // keep-sorted end
1236    }
1237}
1238
1239class_permission_enum! {
1240    SecurityPermission for Security {
1241        // keep-sorted start
1242        /// Permission to validate Security Context using the "context" API.
1243        CheckContext("check_context"),
1244        /// Permission to compute access vectors via the "access" API.
1245        ComputeAv("compute_av"),
1246        /// Permission to compute security contexts based on `type_transition` rules via "create".
1247        ComputeCreate("compute_create"),
1248        /// Permission to compute security contexts based on `type_member` rules via "member".
1249        ComputeMember("compute_member"),
1250        /// Permission to compute security contexts based on `type_change` rules via "relabel".
1251        ComputeRelabel("compute_relabel"),
1252        /// Permission to compute user decisions via "user".
1253        ComputeUser("compute_user"),
1254        /// Permission to load a new binary policy into the kernel via the "load" API.
1255        LoadPolicy("load_policy"),
1256        /// Permission to read the loaded binary policy via the "policy" file.
1257        ReadPolicy("read_policy"),
1258        /// Permission to commit booleans to control conditional elements of the policy.
1259        SetBool("setbool"),
1260        /// Permission to change the way permissions are validated for `mmap()` operations.
1261        SetCheckReqProt("setcheckreqprot"),
1262        /// Permission to switch the system between permissive and enforcing modes, via "enforce".
1263        SetEnforce("setenforce"),
1264        // keep-sorted end
1265     }
1266}
1267
1268class_permission_enum! {
1269    SystemPermission for System {
1270        // keep-sorted start
1271        /// Permission to use the syslog(2) CONSOLE action types.
1272        SyslogConsole("syslog_console"),
1273        /// Permission to use other syslog(2) action types.
1274        SyslogMod("syslog_mod"),
1275        /// Permission to use the syslog(2) READ_ALL related action types.
1276        SyslogRead("syslog_read"),
1277        // keep-sorted end
1278     }
1279}