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 Perfmon("perfmon"),
716 Syslog("syslog"),
717 WakeAlarm("wake_alarm"),
718
719 // keep-sorted end
720 }
721}
722
723class_permission_enum! {
724 /// A well-known "capability2" class permission in SELinux policy that has a particular meaning
725 /// in policy enforcement hooks.
726 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
727 Capability2Permission extends CommonCap2Permission {}
728}
729
730impl ForClass<Cap2Class> for CommonCap2Permission {
731 /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
732 /// This is used to allow hooks to resolve e.g. common "mac_admin" permission access based on
733 /// the "allow" rules for the correct target object class.
734 fn for_class(&self, class: Cap2Class) -> KernelPermission {
735 match class {
736 Cap2Class::Capability2 => Capability2Permission::Common(self.clone()).into(),
737 }
738 }
739}
740
741common_permission_enum! {
742 /// Permissions meaningful for all [`crate::vfs::FsNode`]s, whether file- or socket-like.
743 ///
744 /// This extra layer of common permissions is not reflected in the hierarchy defined by the
745 /// SELinux Reference Policy. Because even common permissions are mapped per-class, by name, to
746 /// the policy equivalents, the implementation and policy notions of common permissions need not
747 /// be identical.
748 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
749 CommonFsNodePermission {
750 // keep-sorted start
751 /// Permission to append to a file or socket.
752 Append("append"),
753 /// Pseudo-permission used in `dontaudit` access-rules to allow access checks to be made
754 /// between specific sources & targets without generating audit logs.
755 AuditAccess("audit_access"),
756 /// Permission to create a file or socket.
757 Create("create"),
758 /// Permission to query attributes, including uid, gid and extended attributes.
759 GetAttr("getattr"),
760 /// Permission to execute ioctls on the file or socket.
761 Ioctl("ioctl"),
762 /// Permission to set and unset file or socket locks.
763 Lock("lock"),
764 /// Permission to map a file.
765 Map("map"),
766 /// Permission to read content from a file or socket, as well as reading or following links.
767 Read("read"),
768 /// Permission checked against the existing label when updating a node's security label.
769 RelabelFrom("relabelfrom"),
770 /// Permission checked against the new label when updating a node's security label.
771 RelabelTo("relabelto"),
772 /// Permission to modify attributes, including uid, gid and extended attributes.
773 SetAttr("setattr"),
774 /// Permission to write contents to the file or socket.
775 Write("write"),
776 // keep-sorted end
777 }
778}
779
780impl<T: Into<FsNodeClass>> ForClass<T> for CommonFsNodePermission {
781 /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
782 /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
783 /// "allow" rules for the correct target object class.
784 fn for_class(&self, class: T) -> KernelPermission {
785 match class.into() {
786 FsNodeClass::File(file_class) => {
787 CommonFilePermission::Common(self.clone()).for_class(file_class)
788 }
789 FsNodeClass::Socket(sock_class) => {
790 CommonSocketPermission::Common(self.clone()).for_class(sock_class)
791 }
792 }
793 }
794}
795common_permission_enum! {
796 /// Permissions common to all socket-like object classes. These are combined with a specific
797 /// `SocketClass` by policy enforcement hooks, to obtain class-affine permission values.
798 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
799 CommonSocketPermission extends CommonFsNodePermission {
800 // keep-sorted start
801 /// Permission to accept a connection.
802 Accept("accept"),
803 /// Permission to bind to a name.
804 Bind("bind"),
805 /// Permission to initiate a connection.
806 Connect("connect"),
807 /// Permission to get socket options.
808 GetOpt("getopt"),
809 /// Permission to listen for connections.
810 Listen("listen"),
811 /// Permission to send datagrams to the socket.
812 SendTo("sendto"),
813 /// Permission to set socket options.
814 SetOpt("setopt"),
815 /// Permission to terminate connection.
816 Shutdown("shutdown"),
817 // keep-sorted end
818 }
819}
820
821impl ForClass<SocketClass> for CommonSocketPermission {
822 /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
823 /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
824 /// "allow" rules for the correct target object class.
825 fn for_class(&self, class: SocketClass) -> KernelPermission {
826 match class {
827 SocketClass::Key => KeySocketPermission::Common(self.clone()).into(),
828 SocketClass::Netlink => NetlinkSocketPermission::Common(self.clone()).into(),
829 SocketClass::NetlinkAudit => NetlinkAuditSocketPermission::Common(self.clone()).into(),
830 SocketClass::NetlinkConnector => {
831 NetlinkConnectorSocketPermission::Common(self.clone()).into()
832 }
833 SocketClass::NetlinkCrypto => {
834 NetlinkCryptoSocketPermission::Common(self.clone()).into()
835 }
836 SocketClass::NetlinkDnrt => NetlinkDnrtSocketPermission::Common(self.clone()).into(),
837 SocketClass::NetlinkFibLookup => {
838 NetlinkFibLookupSocketPermission::Common(self.clone()).into()
839 }
840 SocketClass::NetlinkFirewall => {
841 NetlinkFirewallSocketPermission::Common(self.clone()).into()
842 }
843 SocketClass::NetlinkGeneric => {
844 NetlinkGenericSocketPermission::Common(self.clone()).into()
845 }
846 SocketClass::NetlinkIp6Fw => NetlinkIp6FwSocketPermission::Common(self.clone()).into(),
847 SocketClass::NetlinkIscsi => NetlinkIscsiSocketPermission::Common(self.clone()).into(),
848 SocketClass::NetlinkKobjectUevent => {
849 NetlinkKobjectUeventSocketPermission::Common(self.clone()).into()
850 }
851 SocketClass::NetlinkNetfilter => {
852 NetlinkNetfilterSocketPermission::Common(self.clone()).into()
853 }
854 SocketClass::NetlinkNflog => NetlinkNflogSocketPermission::Common(self.clone()).into(),
855 SocketClass::NetlinkRdma => NetlinkRdmaSocketPermission::Common(self.clone()).into(),
856 SocketClass::NetlinkRoute => NetlinkRouteSocketPermission::Common(self.clone()).into(),
857 SocketClass::NetlinkScsitransport => {
858 NetlinkScsitransportSocketPermission::Common(self.clone()).into()
859 }
860 SocketClass::NetlinkSelinux => {
861 NetlinkSelinuxSocketPermission::Common(self.clone()).into()
862 }
863 SocketClass::NetlinkTcpDiag => {
864 NetlinkTcpDiagSocketPermission::Common(self.clone()).into()
865 }
866 SocketClass::NetlinkXfrm => NetlinkXfrmSocketPermission::Common(self.clone()).into(),
867 SocketClass::Packet => PacketSocketPermission::Common(self.clone()).into(),
868 SocketClass::RawIp => RawIpSocketPermission::Common(self.clone()).into(),
869 SocketClass::Socket => SocketPermission::Common(self.clone()).into(),
870 SocketClass::Tcp => TcpSocketPermission::Common(self.clone()).into(),
871 SocketClass::Udp => UdpSocketPermission::Common(self.clone()).into(),
872 SocketClass::UnixDgram => UnixDgramSocketPermission::Common(self.clone()).into(),
873 SocketClass::UnixStream => UnixStreamSocketPermission::Common(self.clone()).into(),
874 SocketClass::Vsock => VsockSocketPermission::Common(self.clone()).into(),
875 }
876 }
877}
878
879class_permission_enum! {
880 /// A well-known "key_socket" class permission in SELinux policy that has a particular meaning in
881 /// policy enforcement hooks.
882 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
883 KeySocketPermission extends CommonSocketPermission {
884 }
885}
886class_permission_enum! {
887 /// A well-known "netlink_socket" class permission in SELinux policy that has a particular meaning in
888 /// policy enforcement hooks.
889 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
890 NetlinkSocketPermission extends CommonSocketPermission {
891 }
892}
893
894class_permission_enum! {
895 /// A well-known "netlink_route_socket" class permission in SELinux policy that has a particular meaning in
896 /// policy enforcement hooks.
897 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
898 NetlinkRouteSocketPermission extends CommonSocketPermission {
899 // keep-sorted start
900 /// Permission for nlmsg xperms.
901 Nlmsg("nlmsg"),
902 /// Permission to read the kernel routing table.
903 NlmsgRead("nlmsg_read"),
904 /// Permission to write to the kernel routing table.
905 NlmsgWrite("nlmsg_write"),
906 // keep-sorted end
907 }
908}
909
910class_permission_enum! {
911 /// A well-known "netlink_firewall_socket" class permission in SELinux policy that has a particular meaning in
912 /// policy enforcement hooks.
913 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
914 NetlinkFirewallSocketPermission extends CommonSocketPermission {
915 }
916}
917
918class_permission_enum! {
919 /// A well-known "netlink_tcpdiag_socket" class permission in SELinux policy that has a particular meaning in
920 /// policy enforcement hooks.
921 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
922 NetlinkTcpDiagSocketPermission extends CommonSocketPermission {
923 // keep-sorted start
924 /// Permission for nlmsg xperms.
925 Nlmsg("nlmsg"),
926 /// Permission to request information about a protocol.
927 NlmsgRead("nlmsg_read"),
928 /// Permission to write netlink message.
929 NlmsgWrite("nlmsg_write"),
930 // keep-sorted end
931 }
932}
933
934class_permission_enum! {
935 /// A well-known "netlink_nflog_socket" class permission in SELinux policy that has a particular meaning in
936 /// policy enforcement hooks.
937 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
938 NetlinkNflogSocketPermission extends CommonSocketPermission {
939 }
940}
941
942class_permission_enum! {
943 /// A well-known "netlink_xfrm_socket" class permission in SELinux policy that has a particular meaning in
944 /// policy enforcement hooks.
945 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
946 NetlinkXfrmSocketPermission extends CommonSocketPermission {
947 // keep-sorted start
948 /// Permission for nlmsg xperms.
949 Nlmsg("nlmsg"),
950 /// Permission to get IPSec configuration information.
951 NlmsgRead("nlmsg_read"),
952 /// Permission to set IPSec configuration information.
953 NlmsgWrite("nlmsg_write"),
954 // keep-sorted end
955 }
956}
957
958class_permission_enum! {
959 /// A well-known "netlink_selinux_socket" class permission in SELinux policy that has a particular meaning in
960 /// policy enforcement hooks.
961 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
962 NetlinkSelinuxSocketPermission extends CommonSocketPermission {
963 }
964}
965
966class_permission_enum! {
967 /// A well-known "netlink_iscsi_socket" class permission in SELinux policy that has a particular meaning in
968 /// policy enforcement hooks.
969 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
970 NetlinkIscsiSocketPermission extends CommonSocketPermission {
971 }
972}
973
974class_permission_enum! {
975 /// A well-known "netlink_audit_socket" class permission in SELinux policy that has a particular meaning in
976 /// policy enforcement hooks.
977 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
978 NetlinkAuditSocketPermission extends CommonSocketPermission {
979 // keep-sorted start
980 /// Permission for nlmsg xperms.
981 Nlmsg("nlmsg"),
982 /// Permission to query status of audit service.
983 NlmsgRead("nlmsg_read"),
984 /// Permission to list auditing configuration rules.
985 NlmsgReadPriv("nlmsg_readpriv"),
986 /// Permission to send userspace audit messages to the audit service.
987 NlmsgRelay("nlmsg_relay"),
988 /// Permission to control TTY auditing.
989 NlmsgTtyAudit("nlmsg_tty_audit"),
990 /// Permission to update the audit service configuration.
991 NlmsgWrite("nlmsg_write"),
992 // keep-sorted end
993 }
994}
995
996class_permission_enum! {
997 /// A well-known "netlink_fib_lookup_socket" class permission in SELinux policy that has a particular meaning in
998 /// policy enforcement hooks.
999 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1000 NetlinkFibLookupSocketPermission extends CommonSocketPermission {
1001 }
1002}
1003
1004class_permission_enum! {
1005 /// A well-known "netlink_connector_socket" class permission in SELinux policy that has a particular meaning in
1006 /// policy enforcement hooks.
1007 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1008 NetlinkConnectorSocketPermission extends CommonSocketPermission {
1009 }
1010}
1011
1012class_permission_enum! {
1013 /// A well-known "netlink_netfilter_socket" class permission in SELinux policy that has a particular meaning in
1014 /// policy enforcement hooks.
1015 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1016 NetlinkNetfilterSocketPermission extends CommonSocketPermission {
1017 }
1018}
1019
1020class_permission_enum! {
1021 /// A well-known "netlink_ip6fw_socket" class permission in SELinux policy that has a particular meaning in
1022 /// policy enforcement hooks.
1023 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1024 NetlinkIp6FwSocketPermission extends CommonSocketPermission {
1025 }
1026}
1027
1028class_permission_enum! {
1029 /// A well-known "netlink_dnrt_socket" class permission in SELinux policy that has a particular meaning in
1030 /// policy enforcement hooks.
1031 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1032 NetlinkDnrtSocketPermission extends CommonSocketPermission {
1033 }
1034}
1035
1036class_permission_enum! {
1037 /// A well-known "netlink_kobject_uevent_socket" class permission in SELinux policy that has a particular meaning in
1038 /// policy enforcement hooks.
1039 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1040 NetlinkKobjectUeventSocketPermission extends CommonSocketPermission {
1041 }
1042}
1043
1044class_permission_enum! {
1045 /// A well-known "netlink_generic_socket" class permission in SELinux policy that has a particular meaning in
1046 /// policy enforcement hooks.
1047 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1048 NetlinkGenericSocketPermission extends CommonSocketPermission {
1049 }
1050}
1051
1052class_permission_enum! {
1053 /// A well-known "netlink_scsitransport_socket" class permission in SELinux policy that has a particular meaning in
1054 /// policy enforcement hooks.
1055 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1056 NetlinkScsitransportSocketPermission extends CommonSocketPermission {
1057 }
1058}
1059
1060class_permission_enum! {
1061 /// A well-known "netlink_rdma_socket" class permission in SELinux policy that has a particular meaning in
1062 /// policy enforcement hooks.
1063 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1064 NetlinkRdmaSocketPermission extends CommonSocketPermission {
1065 }
1066}
1067
1068class_permission_enum! {
1069 /// A well-known "netlink_crypto_socket" class permission in SELinux policy that has a particular meaning in
1070 /// policy enforcement hooks.
1071 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1072 NetlinkCryptoSocketPermission extends CommonSocketPermission {
1073 }
1074}
1075
1076class_permission_enum! {
1077 /// A well-known "packet_socket" class permission in SELinux policy that has a particular meaning in
1078 /// policy enforcement hooks.
1079 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1080 PacketSocketPermission extends CommonSocketPermission {
1081 }
1082}
1083
1084class_permission_enum! {
1085 /// A well-known "rawip_socket" class permission in SELinux policy that has a particular meaning in
1086 /// policy enforcement hooks.
1087 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1088 RawIpSocketPermission extends CommonSocketPermission {
1089 }
1090}
1091
1092class_permission_enum! {
1093 /// A well-known "socket" class permission in SELinux policy that has a particular meaning in
1094 /// policy enforcement hooks.
1095 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1096 SocketPermission extends CommonSocketPermission {
1097 }
1098}
1099
1100class_permission_enum! {
1101 /// A well-known "tcp_socket" class permission in SELinux policy that has a particular meaning in
1102 /// policy enforcement hooks.
1103 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1104 TcpSocketPermission extends CommonSocketPermission {
1105 }
1106}
1107
1108class_permission_enum! {
1109 /// A well-known "udp_socket" class permission in SELinux policy that has a particular meaning in
1110 /// policy enforcement hooks.
1111 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1112 UdpSocketPermission extends CommonSocketPermission {
1113 }
1114}
1115
1116class_permission_enum! {
1117 /// A well-known "unix_stream_socket" class permission in SELinux policy that has a particular meaning in
1118 /// policy enforcement hooks.
1119 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1120 UnixStreamSocketPermission extends CommonSocketPermission {
1121 // keep-sorted start
1122 /// Permission to connect a streaming Unix-domain socket.
1123 ConnectTo("connectto"),
1124 // keep-sorted end
1125 }
1126}
1127
1128class_permission_enum! {
1129 /// A well-known "unix_dgram_socket" class permission in SELinux policy that has a particular meaning in
1130 /// policy enforcement hooks.
1131 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1132 UnixDgramSocketPermission extends CommonSocketPermission {
1133 }
1134}
1135
1136class_permission_enum! {
1137 /// A well-known "vsock_socket" class permission in SELinux policy that has a particular meaning in
1138 /// policy enforcement hooks.
1139 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1140 VsockSocketPermission extends CommonSocketPermission {
1141 }
1142}
1143
1144common_permission_enum! {
1145 /// Permissions common to all file-like object classes (e.g. "lnk_file", "dir"). These are
1146 /// combined with a specific `FileClass` by policy enforcement hooks, to obtain class-affine
1147 /// permission values to check.
1148 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1149 CommonFilePermission extends CommonFsNodePermission {
1150 // keep-sorted start
1151 /// Permission to execute a file with domain transition.
1152 Execute("execute"),
1153 /// Permissions to create hard link.
1154 Link("link"),
1155 /// Permission to use as mount point; only useful for directories and files.
1156 MountOn("mounton"),
1157 /// Permission to open a file.
1158 Open("open"),
1159 /// Permission to rename a file.
1160 Rename("rename"),
1161 /// Permission to delete a file or remove a hard link.
1162 Unlink("unlink"),
1163 // keep-sorted end
1164 }
1165}
1166
1167impl ForClass<FileClass> for CommonFilePermission {
1168 /// Returns the `class`-affine `KernelPermission` value corresponding to this common permission.
1169 /// This is used to allow hooks to resolve e.g. common "read" permission access based on the
1170 /// "allow" rules for the correct target object class.
1171 fn for_class(&self, class: FileClass) -> KernelPermission {
1172 match class {
1173 FileClass::AnonFsNode => AnonFsNodePermission::Common(self.clone()).into(),
1174 FileClass::Block => BlockFilePermission::Common(self.clone()).into(),
1175 FileClass::Character => CharacterFilePermission::Common(self.clone()).into(),
1176 FileClass::Dir => DirPermission::Common(self.clone()).into(),
1177 FileClass::Fifo => FifoFilePermission::Common(self.clone()).into(),
1178 FileClass::File => FilePermission::Common(self.clone()).into(),
1179 FileClass::Link => LinkFilePermission::Common(self.clone()).into(),
1180 FileClass::SockFile => SockFilePermission::Common(self.clone()).into(),
1181 }
1182 }
1183}
1184
1185class_permission_enum! {
1186 /// A well-known "anon_file" class permission used to manage special file-like nodes not linked
1187 /// into any directory structures.
1188 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1189 AnonFsNodePermission extends CommonFilePermission {
1190 }
1191}
1192
1193class_permission_enum! {
1194 /// A well-known "binder" class permission in SELinux policy that has a particular meaning in
1195 /// policy enforcement hooks.
1196 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1197 BinderPermission {
1198 // keep-sorted start
1199 /// Permission to perform a binder IPC to a given target process.
1200 Call("call"),
1201 /// Permission to use a Binder connection created with a different security context.
1202 Impersonate("impersonate"),
1203 /// Permission to set oneself as a context manager.
1204 SetContextMgr("set_context_mgr"),
1205 /// Permission to transfer Binder objects as part of a Binder transaction.
1206 Transfer("transfer"),
1207 // keep-sorted end
1208 }
1209}
1210
1211class_permission_enum! {
1212 /// A well-known "blk_file" class permission in SELinux policy that has a particular meaning in
1213 /// policy enforcement hooks.
1214 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1215 BlockFilePermission extends CommonFilePermission {
1216 }
1217}
1218
1219class_permission_enum! {
1220 /// A well-known "chr_file" class permission in SELinux policy that has a particular meaning in
1221 /// policy enforcement hooks.
1222 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1223 CharacterFilePermission extends CommonFilePermission {
1224 }
1225}
1226
1227class_permission_enum! {
1228 /// A well-known "dir" class permission in SELinux policy that has a particular meaning in
1229 /// policy enforcement hooks.
1230 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1231 DirPermission extends CommonFilePermission {
1232 // keep-sorted start
1233 /// Permission to add a file to the directory.
1234 AddName("add_name"),
1235 /// Permission to remove a directory.
1236 RemoveDir("rmdir"),
1237 /// Permission to remove an entry from a directory.
1238 RemoveName("remove_name"),
1239 /// Permission to change parent directory.
1240 Reparent("reparent"),
1241 /// Search access to the directory.
1242 Search("search"),
1243 // keep-sorted end
1244 }
1245}
1246
1247class_permission_enum! {
1248 /// A well-known "fd" class permission in SELinux policy that has a particular meaning in policy
1249 /// enforcement hooks.
1250 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1251 FdPermission {
1252 // keep-sorted start
1253 /// Permission to use file descriptors copied/retained/inherited from another security
1254 /// context. This permission is generally used to control whether an `exec*()` call from a
1255 /// cloned process that retained a copy of the file descriptor table should succeed.
1256 Use("use"),
1257 // keep-sorted end
1258 }
1259}
1260
1261class_permission_enum! {
1262 /// A well-known "bpf" class permission in SELinux policy that has a particular meaning in
1263 /// policy enforcement hooks.
1264 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1265 BpfPermission {
1266 // keep-sorted start
1267 /// Permission to create a map.
1268 MapCreate("map_create"),
1269 /// Permission to read from a map.
1270 MapRead("map_read"),
1271 /// Permission to write on a map.
1272 MapWrite("map_write"),
1273 /// Permission to load a program.
1274 ProgLoad("prog_load"),
1275 /// Permission to run a program.
1276 ProgRun("prog_run"),
1277 // keep-sorted end
1278 }
1279}
1280
1281class_permission_enum! {
1282 /// A well-known "perf_event" class permission in SELinux policy that has a particular meaning
1283 /// in policy hooks.
1284 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1285 PerfEventPermission {
1286 // keep-sorted start
1287 /// Permission to monitor the cpu.
1288 Cpu("cpu"),
1289 /// Permission to monitor the kernel.
1290 Kernel("kernel"),
1291 /// Permission to open a perf event.
1292 Open("open"),
1293 /// Permission to read a perf event.
1294 Read("read"),
1295 /// Permission to set tracepoints.
1296 Tracepoint("tracepoint"),
1297 /// Permission to write a perf event.
1298 Write("write"),
1299 // keep-sorted end
1300 }
1301}
1302
1303class_permission_enum! {
1304 /// A well-known "fifo_file" class permission in SELinux policy that has a particular meaning in
1305 /// policy enforcement hooks.
1306 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1307 FifoFilePermission extends CommonFilePermission {
1308 }
1309}
1310
1311class_permission_enum! {
1312 /// A well-known "file" class permission in SELinux policy that has a particular meaning in
1313 /// policy enforcement hooks.
1314 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1315 FilePermission extends CommonFilePermission {
1316 // keep-sorted start
1317 /// Permission to use a file as an entry point into the new domain on transition.
1318 Entrypoint("entrypoint"),
1319 /// Permission to use a file as an entry point to the calling domain without performing a
1320 /// transition.
1321 ExecuteNoTrans("execute_no_trans"),
1322 // keep-sorted end
1323 }
1324}
1325
1326class_permission_enum! {
1327 /// A well-known "filesystem" class permission in SELinux policy that has a particular meaning in
1328 /// policy enforcement hooks.
1329 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1330 FileSystemPermission {
1331 // keep-sorted start
1332 /// Permission to associate a file to the filesystem.
1333 Associate("associate"),
1334 /// Permission to get filesystem attributes.
1335 GetAttr("getattr"),
1336 /// Permission mount a filesystem.
1337 Mount("mount"),
1338 /// Permission to remount a filesystem with different flags.
1339 Remount("remount"),
1340 /// Permission to unmount a filesystem.
1341 Unmount("unmount"),
1342 // keep-sorted end
1343 }
1344}
1345
1346class_permission_enum! {
1347 /// A well-known "lnk_file" class permission in SELinux policy that has a particular meaning in
1348 /// policy enforcement hooks.
1349 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1350 LinkFilePermission extends CommonFilePermission {
1351 }
1352}
1353
1354class_permission_enum! {
1355 /// A well-known "sock_file" class permission in SELinux policy that has a particular meaning in
1356 /// policy enforcement hooks.
1357 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1358 SockFilePermission extends CommonFilePermission {
1359 }
1360}
1361
1362class_permission_enum! {
1363 /// A well-known "process" class permission in SELinux policy that has a particular meaning in
1364 /// policy enforcement hooks.
1365 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1366 ProcessPermission {
1367 // keep-sorted start
1368 /// Permission to dynamically transition a process to a different security domain.
1369 DynTransition("dyntransition"),
1370 /// Permission to execute arbitrary code from the heap.
1371 ExecHeap("execheap"),
1372 /// Permission to execute arbitrary code from memory.
1373 ExecMem("execmem"),
1374 /// Permission to execute arbitrary code from the stack.
1375 ExecStack("execstack"),
1376 /// Permission to fork the current running process.
1377 Fork("fork"),
1378 /// Permission to get the process group ID.
1379 GetPgid("getpgid"),
1380 /// Permission to get the resource limits on a process.
1381 GetRlimit("getrlimit"),
1382 /// Permission to get scheduling policy currently applied to a process.
1383 GetSched("getsched"),
1384 /// Permission to get the session ID.
1385 GetSession("getsession"),
1386 /// Permission to trace a process.
1387 Ptrace("ptrace"),
1388 /// Permission to inherit the parent process's resource limits on exec.
1389 RlimitInh("rlimitinh"),
1390 /// Permission to set the calling task's current Security Context.
1391 /// The "dyntransition" permission separately limits which Contexts "setcurrent" may be used to transition to.
1392 SetCurrent("setcurrent"),
1393 /// Permission to set the Security Context used by `exec()`.
1394 SetExec("setexec"),
1395 /// Permission to set the Security Context used when creating filesystem objects.
1396 SetFsCreate("setfscreate"),
1397 /// Permission to set the Security Context used when creating kernel keyrings.
1398 SetKeyCreate("setkeycreate"),
1399 /// Permission to set the process group ID.
1400 SetPgid("setpgid"),
1401 /// Permission to set the resource limits on a process.
1402 SetRlimit("setrlimit"),
1403 /// Permission to set scheduling policy for a process.
1404 SetSched("setsched"),
1405 /// Permission to set the Security Context used when creating new labeled sockets.
1406 SetSockCreate("setsockcreate"),
1407 /// Permission to share resources (e.g. FD table, address-space, etc) with a process.
1408 Share("share"),
1409 /// Permission to send SIGCHLD to a process.
1410 SigChld("sigchld"),
1411 /// Permission to inherit the parent process's signal state.
1412 SigInh("siginh"),
1413 /// Permission to send SIGKILL to a process.
1414 SigKill("sigkill"),
1415 /// Permission to send SIGSTOP to a process.
1416 SigStop("sigstop"),
1417 /// Permission to send a signal other than SIGKILL, SIGSTOP, or SIGCHLD to a process.
1418 Signal("signal"),
1419 /// Permission to transition to a different security domain.
1420 Transition("transition"),
1421 // keep-sorted end
1422 }
1423}
1424
1425class_permission_enum! {
1426 /// A well-known "security" class permission in SELinux policy, used to control access to
1427 /// sensitive administrative and query API surfaces in the "selinuxfs".
1428 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1429 SecurityPermission {
1430 // keep-sorted start
1431 /// Permission to validate Security Context using the "context" API.
1432 CheckContext("check_context"),
1433 /// Permission to compute access vectors via the "access" API.
1434 ComputeAv("compute_av"),
1435 /// Permission to compute security contexts based on `type_transition` rules via "create".
1436 ComputeCreate("compute_create"),
1437 /// Permission to compute security contexts based on `type_member` rules via "member".
1438 ComputeMember("compute_member"),
1439 /// Permission to compute security contexts based on `type_change` rules via "relabel".
1440 ComputeRelabel("compute_relabel"),
1441 /// Permission to compute user decisions via "user".
1442 ComputeUser("compute_user"),
1443 /// Permission to load a new binary policy into the kernel via the "load" API.
1444 LoadPolicy("load_policy"),
1445 /// Permission to commit booleans to control conditional elements of the policy.
1446 SetBool("setbool"),
1447 /// Permission to change the way permissions are validated for `mmap()` operations.
1448 SetCheckReqProt("setcheckreqprot"),
1449 /// Permission to switch the system between permissive and enforcing modes, via "enforce".
1450 SetEnforce("setenforce"),
1451 // keep-sorted end
1452 }
1453}
1454
1455class_permission_enum! {
1456 /// A well-known "system" class permission in SELinux policy, used to control access to
1457 /// sensitive administrative and query API surfaces in the "selinuxfs".
1458 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
1459 SystemPermission {
1460 // keep-sorted start
1461 /// Permission to use the syslog(2) CONSOLE action types.
1462 SyslogConsole("syslog_console"),
1463 /// Permission to use other syslog(2) action types.
1464 SyslogMod("syslog_mod"),
1465 /// Permission to use the syslog(2) READ_ALL related action types.
1466 SyslogRead("syslog_read"),
1467 // keep-sorted end
1468 }
1469}
1470
1471/// Initial Security Identifier (SID) values defined by the SELinux Reference Policy.
1472/// Where the SELinux Reference Policy retains definitions for some deprecated initial SIDs, this
1473/// enum omits deprecated entries for clarity.
1474#[repr(u64)]
1475enum ReferenceInitialSid {
1476 Kernel = 1,
1477 Security = 2,
1478 Unlabeled = 3,
1479 _Fs = 4,
1480 File = 5,
1481 _Port = 9,
1482 _Netif = 10,
1483 _Netmsg = 11,
1484 _Node = 12,
1485 _Sysctl = 17,
1486 Devnull = 27,
1487
1488 FirstUnused,
1489}
1490
1491/// Lowest Security Identifier value guaranteed not to be used by this
1492/// implementation to refer to an initial Security Context.
1493pub const FIRST_UNUSED_SID: u32 = ReferenceInitialSid::FirstUnused as u32;
1494
1495macro_rules! initial_sid_enum {
1496 ($(#[$meta:meta])* $name:ident {
1497 $($(#[$variant_meta:meta])* $variant:ident ($variant_name: literal)),*,
1498 }) => {
1499 $(#[$meta])*
1500 pub enum $name {
1501 $($(#[$variant_meta])* $variant = ReferenceInitialSid::$variant as isize),*
1502 }
1503
1504 impl $name {
1505 pub fn all_variants() -> &'static [Self] {
1506 &[
1507 $($name::$variant),*
1508 ]
1509 }
1510
1511 pub fn name(&self) -> &'static str {
1512 match self {
1513 $($name::$variant => $variant_name),*
1514 }
1515 }
1516 }
1517 }
1518}
1519
1520initial_sid_enum! {
1521/// Initial Security Identifier (SID) values actually used by this implementation.
1522/// These must be present in the policy, for it to be valid.
1523#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
1524 InitialSid {
1525 // keep-sorted start
1526 Devnull("devnull"),
1527 File("file"),
1528 Kernel("kernel"),
1529 Security("security"),
1530 Unlabeled("unlabeled"),
1531 // keep-sorted end
1532 }
1533}
1534
1535/// A borrowed byte slice that contains no `NUL` characters by truncating the input slice at the
1536/// first `NUL` (if any) upon construction.
1537#[derive(Clone, Copy, Debug, PartialEq)]
1538pub struct NullessByteStr<'a>(&'a [u8]);
1539
1540impl<'a> NullessByteStr<'a> {
1541 /// Returns a non-null-terminated representation of the security context string.
1542 pub fn as_bytes(&self) -> &[u8] {
1543 &self.0
1544 }
1545}
1546
1547impl<'a, S: AsRef<[u8]> + ?Sized> From<&'a S> for NullessByteStr<'a> {
1548 /// Any `AsRef<[u8]>` can be processed into a [`NullessByteStr`]. The [`NullessByteStr`] will
1549 /// retain everything up to (but not including) a null character, or else the complete byte
1550 /// string.
1551 fn from(s: &'a S) -> Self {
1552 let value = s.as_ref();
1553 match value.iter().position(|c| *c == 0) {
1554 Some(end) => Self(&value[..end]),
1555 None => Self(value),
1556 }
1557 }
1558}
1559
1560#[derive(Clone, Debug, PartialEq)]
1561pub struct FileSystemMountSids {
1562 pub context: Option<SecurityId>,
1563 pub fs_context: Option<SecurityId>,
1564 pub def_context: Option<SecurityId>,
1565 pub root_context: Option<SecurityId>,
1566}
1567
1568#[derive(Clone, Debug, PartialEq)]
1569pub struct FileSystemLabel {
1570 pub sid: SecurityId,
1571 pub scheme: FileSystemLabelingScheme,
1572 // Sids obtained by parsing the mount options of the FileSystem.
1573 pub mount_sids: FileSystemMountSids,
1574}
1575
1576#[derive(Clone, Debug, PartialEq)]
1577pub enum FileSystemLabelingScheme {
1578 /// This filesystem was mounted with "context=".
1579 Mountpoint { sid: SecurityId },
1580 /// This filesystem has an "fs_use_xattr", "fs_use_task", or "fs_use_trans" entry in the
1581 /// policy. If the `fs_use_type` is "fs_use_xattr" then the `default_sid` specifies the SID
1582 /// with which to label `FsNode`s of files that do not have the "security.selinux" xattr.
1583 FsUse { fs_use_type: FsUseType, default_sid: SecurityId },
1584 /// This filesystem has one or more "genfscon" statements associated with it in the policy.
1585 GenFsCon,
1586}
1587
1588/// SELinux security context-related filesystem mount options. These options are documented in the
1589/// `context=context, fscontext=context, defcontext=context, and rootcontext=context` section of
1590/// the `mount(8)` manpage.
1591#[derive(Clone, Debug, Default, PartialEq)]
1592pub struct FileSystemMountOptions {
1593 /// Specifies the effective security context to use for all nodes in the filesystem, and the
1594 /// filesystem itself. If the filesystem already contains security attributes then these are
1595 /// ignored. May not be combined with any of the other options.
1596 pub context: Option<Vec<u8>>,
1597 /// Specifies an effective security context to use for un-labeled nodes in the filesystem,
1598 /// rather than falling-back to the policy-defined "file" context.
1599 pub def_context: Option<Vec<u8>>,
1600 /// The value of the `fscontext=[security-context]` mount option. This option is used to
1601 /// label the filesystem (superblock) itself.
1602 pub fs_context: Option<Vec<u8>>,
1603 /// The value of the `rootcontext=[security-context]` mount option. This option is used to
1604 /// (re)label the inode located at the filesystem mountpoint.
1605 pub root_context: Option<Vec<u8>>,
1606}
1607
1608/// Status information parameter for the [`SeLinuxStatusPublisher`] interface.
1609pub struct SeLinuxStatus {
1610 /// SELinux-wide enforcing vs. permissive mode bit.
1611 pub is_enforcing: bool,
1612 /// Number of times the policy has been changed since SELinux started.
1613 pub change_count: u32,
1614 /// Bit indicating whether operations unknown SELinux abstractions will be denied.
1615 pub deny_unknown: bool,
1616}
1617
1618/// Interface for security server to interact with selinuxfs status file.
1619pub trait SeLinuxStatusPublisher: Send + Sync {
1620 /// Sets the value part of the associated selinuxfs status file.
1621 fn set_status(&mut self, policy_status: SeLinuxStatus);
1622}
1623
1624#[cfg(test)]
1625mod tests {
1626 use super::*;
1627
1628 #[test]
1629 fn object_class_permissions() {
1630 let test_class_id = ClassId::new(NonZeroU32::new(20).unwrap());
1631 assert_eq!(ObjectClass::ClassId(test_class_id), test_class_id.into());
1632 for variant in ProcessPermission::all_variants().into_iter() {
1633 assert_eq!(KernelClass::Process, variant.class());
1634 assert_eq!("process", variant.class().name());
1635 let permission: KernelPermission = variant.clone().into();
1636 assert_eq!(KernelPermission::Process(variant.clone()), permission);
1637 assert_eq!(ObjectClass::Kernel(KernelClass::Process), variant.class().into());
1638 }
1639 }
1640
1641 #[test]
1642 fn nulless_byte_str_equivalence() {
1643 let unterminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0".into();
1644 let nul_terminated: NullessByteStr<'_> = b"u:object_r:test_valid_t:s0\0".into();
1645 let nul_containing: NullessByteStr<'_> =
1646 b"u:object_r:test_valid_t:s0\0IGNORE THIS\0!\0".into();
1647
1648 for context in [nul_terminated, nul_containing] {
1649 assert_eq!(unterminated, context);
1650 assert_eq!(unterminated.as_bytes(), context.as_bytes());
1651 }
1652 }
1653}