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