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