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