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 routing table.
752 NlmsgRead("nlmsg_read"),
753 /// Permission to write to the kernel routing table.
754 NlmsgWrite("nlmsg_write"),
755 // keep-sorted end
756 }
757}
758
759socket_class_permission_enum! {
760 NetlinkFirewallSocketPermission for NetlinkFirewallSocket {
761 }
762}
763
764socket_class_permission_enum! {
765 NetlinkTcpDiagSocketPermission for NetlinkTcpDiagSocket {
766 // keep-sorted start
767 /// Permission for nlmsg xperms.
768 Nlmsg("nlmsg"),
769 /// Permission to request information about a protocol.
770 NlmsgRead("nlmsg_read"),
771 /// Permission to write netlink message.
772 NlmsgWrite("nlmsg_write"),
773 // keep-sorted end
774 }
775}
776
777socket_class_permission_enum! {
778 NetlinkNflogSocketPermission for NetlinkNflogSocket {
779 }
780}
781
782socket_class_permission_enum! {
783 NetlinkXfrmSocketPermission for NetlinkXfrmSocket {
784 // keep-sorted start
785 /// Permission for nlmsg xperms.
786 Nlmsg("nlmsg"),
787 /// Permission to get IPSec configuration information.
788 NlmsgRead("nlmsg_read"),
789 /// Permission to set IPSec configuration information.
790 NlmsgWrite("nlmsg_write"),
791 // keep-sorted end
792 }
793}
794
795socket_class_permission_enum! {
796 NetlinkSelinuxSocketPermission for NetlinkSelinuxSocket {
797 }
798}
799
800socket_class_permission_enum! {
801 NetlinkIscsiSocketPermission for NetlinkIscsiSocket {
802 }
803}
804
805socket_class_permission_enum! {
806 NetlinkAuditSocketPermission for NetlinkAuditSocket {
807 // keep-sorted start
808 /// Permission for nlmsg xperms.
809 Nlmsg("nlmsg"),
810 /// Permission to query status of audit service.
811 NlmsgRead("nlmsg_read"),
812 /// Permission to list auditing configuration rules.
813 NlmsgReadPriv("nlmsg_readpriv"),
814 /// Permission to send userspace audit messages to the audit service.
815 NlmsgRelay("nlmsg_relay"),
816 /// Permission to control TTY auditing.
817 NlmsgTtyAudit("nlmsg_tty_audit"),
818 /// Permission to update the audit service configuration.
819 NlmsgWrite("nlmsg_write"),
820 // keep-sorted end
821 }
822}
823
824socket_class_permission_enum! {
825 NetlinkFibLookupSocketPermission for NetlinkFibLookupSocket {
826 }
827}
828
829socket_class_permission_enum! {
830 NetlinkConnectorSocketPermission for NetlinkConnectorSocket {
831 }
832}
833
834socket_class_permission_enum! {
835 NetlinkNetfilterSocketPermission for NetlinkNetfilterSocket {
836 }
837}
838
839socket_class_permission_enum! {
840 NetlinkIp6FwSocketPermission for NetlinkIp6FwSocket {
841 }
842}
843
844socket_class_permission_enum! {
845 NetlinkDnrtSocketPermission for NetlinkDnrtSocket {
846 }
847}
848
849socket_class_permission_enum! {
850 NetlinkKobjectUeventSocketPermission for NetlinkKobjectUeventSocket {
851 }
852}
853
854socket_class_permission_enum! {
855 NetlinkGenericSocketPermission for NetlinkGenericSocket {
856 }
857}
858
859socket_class_permission_enum! {
860 NetlinkScsitransportSocketPermission for NetlinkScsitransportSocket {
861 }
862}
863
864socket_class_permission_enum! {
865 NetlinkRdmaSocketPermission for NetlinkRdmaSocket {
866 }
867}
868
869socket_class_permission_enum! {
870 NetlinkCryptoSocketPermission for NetlinkCryptoSocket {
871 }
872}
873
874socket_class_permission_enum! {
875 PacketSocketPermission for PacketSocket {
876 }
877}
878
879socket_class_permission_enum! {
880 QipcrtrSocketPermission for QipcrtrSocket {
881 }
882}
883
884socket_class_permission_enum! {
885 RawIpSocketPermission for RawIpSocket {
886 }
887}
888
889socket_class_permission_enum! {
890 SctpSocketPermission for SctpSocket {
891 // keep-sorted start
892 /// Permission to create an SCTP association.
893 Associate("associate"),
894 /// Permission to `connect()` or `connectx()` an SCTP socket.
895 NameConnect("name_connect"),
896 /// Permission to `bind()` or `bindx()` an SCTP socket.
897 NodeBind("node_bind"),
898 // keep-sorted end
899 }
900}
901
902socket_class_permission_enum! {
903 SocketPermission for Socket {
904 }
905}
906
907socket_class_permission_enum! {
908 TcpSocketPermission for TcpSocket {
909 }
910}
911
912socket_class_permission_enum! {
913 TunSocketPermission for TunSocket {
914 }
915}
916
917socket_class_permission_enum! {
918 UdpSocketPermission for UdpSocket {
919 }
920}
921
922socket_class_permission_enum! {
923 UnixStreamSocketPermission for UnixStreamSocket {
924 // keep-sorted start
925 /// Permission to connect a streaming Unix-domain socket.
926 ConnectTo("connectto"),
927 // keep-sorted end
928 }
929}
930
931socket_class_permission_enum! {
932 UnixDgramSocketPermission for UnixDgramSocket {
933 }
934}
935
936socket_class_permission_enum! {
937 VsockSocketPermission for VsockSocket {
938 }
939}
940
941socket_class_permission_enum! {
942 IcmpSocketPermission for IcmpSocket {
943 // keep-sorted start
944 /// Permission to `bind()` an ICMP socket.
945 NodeBind("node_bind"),
946 // keep-sorted end
947 }
948}
949
950/// Permissions common to all file-like object classes (e.g. "lnk_file", "dir"). These are
951/// combined with a specific `FileClass` by policy enforcement hooks, to obtain class-affine
952/// permission values to check.
953macro_rules! file_class_permission_enum {
954 ($(#[$meta:meta])* $name:ident $(for $kernel_class:ident)? {
955 $($(#[$variant_meta:meta])* $variant:ident ($variant_name:literal),)*
956 }) => {
957 fs_node_class_permission_enum! {
958 $(#[$meta])* $name $(for $kernel_class)? {
959 // keep-sorted start
960
961 /// Permission to execute a file with domain transition.
962 Execute("execute"),
963 /// Permissions to create hard link.
964 Link("link"),
965 /// Permission to use as mount point; only useful for directories and files.
966 MountOn("mounton"),
967 /// Permission to open a file.
968 Open("open"),
969 /// Permission to rename a file.
970 Rename("rename"),
971 /// Permission to delete a file or remove a hard link.
972 Unlink("unlink"),
973 // keep-sorted end
974
975 // Additional permissions specific to the derived class.
976 $($(#[$variant_meta])* $variant ($variant_name),)*
977 }}
978
979 $(impl From<CommonFilePermission> for $name {
980 fn from(other: CommonFilePermission) -> Self {
981 // SAFETY: $name's values include all of CommonFilePermission.
982 let result: $name = unsafe { std::mem::transmute(other) };
983 debug_assert_eq!(result.class(), KernelClass::$kernel_class);
984 result
985 }
986 })?
987 }
988}
989
990file_class_permission_enum! {
991 CommonFilePermission {}
992}
993
994impl ForClass<FileClass> for CommonFilePermission {
995 /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
996 /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
997 /// "allow" rules for the correct target object class.
998 fn for_class(&self, class: FileClass) -> KernelPermission {
999 match class {
1000 FileClass::AnonFsNode => AnonFsNodePermission::from(*self).into(),
1001 FileClass::BlkFile => BlkFilePermission::from(*self).into(),
1002 FileClass::ChrFile => ChrFilePermission::from(*self).into(),
1003 FileClass::Dir => DirPermission::from(*self).into(),
1004 FileClass::FifoFile => FifoFilePermission::from(*self).into(),
1005 FileClass::File => FilePermission::from(*self).into(),
1006 FileClass::LnkFile => LnkFilePermission::from(*self).into(),
1007 FileClass::SockFile => SockFilePermission::from(*self).into(),
1008 FileClass::MemFdFile => MemFdFilePermission::from(*self).into(),
1009 }
1010 }
1011}
1012
1013file_class_permission_enum! {
1014 AnonFsNodePermission for AnonFsNode {
1015 }
1016}
1017
1018class_permission_enum! {
1019 BinderPermission for Binder {
1020 // keep-sorted start
1021 /// Permission to perform a binder IPC to a given target process.
1022 Call("call"),
1023 /// Permission to use a Binder connection created with a different security context.
1024 Impersonate("impersonate"),
1025 /// Permission to set oneself as a context manager.
1026 SetContextMgr("set_context_mgr"),
1027 /// Permission to transfer Binder objects as part of a Binder transaction.
1028 Transfer("transfer"),
1029 // keep-sorted end
1030 }
1031}
1032
1033file_class_permission_enum! {
1034 BlkFilePermission for BlkFile {
1035 }
1036}
1037
1038file_class_permission_enum! {
1039 ChrFilePermission for ChrFile {
1040 }
1041}
1042
1043file_class_permission_enum! {
1044 DirPermission for Dir {
1045 // keep-sorted start
1046 /// Permission to add a file to the directory.
1047 AddName("add_name"),
1048 /// Permission to remove a directory.
1049 RemoveDir("rmdir"),
1050 /// Permission to remove an entry from a directory.
1051 RemoveName("remove_name"),
1052 /// Permission to change parent directory.
1053 Reparent("reparent"),
1054 /// Search access to the directory.
1055 Search("search"),
1056 // keep-sorted end
1057 }
1058}
1059
1060class_permission_enum! {
1061 FdPermission for Fd {
1062 // keep-sorted start
1063 /// Permission to use file descriptors copied/retained/inherited from another security
1064 /// context. This permission is generally used to control whether an `exec*()` call from a
1065 /// cloned process that retained a copy of the file descriptor table should succeed.
1066 Use("use"),
1067 // keep-sorted end
1068 }
1069}
1070
1071class_permission_enum! {
1072 BpfPermission for Bpf {
1073 // keep-sorted start
1074 /// Permission to create a map.
1075 MapCreate("map_create"),
1076 /// Permission to read from a map.
1077 MapRead("map_read"),
1078 /// Permission to write on a map.
1079 MapWrite("map_write"),
1080 /// Permission to load a program.
1081 ProgLoad("prog_load"),
1082 /// Permission to run a program.
1083 ProgRun("prog_run"),
1084 // keep-sorted end
1085 }
1086}
1087
1088class_permission_enum! {
1089 PerfEventPermission for PerfEvent {
1090 // keep-sorted start
1091 /// Permission to monitor the cpu.
1092 Cpu("cpu"),
1093 /// Permission to monitor the kernel.
1094 Kernel("kernel"),
1095 /// Permission to open a perf event.
1096 Open("open"),
1097 /// Permission to read a perf event.
1098 Read("read"),
1099 /// Permission to set tracepoints.
1100 Tracepoint("tracepoint"),
1101 /// Permission to write a perf event.
1102 Write("write"),
1103 // keep-sorted end
1104 }
1105}
1106
1107file_class_permission_enum! {
1108 FifoFilePermission for FifoFile {
1109 }
1110}
1111
1112file_class_permission_enum! {
1113 FilePermission for File {
1114 // keep-sorted start
1115 /// Permission to use a file as an entry point into the new domain on transition.
1116 Entrypoint("entrypoint"),
1117 /// Permission to use a file as an entry point to the calling domain without performing a
1118 /// transition.
1119 ExecuteNoTrans("execute_no_trans"),
1120 // keep-sorted end
1121 }
1122}
1123
1124class_permission_enum! {
1125 FileSystemPermission for FileSystem {
1126 // keep-sorted start
1127 /// Permission to associate a file to the filesystem.
1128 Associate("associate"),
1129 /// Permission to get filesystem attributes.
1130 GetAttr("getattr"),
1131 /// Permission mount a filesystem.
1132 Mount("mount"),
1133 /// Permission to remount a filesystem with different flags.
1134 Remount("remount"),
1135 /// Permission to unmount a filesystem.
1136 Unmount("unmount"),
1137 // keep-sorted end
1138 }
1139}
1140
1141file_class_permission_enum! {
1142 LnkFilePermission for LnkFile {
1143 }
1144}
1145
1146file_class_permission_enum! {
1147 MemFdFilePermission for MemFdFile {
1148 }
1149}
1150
1151file_class_permission_enum! {
1152 SockFilePermission for SockFile {
1153 }
1154}
1155
1156class_permission_enum! {
1157 ProcessPermission for Process {
1158 // keep-sorted start
1159 /// Permission to dynamically transition a process to a different security domain.
1160 DynTransition("dyntransition"),
1161 /// Permission to execute arbitrary code from the heap.
1162 ExecHeap("execheap"),
1163 /// Permission to execute arbitrary code from memory.
1164 ExecMem("execmem"),
1165 /// Permission to execute arbitrary code from the stack.
1166 ExecStack("execstack"),
1167 /// Permission to fork the current running process.
1168 Fork("fork"),
1169 /// Permission to get Linux capabilities of a process.
1170 GetCap("getcap"),
1171 /// Permission to get the process group ID.
1172 GetPgid("getpgid"),
1173 /// Permission to get the resource limits on a process.
1174 GetRlimit("getrlimit"),
1175 /// Permission to get scheduling policy currently applied to a process.
1176 GetSched("getsched"),
1177 /// Permission to get the session ID.
1178 GetSession("getsession"),
1179 /// Permission to exec into a new security domain without setting the AT_SECURE entry in the
1180 /// executable's auxiliary vector.
1181 NoAtSecure("noatsecure"),
1182 /// Permission to trace a process.
1183 Ptrace("ptrace"),
1184 /// Permission to inherit the parent process's resource limits on exec.
1185 RlimitInh("rlimitinh"),
1186 /// Permission to set Linux capabilities of a process.
1187 SetCap("setcap"),
1188 /// Permission to set the calling task's current Security Context.
1189 /// The "dyntransition" permission separately limits which Contexts "setcurrent" may be used to transition to.
1190 SetCurrent("setcurrent"),
1191 /// Permission to set the Security Context used by `exec()`.
1192 SetExec("setexec"),
1193 /// Permission to set the Security Context used when creating filesystem objects.
1194 SetFsCreate("setfscreate"),
1195 /// Permission to set the Security Context used when creating kernel keyrings.
1196 SetKeyCreate("setkeycreate"),
1197 /// Permission to set the process group ID.
1198 SetPgid("setpgid"),
1199 /// Permission to set the resource limits on a process.
1200 SetRlimit("setrlimit"),
1201 /// Permission to set scheduling policy for a process.
1202 SetSched("setsched"),
1203 /// Permission to set the Security Context used when creating new labeled sockets.
1204 SetSockCreate("setsockcreate"),
1205 /// Permission to share resources (e.g. FD table, address-space, etc) with a process.
1206 Share("share"),
1207 /// Permission to send SIGCHLD to a process.
1208 SigChld("sigchld"),
1209 /// Permission to inherit the parent process's signal state.
1210 SigInh("siginh"),
1211 /// Permission to send SIGKILL to a process.
1212 SigKill("sigkill"),
1213 /// Permission to send SIGSTOP to a process.
1214 SigStop("sigstop"),
1215 /// Permission to send a signal other than SIGKILL, SIGSTOP, or SIGCHLD to a process.
1216 Signal("signal"),
1217 /// Permission to transition to a different security domain.
1218 Transition("transition"),
1219 // keep-sorted end
1220 }
1221}
1222
1223class_permission_enum! {
1224 Process2Permission for Process2 {
1225 // keep-sorted start
1226 /// Permission to transition to an unbounded domain when no-new-privileges is set.
1227 NnpTransition("nnp_transition"),
1228 /// Permission to transition domain when executing from a no-SUID mounted filesystem.
1229 NosuidTransition("nosuid_transition"),
1230 // keep-sorted end
1231 }
1232}
1233
1234class_permission_enum! {
1235 SecurityPermission for Security {
1236 // keep-sorted start
1237 /// Permission to validate Security Context using the "context" API.
1238 CheckContext("check_context"),
1239 /// Permission to compute access vectors via the "access" API.
1240 ComputeAv("compute_av"),
1241 /// Permission to compute security contexts based on `type_transition` rules via "create".
1242 ComputeCreate("compute_create"),
1243 /// Permission to compute security contexts based on `type_member` rules via "member".
1244 ComputeMember("compute_member"),
1245 /// Permission to compute security contexts based on `type_change` rules via "relabel".
1246 ComputeRelabel("compute_relabel"),
1247 /// Permission to compute user decisions via "user".
1248 ComputeUser("compute_user"),
1249 /// Permission to load a new binary policy into the kernel via the "load" API.
1250 LoadPolicy("load_policy"),
1251 /// Permission to commit booleans to control conditional elements of the policy.
1252 SetBool("setbool"),
1253 /// Permission to change the way permissions are validated for `mmap()` operations.
1254 SetCheckReqProt("setcheckreqprot"),
1255 /// Permission to switch the system between permissive and enforcing modes, via "enforce".
1256 SetEnforce("setenforce"),
1257 // keep-sorted end
1258 }
1259}
1260
1261class_permission_enum! {
1262 SystemPermission for System {
1263 // keep-sorted start
1264 /// Permission to use the syslog(2) CONSOLE action types.
1265 SyslogConsole("syslog_console"),
1266 /// Permission to use other syslog(2) action types.
1267 SyslogMod("syslog_mod"),
1268 /// Permission to use the syslog(2) READ_ALL related action types.
1269 SyslogRead("syslog_read"),
1270 // keep-sorted end
1271 }
1272}