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