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