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