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