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 read content from a file or socket, as well as reading or following links.
758 Read("read"),
759 /// Permission checked against the existing label when updating a node's security label.
760 RelabelFrom("relabelfrom"),
761 /// Permission checked against the new label when updating a node's security label.
762 RelabelTo("relabelto"),
763 /// Permission to modify attributes, including uid, gid and extended attributes.
764 SetAttr("setattr"),
765 /// Permission to write contents to the file or socket.
766 Write("write"),
767 // keep-sorted end
768 }
769}
770
771impl CommonFsNodePermission {
772 /// Returns the `class`-affine `Permission` value corresponding to this common permission.
773 /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
774 /// "allow" rules for the correct target object class.
775 pub fn for_class(&self, class: impl Into<FsNodeClass>) -> Permission {
776 match class.into() {
777 FsNodeClass::File(file_class) => {
778 CommonFilePermission::Common(self.clone()).for_class(file_class)
779 }
780 FsNodeClass::Socket(sock_class) => {
781 CommonSocketPermission::Common(self.clone()).for_class(sock_class)
782 }
783 }
784 }
785}
786common_permission_enum! {
787 /// Permissions common to all socket-like object classes. These are combined with a specific
788 /// `SocketClass` by policy enforcement hooks, to obtain class-affine permission values.
789 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
790 CommonSocketPermission extends CommonFsNodePermission {
791 // keep-sorted start
792 // keep-sorted end
793 }
794}
795
796impl CommonSocketPermission {
797 /// Returns the `class`-affine `Permission` value corresponding to this common permission.
798 /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
799 /// "allow" rules for the correct target object class.
800 pub fn for_class(&self, class: SocketClass) -> Permission {
801 match class {
802 SocketClass::Key => KeySocketPermission::Common(self.clone()).into(),
803 SocketClass::Netlink => NetlinkSocketPermission::Common(self.clone()).into(),
804 SocketClass::NetlinkAudit => NetlinkAuditSocketPermission::Common(self.clone()).into(),
805 SocketClass::NetlinkConnector => {
806 NetlinkConnectorSocketPermission::Common(self.clone()).into()
807 }
808 SocketClass::NetlinkCrypto => {
809 NetlinkCryptoSocketPermission::Common(self.clone()).into()
810 }
811 SocketClass::NetlinkDnrt => NetlinkDnrtSocketPermission::Common(self.clone()).into(),
812 SocketClass::NetlinkFibLookup => {
813 NetlinkFibLookupSocketPermission::Common(self.clone()).into()
814 }
815 SocketClass::NetlinkFirewall => {
816 NetlinkFirewallSocketPermission::Common(self.clone()).into()
817 }
818 SocketClass::NetlinkGeneric => {
819 NetlinkGenericSocketPermission::Common(self.clone()).into()
820 }
821 SocketClass::NetlinkIp6Fw => NetlinkIp6FwSocketPermission::Common(self.clone()).into(),
822 SocketClass::NetlinkIscsi => NetlinkIscsiSocketPermission::Common(self.clone()).into(),
823 SocketClass::NetlinkKobjectUevent => {
824 NetlinkKobjectUeventSocketPermission::Common(self.clone()).into()
825 }
826 SocketClass::NetlinkNetfilter => {
827 NetlinkNetfilterSocketPermission::Common(self.clone()).into()
828 }
829 SocketClass::NetlinkNflog => NetlinkNflogSocketPermission::Common(self.clone()).into(),
830 SocketClass::NetlinkRdma => NetlinkRdmaSocketPermission::Common(self.clone()).into(),
831 SocketClass::NetlinkRoute => NetlinkRouteSocketPermission::Common(self.clone()).into(),
832 SocketClass::NetlinkScsitransport => {
833 NetlinkScsitransportSocketPermission::Common(self.clone()).into()
834 }
835 SocketClass::NetlinkSelinux => {
836 NetlinkSelinuxSocketPermission::Common(self.clone()).into()
837 }
838 SocketClass::NetlinkTcpDiag => {
839 NetlinkTcpDiagSocketPermission::Common(self.clone()).into()
840 }
841 SocketClass::NetlinkXfrm => NetlinkXfrmSocketPermission::Common(self.clone()).into(),
842 SocketClass::Packet => PacketSocketPermission::Common(self.clone()).into(),
843 SocketClass::RawIp => RawIpSocketPermission::Common(self.clone()).into(),
844 SocketClass::Socket => SocketPermission::Common(self.clone()).into(),
845 SocketClass::Tcp => TcpSocketPermission::Common(self.clone()).into(),
846 SocketClass::Udp => UdpSocketPermission::Common(self.clone()).into(),
847 SocketClass::UnixDgram => UnixDgramSocketPermission::Common(self.clone()).into(),
848 SocketClass::UnixStream => UnixStreamSocketPermission::Common(self.clone()).into(),
849 SocketClass::Vsock => VsockSocketPermission::Common(self.clone()).into(),
850 }
851 }
852}
853
854class_permission_enum! {
855 /// A well-known "key_socket" class permission in SELinux policy that has a particular meaning in
856 /// policy enforcement hooks.
857 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
858 KeySocketPermission extends CommonSocketPermission {
859 }
860}
861class_permission_enum! {
862 /// A well-known "netlink_socket" class permission in SELinux policy that has a particular meaning in
863 /// policy enforcement hooks.
864 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
865 NetlinkSocketPermission extends CommonSocketPermission {
866 }
867}
868
869class_permission_enum! {
870 /// A well-known "netlink_route_socket" class permission in SELinux policy that has a particular meaning in
871 /// policy enforcement hooks.
872 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
873 NetlinkRouteSocketPermission extends CommonSocketPermission {
874 }
875}
876
877class_permission_enum! {
878 /// A well-known "netlink_firewall_socket" class permission in SELinux policy that has a particular meaning in
879 /// policy enforcement hooks.
880 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
881 NetlinkFirewallSocketPermission extends CommonSocketPermission {
882 }
883}
884
885class_permission_enum! {
886 /// A well-known "netlink_tcpdiag_socket" class permission in SELinux policy that has a particular meaning in
887 /// policy enforcement hooks.
888 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
889 NetlinkTcpDiagSocketPermission extends CommonSocketPermission {
890 }
891}
892
893class_permission_enum! {
894 /// A well-known "netlink_nflog_socket" class permission in SELinux policy that has a particular meaning in
895 /// policy enforcement hooks.
896 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
897 NetlinkNflogSocketPermission extends CommonSocketPermission {
898 }
899}
900
901class_permission_enum! {
902 /// A well-known "netlink_xfrm_socket" class permission in SELinux policy that has a particular meaning in
903 /// policy enforcement hooks.
904 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
905 NetlinkXfrmSocketPermission extends CommonSocketPermission {
906 }
907}
908
909class_permission_enum! {
910 /// A well-known "netlink_selinux_socket" class permission in SELinux policy that has a particular meaning in
911 /// policy enforcement hooks.
912 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
913 NetlinkSelinuxSocketPermission extends CommonSocketPermission {
914 }
915}
916
917class_permission_enum! {
918 /// A well-known "netlink_iscsi_socket" class permission in SELinux policy that has a particular meaning in
919 /// policy enforcement hooks.
920 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
921 NetlinkIscsiSocketPermission extends CommonSocketPermission {
922 }
923}
924
925class_permission_enum! {
926 /// A well-known "netlink_audit_socket" class permission in SELinux policy that has a particular meaning in
927 /// policy enforcement hooks.
928 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
929 NetlinkAuditSocketPermission extends CommonSocketPermission {
930 }
931}
932
933class_permission_enum! {
934 /// A well-known "netlink_fib_lookup_socket" class permission in SELinux policy that has a particular meaning in
935 /// policy enforcement hooks.
936 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
937 NetlinkFibLookupSocketPermission extends CommonSocketPermission {
938 }
939}
940
941class_permission_enum! {
942 /// A well-known "netlink_connector_socket" class permission in SELinux policy that has a particular meaning in
943 /// policy enforcement hooks.
944 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
945 NetlinkConnectorSocketPermission extends CommonSocketPermission {
946 }
947}
948
949class_permission_enum! {
950 /// A well-known "netlink_netfilter_socket" class permission in SELinux policy that has a particular meaning in
951 /// policy enforcement hooks.
952 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
953 NetlinkNetfilterSocketPermission extends CommonSocketPermission {
954 }
955}
956
957class_permission_enum! {
958 /// A well-known "netlink_ip6fw_socket" class permission in SELinux policy that has a particular meaning in
959 /// policy enforcement hooks.
960 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
961 NetlinkIp6FwSocketPermission extends CommonSocketPermission {
962 }
963}
964
965class_permission_enum! {
966 /// A well-known "netlink_dnrt_socket" class permission in SELinux policy that has a particular meaning in
967 /// policy enforcement hooks.
968 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
969 NetlinkDnrtSocketPermission extends CommonSocketPermission {
970 }
971}
972
973class_permission_enum! {
974 /// A well-known "netlink_kobject_uevent_socket" class permission in SELinux policy that has a particular meaning in
975 /// policy enforcement hooks.
976 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
977 NetlinkKobjectUeventSocketPermission extends CommonSocketPermission {
978 }
979}
980
981class_permission_enum! {
982 /// A well-known "netlink_generic_socket" class permission in SELinux policy that has a particular meaning in
983 /// policy enforcement hooks.
984 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
985 NetlinkGenericSocketPermission extends CommonSocketPermission {
986 }
987}
988
989class_permission_enum! {
990 /// A well-known "netlink_scsitransport_socket" class permission in SELinux policy that has a particular meaning in
991 /// policy enforcement hooks.
992 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
993 NetlinkScsitransportSocketPermission extends CommonSocketPermission {
994 }
995}
996
997class_permission_enum! {
998 /// A well-known "netlink_rdma_socket" class permission in SELinux policy that has a particular meaning in
999 /// policy enforcement hooks.
1000 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1001 NetlinkRdmaSocketPermission extends CommonSocketPermission {
1002 }
1003}
1004
1005class_permission_enum! {
1006 /// A well-known "netlink_crypto_socket" class permission in SELinux policy that has a particular meaning in
1007 /// policy enforcement hooks.
1008 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1009 NetlinkCryptoSocketPermission extends CommonSocketPermission {
1010 }
1011}
1012
1013class_permission_enum! {
1014 /// A well-known "packet_socket" class permission in SELinux policy that has a particular meaning in
1015 /// policy enforcement hooks.
1016 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1017 PacketSocketPermission extends CommonSocketPermission {
1018 }
1019}
1020
1021class_permission_enum! {
1022 /// A well-known "rawip_socket" class permission in SELinux policy that has a particular meaning in
1023 /// policy enforcement hooks.
1024 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1025 RawIpSocketPermission extends CommonSocketPermission {
1026 }
1027}
1028
1029class_permission_enum! {
1030 /// A well-known "socket" class permission in SELinux policy that has a particular meaning in
1031 /// policy enforcement hooks.
1032 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1033 SocketPermission extends CommonSocketPermission {
1034 }
1035}
1036
1037class_permission_enum! {
1038 /// A well-known "tcp_socket" class permission in SELinux policy that has a particular meaning in
1039 /// policy enforcement hooks.
1040 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1041 TcpSocketPermission extends CommonSocketPermission {
1042 }
1043}
1044
1045class_permission_enum! {
1046 /// A well-known "udp_socket" class permission in SELinux policy that has a particular meaning in
1047 /// policy enforcement hooks.
1048 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1049 UdpSocketPermission extends CommonSocketPermission {
1050 }
1051}
1052
1053class_permission_enum! {
1054 /// A well-known "unix_stream_socket" class permission in SELinux policy that has a particular meaning in
1055 /// policy enforcement hooks.
1056 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1057 UnixStreamSocketPermission extends CommonSocketPermission {
1058 }
1059}
1060
1061class_permission_enum! {
1062 /// A well-known "unix_dgram_socket" class permission in SELinux policy that has a particular meaning in
1063 /// policy enforcement hooks.
1064 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1065 UnixDgramSocketPermission extends CommonSocketPermission {
1066 }
1067}
1068
1069class_permission_enum! {
1070 /// A well-known "vsock_socket" class permission in SELinux policy that has a particular meaning in
1071 /// policy enforcement hooks.
1072 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1073 VsockSocketPermission extends CommonSocketPermission {
1074 }
1075}
1076
1077common_permission_enum! {
1078 /// Permissions common to all file-like object classes (e.g. "lnk_file", "dir"). These are
1079 /// combined with a specific `FileClass` by policy enforcement hooks, to obtain class-affine
1080 /// permission values to check.
1081 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1082 CommonFilePermission extends CommonFsNodePermission {
1083 // keep-sorted start
1084 /// Permission to execute a file with domain transition.
1085 Execute("execute"),
1086 /// Permissions to create hard link.
1087 Link("link"),
1088 /// Permission to use as mount point; only useful for directories and files.
1089 MountOn("mounton"),
1090 /// Permission to open a file.
1091 Open("open"),
1092 /// Permission to rename a file.
1093 Rename("rename"),
1094 /// Permission to delete a file or remove a hard link.
1095 Unlink("unlink"),
1096 // keep-sorted end
1097 }
1098}
1099
1100impl CommonFilePermission {
1101 /// Returns the `class`-affine `Permission` value corresponding to this common permission.
1102 /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
1103 /// "allow" rules for the correct target object class.
1104 pub fn for_class(&self, class: FileClass) -> Permission {
1105 match class {
1106 FileClass::AnonFsNode => AnonFsNodePermission::Common(self.clone()).into(),
1107 FileClass::Block => BlockFilePermission::Common(self.clone()).into(),
1108 FileClass::Character => CharacterFilePermission::Common(self.clone()).into(),
1109 FileClass::Dir => DirPermission::Common(self.clone()).into(),
1110 FileClass::Fifo => FifoFilePermission::Common(self.clone()).into(),
1111 FileClass::File => FilePermission::Common(self.clone()).into(),
1112 FileClass::Link => LinkFilePermission::Common(self.clone()).into(),
1113 FileClass::SockFile => SockFilePermission::Common(self.clone()).into(),
1114 }
1115 }
1116}
1117
1118class_permission_enum! {
1119 /// A well-known "anon_file" class permission used to manage special file-like nodes not linked
1120 /// into any directory structures.
1121 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1122 AnonFsNodePermission extends CommonFilePermission {
1123 }
1124}
1125
1126class_permission_enum! {
1127 /// A well-known "blk_file" class permission in SELinux policy that has a particular meaning in
1128 /// policy enforcement hooks.
1129 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1130 BlockFilePermission extends CommonFilePermission {
1131 }
1132}
1133
1134class_permission_enum! {
1135 /// A well-known "chr_file" class permission in SELinux policy that has a particular meaning in
1136 /// policy enforcement hooks.
1137 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1138 CharacterFilePermission extends CommonFilePermission {
1139 }
1140}
1141
1142class_permission_enum! {
1143 /// A well-known "dir" class permission in SELinux policy that has a particular meaning in
1144 /// policy enforcement hooks.
1145 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1146 DirPermission extends CommonFilePermission {
1147 // keep-sorted start
1148 /// Permission to add a file to the directory.
1149 AddName("add_name"),
1150 /// Permission to remove a directory.
1151 RemoveDir("rmdir"),
1152 /// Permission to remove an entry from a directory.
1153 RemoveName("remove_name"),
1154 /// Permission to change parent directory.
1155 Reparent("reparent"),
1156 /// Search access to the directory.
1157 Search("search"),
1158 // keep-sorted end
1159 }
1160}
1161
1162class_permission_enum! {
1163 /// A well-known "fd" class permission in SELinux policy that has a particular meaning in policy
1164 /// enforcement hooks.
1165 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1166 FdPermission {
1167 // keep-sorted start
1168 /// Permission to use file descriptors copied/retained/inherited from another security
1169 /// context. This permission is generally used to control whether an `exec*()` call from a
1170 /// cloned process that retained a copy of the file descriptor table should succeed.
1171 Use("use"),
1172 // keep-sorted end
1173 }
1174}
1175
1176class_permission_enum! {
1177 /// A well-known "bpf" class permission in SELinux policy that has a particular meaning in
1178 /// policy enforcement hooks.
1179 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1180 BpfPermission {
1181 // keep-sorted start
1182 /// Permission to create a map.
1183 MapCreate("map_create"),
1184 /// Permission to read from a map.
1185 MapRead("map_read"),
1186 /// Permission to write on a map.
1187 MapWrite("map_write"),
1188 /// Permission to load a program.
1189 ProgLoad("prog_load"),
1190 /// Permission to run a program.
1191 ProgRun("prog_run"),
1192 // keep-sorted end
1193 }
1194}
1195
1196class_permission_enum! {
1197 /// A well-known "fifo_file" class permission in SELinux policy that has a particular meaning in
1198 /// policy enforcement hooks.
1199 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1200 FifoFilePermission extends CommonFilePermission {
1201 }
1202}
1203
1204class_permission_enum! {
1205 /// A well-known "file" class permission in SELinux policy that has a particular meaning in
1206 /// policy enforcement hooks.
1207 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1208 FilePermission extends CommonFilePermission {
1209 // keep-sorted start
1210 /// Permission to use a file as an entry point into the new domain on transition.
1211 Entrypoint("entrypoint"),
1212 /// Permission to use a file as an entry point to the calling domain without performing a
1213 /// transition.
1214 ExecuteNoTrans("execute_no_trans"),
1215 // keep-sorted end
1216 }
1217}
1218
1219class_permission_enum! {
1220 /// A well-known "filesystem" class permission in SELinux policy that has a particular meaning in
1221 /// policy enforcement hooks.
1222 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1223 FileSystemPermission {
1224 // keep-sorted start
1225 /// Permission to associate a file to the filesystem.
1226 Associate("associate"),
1227 /// Permission to get filesystem attributes.
1228 GetAttr("getattr"),
1229 /// Permission mount a filesystem.
1230 Mount("mount"),
1231 /// Permission to remount a filesystem with different flags.
1232 Remount("remount"),
1233 /// Permission to unmount a filesystem.
1234 Unmount("unmount"),
1235 // keep-sorted end
1236 }
1237}
1238
1239class_permission_enum! {
1240 /// A well-known "lnk_file" class permission in SELinux policy that has a particular meaning in
1241 /// policy enforcement hooks.
1242 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1243 LinkFilePermission extends CommonFilePermission {
1244 }
1245}
1246
1247class_permission_enum! {
1248 /// A well-known "sock_file" class permission in SELinux policy that has a particular meaning in
1249 /// policy enforcement hooks.
1250 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1251 SockFilePermission extends CommonFilePermission {
1252 }
1253}
1254
1255class_permission_enum! {
1256 /// A well-known "process" class permission in SELinux policy that has a particular meaning in
1257 /// policy enforcement hooks.
1258 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1259 ProcessPermission {
1260 // keep-sorted start
1261 /// Permission to dynamically transition a process to a different security domain.
1262 DynTransition("dyntransition"),
1263 /// Permission to fork the current running process.
1264 Fork("fork"),
1265 /// Permission to get the process group ID.
1266 GetPgid("getpgid"),
1267 /// Permission to get the resource limits on a process.
1268 GetRlimit("getrlimit"),
1269 /// Permission to get scheduling policy currently applied to a process.
1270 GetSched("getsched"),
1271 /// Permission to get the session ID.
1272 GetSession("getsession"),
1273 /// Permission to trace a process.
1274 Ptrace("ptrace"),
1275 /// Permission to inherit the parent process's resource limits on exec.
1276 RlimitInh("rlimitinh"),
1277 /// Permission to set the calling task's current Security Context.
1278 /// The "dyntransition" permission separately limits which Contexts "setcurrent" may be used to transition to.
1279 SetCurrent("setcurrent"),
1280 /// Permission to set the Security Context used by `exec()`.
1281 SetExec("setexec"),
1282 /// Permission to set the Security Context used when creating filesystem objects.
1283 SetFsCreate("setfscreate"),
1284 /// Permission to set the Security Context used when creating kernel keyrings.
1285 SetKeyCreate("setkeycreate"),
1286 /// Permission to set the process group ID.
1287 SetPgid("setpgid"),
1288 /// Permission to set the resource limits on a process.
1289 SetRlimit("setrlimit"),
1290 /// Permission to set scheduling policy for a process.
1291 SetSched("setsched"),
1292 /// Permission to set the Security Context used when creating new labeled sockets.
1293 SetSockCreate("setsockcreate"),
1294 /// Permission to share resources (e.g. FD table, address-space, etc) with a process.
1295 Share("share"),
1296 /// Permission to send SIGCHLD to a process.
1297 SigChld("sigchld"),
1298 /// Permission to send SIGKILL to a process.
1299 SigKill("sigkill"),
1300 /// Permission to send SIGSTOP to a process.
1301 SigStop("sigstop"),
1302 /// Permission to send a signal other than SIGKILL, SIGSTOP, or SIGCHLD to a process.
1303 Signal("signal"),
1304 /// Permission to transition to a different security domain.
1305 Transition("transition"),
1306 // keep-sorted end
1307 }
1308}
1309
1310class_permission_enum! {
1311 /// A well-known "security" class permission in SELinux policy, used to control access to
1312 /// sensitive administrative and query API surfaces in the "selinuxfs".
1313 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1314 SecurityPermission {
1315 // keep-sorted start
1316 /// Permission to validate Security Context using the "context" API.
1317 CheckContext("check_context"),
1318 /// Permission to compute access vectors via the "access" API.
1319 ComputeAv("compute_av"),
1320 /// Permission to compute security contexts for newly created objects via "create".
1321 ComputeCreate("compute_create"),
1322 /// Permission to load a new binary policy into the kernel via the "load" API.
1323 LoadPolicy("load_policy"),
1324 /// Permission to commit booleans to control conditional elements of the policy.
1325 SetBool("setbool"),
1326 /// Permission to change the way permissions are validated for `mmap()` operations.
1327 SetCheckReqProt("setcheckreqprot"),
1328 /// Permission to switch the system between permissive and enforcing modes, via "enforce".
1329 SetEnforce("setenforce"),
1330 // keep-sorted end
1331 }
1332}
1333
1334/// Initial Security Identifier (SID) values defined by the SELinux Reference Policy.
1335/// Where the SELinux Reference Policy retains definitions for some deprecated initial SIDs, this
1336/// enum omits deprecated entries for clarity.
1337#[repr(u64)]
1338enum ReferenceInitialSid {
1339 Kernel = 1,
1340 Security = 2,
1341 Unlabeled = 3,
1342 _Fs = 4,
1343 File = 5,
1344 _AnySocket = 6,
1345 _Port = 7,
1346 _Netif = 8,
1347 _Netmsg = 9,
1348 _Node = 10,
1349 _Sysctl = 15,
1350 _Devnull = 25,
1351
1352 FirstUnused,
1353}
1354
1355/// Lowest Security Identifier value guaranteed not to be used by this
1356/// implementation to refer to an initial Security Context.
1357pub const FIRST_UNUSED_SID: u32 = ReferenceInitialSid::FirstUnused as u32;
1358
1359macro_rules! initial_sid_enum {
1360 ($(#[$meta:meta])* $name:ident {
1361 $($(#[$variant_meta:meta])* $variant:ident ($variant_name: literal)),*,
1362 }) => {
1363 $(#[$meta])*
1364 pub enum $name {
1365 $($(#[$variant_meta])* $variant = ReferenceInitialSid::$variant as isize),*
1366 }
1367
1368 impl $name {
1369 pub fn all_variants() -> Vec<Self> {
1370 vec![
1371 $($name::$variant),*
1372 ]
1373 }
1374
1375 pub fn name(&self) -> &'static str {
1376 match self {
1377 $($name::$variant => $variant_name),*
1378 }
1379 }
1380 }
1381 }
1382}
1383
1384initial_sid_enum! {
1385/// Initial Security Identifier (SID) values actually used by this implementation.
1386/// These must be present in the policy, for it to be valid.
1387#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1388 InitialSid {
1389 // keep-sorted start
1390 File("file"),
1391 Kernel("kernel"),
1392 Security("security"),
1393 Unlabeled("unlabeled"),
1394 // keep-sorted end
1395 }
1396}
1397
1398/// A borrowed byte slice that contains no `NUL` characters by truncating the input slice at the
1399/// first `NUL` (if any) upon construction.
1400#[derive(Clone, Copy, Debug, PartialEq)]
1401pub struct NullessByteStr<'a>(&'a [u8]);
1402
1403impl<'a> NullessByteStr<'a> {
1404 /// Returns a non-null-terminated representation of the security context string.
1405 pub fn as_bytes(&self) -> &[u8] {
1406 &self.0
1407 }
1408}
1409
1410impl<'a, S: AsRef<[u8]> + ?Sized> From<&'a S> for NullessByteStr<'a> {
1411 /// Any `AsRef<[u8]>` can be processed into a [`NullessByteStr`]. The [`NullessByteStr`] will
1412 /// retain everything up to (but not including) a null character, or else the complete byte
1413 /// string.
1414 fn from(s: &'a S) -> Self {
1415 let value = s.as_ref();
1416 match value.iter().position(|c| *c == 0) {
1417 Some(end) => Self(&value[..end]),
1418 None => Self(value),
1419 }
1420 }
1421}
1422
1423#[derive(Clone, Debug, PartialEq)]
1424pub struct FileSystemMountSids {
1425 pub context: Option<SecurityId>,
1426 pub fs_context: Option<SecurityId>,
1427 pub def_context: Option<SecurityId>,
1428 pub root_context: Option<SecurityId>,
1429}
1430
1431#[derive(Clone, Debug, PartialEq)]
1432pub struct FileSystemLabel {
1433 pub sid: SecurityId,
1434 pub scheme: FileSystemLabelingScheme,
1435 // Sids obtained by parsing the mount options of the FileSystem.
1436 pub mount_sids: FileSystemMountSids,
1437}
1438
1439#[derive(Clone, Debug, PartialEq)]
1440pub enum FileSystemLabelingScheme {
1441 /// This filesystem was mounted with "context=".
1442 Mountpoint { sid: SecurityId },
1443 /// This filesystem has an "fs_use_xattr", "fs_use_task", or "fs_use_trans" entry in the
1444 /// policy. `root_sid` identifies the context for the root of the filesystem and
1445 /// `computed_def_sid` identifies the context to use for unlabeled files in the filesystem
1446 /// (the "default context").
1447 FsUse { fs_use_type: FsUseType, computed_def_sid: SecurityId },
1448 /// This filesystem has one or more "genfscon" statements associated with it in the policy.
1449 GenFsCon,
1450}
1451
1452/// SELinux security context-related filesystem mount options. These options are documented in the
1453/// `context=context, fscontext=context, defcontext=context, and rootcontext=context` section of
1454/// the `mount(8)` manpage.
1455#[derive(Clone, Debug, Default, PartialEq)]
1456pub struct FileSystemMountOptions {
1457 /// Specifies the effective security context to use for all nodes in the filesystem, and the
1458 /// filesystem itself. If the filesystem already contains security attributes then these are
1459 /// ignored. May not be combined with any of the other options.
1460 pub context: Option<Vec<u8>>,
1461 /// Specifies an effective security context to use for un-labeled nodes in the filesystem,
1462 /// rather than falling-back to the policy-defined "file" context.
1463 pub def_context: Option<Vec<u8>>,
1464 /// The value of the `fscontext=[security-context]` mount option. This option is used to
1465 /// label the filesystem (superblock) itself.
1466 pub fs_context: Option<Vec<u8>>,
1467 /// The value of the `rootcontext=[security-context]` mount option. This option is used to
1468 /// (re)label the inode located at the filesystem mountpoint.
1469 pub root_context: Option<Vec<u8>>,
1470}
1471
1472/// Status information parameter for the [`SeLinuxStatusPublisher`] interface.
1473pub struct SeLinuxStatus {
1474 /// SELinux-wide enforcing vs. permissive mode bit.
1475 pub is_enforcing: bool,
1476 /// Number of times the policy has been changed since SELinux started.
1477 pub change_count: u32,
1478 /// Bit indicating whether operations unknown SELinux abstractions will be denied.
1479 pub deny_unknown: bool,
1480}
1481
1482/// Interface for security server to interact with selinuxfs status file.
1483pub trait SeLinuxStatusPublisher: Send {
1484 /// Sets the value part of the associated selinuxfs status file.
1485 fn set_status(&mut self, policy_status: SeLinuxStatus);
1486}
1487
1488#[cfg(test)]
1489mod tests {
1490 use super::*;
1491
1492 #[test]
1493 fn object_class_permissions() {
1494 assert_eq!(AbstractObjectClass::Unspecified, AbstractObjectClass::default());
1495 assert_eq!(
1496 AbstractObjectClass::Custom(String::from("my_class")),
1497 String::from("my_class").into()
1498 );
1499 for variant in ProcessPermission::all_variants().into_iter() {
1500 assert_eq!(ObjectClass::Process, variant.class());
1501 assert_eq!("process", variant.class().name());
1502 let permission: Permission = variant.clone().into();
1503 assert_eq!(Permission::Process(variant.clone()), permission);
1504 assert_eq!(
1505 AbstractPermission::System(Permission::Process(variant.clone())),
1506 permission.into()
1507 );
1508 assert_eq!(AbstractObjectClass::System(ObjectClass::Process), variant.class().into());
1509 }
1510 }
1511
1512 #[test]
1513 fn nulless_byte_str_equivalence() {
1514 let unterminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0".into();
1515 let nul_terminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0\0".into();
1516 let nul_containing: NullessByteStr<'_> =
1517 b"u:object_r:test_valid_t:s0\0IGNORE THIS\0!\0".into();
1518
1519 for context in [nul_terminated, nul_containing] {
1520 assert_eq!(unterminated, context);
1521 assert_eq!(unterminated.as_bytes(), context.as_bytes());
1522 }
1523 }
1524}