1#![allow(non_upper_case_globals)]
7
8pub(super) mod audit;
9pub(super) mod binder;
10pub(super) mod bpf;
11pub(super) mod file;
12pub(super) mod fs_node;
13pub(super) mod netlink_socket;
14pub(super) mod perf_event;
15pub(super) mod selinuxfs;
16pub(super) mod socket;
17pub(super) mod superblock;
18pub(super) mod task;
19pub(super) mod testing;
20
21use super::PermissionFlags;
22use crate::task::{CurrentTask, TaskPersistentInfo};
23use crate::vfs::{DirEntry, FileHandle, FileObject, FileSystem, FileSystemOps, FsNode};
24use audit::{Auditable, audit_decision, audit_todo_decision};
25use fuchsia_rcu::{RcuCell, RcuReadGuard};
26use indexmap::IndexSet;
27use selinux::permission_check::PermissionCheck;
28use selinux::policy::{FsUseType, XpermsKind};
29use selinux::{
30 ClassPermission, CommonFilePermission, CommonFsNodePermission, DirPermission, FdPermission,
31 FileClass, FileSystemLabel, FileSystemLabelingScheme, FileSystemMountOptions, ForClass,
32 FsNodeClass, InitialSid, KernelPermission, PolicyCap, ProcessPermission, SecurityId,
33 SecurityServer, TaskAttrs,
34};
35use smallvec;
36use starnix_logging::{BugRef, CATEGORY_STARNIX_SECURITY, bug_ref, trace_duration, track_stub};
37use starnix_sync::Mutex;
38use starnix_uapi::arc_key::WeakKey;
39use starnix_uapi::errors::Errno;
40use starnix_uapi::file_mode::FileMode;
41use starnix_uapi::{errno, error};
42use std::cell::Ref;
43use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
44use std::sync::{Arc, OnceLock};
45
46const NO_PERMISSIONS: &[KernelPermission] = &[];
49
50type PermissionFlagsVec = smallvec::SmallVec<[KernelPermission; 3]>;
52
53fn permissions_from_flags(flags: PermissionFlags, class: FsNodeClass) -> PermissionFlagsVec {
55 let mut result = PermissionFlagsVec::new();
56
57 if flags.contains(PermissionFlags::READ) {
58 result.push(CommonFsNodePermission::Read.for_class(class));
59 }
60 if flags.contains(PermissionFlags::WRITE) {
61 if flags.contains(PermissionFlags::APPEND) {
64 result.push(CommonFsNodePermission::Append.for_class(class));
65 } else {
66 result.push(CommonFsNodePermission::Write.for_class(class));
67 }
68 }
69
70 if let FsNodeClass::File(class) = class {
71 if flags.contains(PermissionFlags::EXEC) {
72 if class == FileClass::Dir {
73 result.push(DirPermission::Search.into());
74 } else {
75 result.push(CommonFilePermission::Execute.for_class(class));
76 }
77 }
78 }
79 result
80}
81
82fn is_internal_operation(current_task: &CurrentTask) -> bool {
83 current_task_state(current_task).internal_operation
84}
85
86fn has_file_permissions(
89 permission_check: &PermissionCheck<'_>,
90 current_task: &CurrentTask,
91 subject_sid: SecurityId,
92 file: &FileObject,
93 permissions: &[impl ForClass<FsNodeClass>],
94 audit_context: Auditable<'_>,
95) -> Result<(), Errno> {
96 if is_internal_operation(current_task) {
97 return Ok(());
98 };
99 let file_sid = file.security_state.state.sid;
102 if subject_sid != file_sid {
103 let node = file.node().as_ref().as_ref();
104 let audit_context = [audit_context, file.into(), node.into()];
105 check_permission(
106 permission_check,
107 current_task,
108 subject_sid,
109 file_sid,
110 FdPermission::Use,
111 (&audit_context).into(),
112 )?;
113 }
114
115 if !permissions.is_empty() {
117 let audit_context = [audit_context, file.into()];
118 has_fs_node_permissions(
119 permission_check,
120 current_task,
121 subject_sid,
122 file.node(),
123 permissions,
124 (&audit_context).into(),
125 )?;
126 }
127
128 Ok(())
129}
130
131fn has_file_ioctl_permission(
132 permission_check: &PermissionCheck<'_>,
133 current_task: &CurrentTask,
134 subject_sid: SecurityId,
135 file: &FileObject,
136 ioctl: u16,
137 audit_context: Auditable<'_>,
138) -> Result<(), Errno> {
139 has_file_permissions(
141 permission_check,
142 current_task,
143 subject_sid,
144 file,
145 NO_PERMISSIONS,
146 audit_context,
147 )?;
148
149 let fs_node = file.node().as_ref().as_ref();
152 if fs_node.is_private() {
153 return Ok(());
154 }
155 let FsNodeSidAndClass { sid: target_sid, class: target_class } =
156 fs_node_effective_sid_and_class(fs_node);
157
158 let audit_context =
159 &[audit_context, file.into(), fs_node.into(), Auditable::IoctlCommand(ioctl)];
160
161 check_permission_and_xperms(
163 permission_check,
164 current_task,
165 subject_sid,
166 target_sid,
167 CommonFsNodePermission::Ioctl.for_class(target_class),
168 XpermsKind::Ioctl,
169 ioctl,
170 audit_context.into(),
171 )
172}
173
174fn check_permission_and_xperms(
175 permission_check: &PermissionCheck<'_>,
176 current_task: &CurrentTask,
177 subject_sid: SecurityId,
178 target_sid: SecurityId,
179 permission: KernelPermission,
180 xperms_kind: XpermsKind,
181 xperm: u16,
182 audit_context: Auditable<'_>,
183) -> Result<(), Errno> {
184 if is_internal_operation(current_task) {
185 return Ok(());
186 }
187 let result = permission_check.has_extended_permission(
188 xperms_kind,
189 subject_sid,
190 target_sid,
191 permission.clone(),
192 xperm,
193 );
194
195 if result.audit {
196 if !result.permit() {
197 current_task
198 .kernel()
199 .security_state
200 .state
201 .as_ref()
202 .unwrap()
203 .access_denial_count
204 .fetch_add(1, Ordering::Release);
205 }
206
207 audit_decision(
208 current_task,
209 permission_check,
210 result.clone(),
211 subject_sid,
212 target_sid,
213 permission.into(),
214 audit_context.into(),
215 );
216 }
217
218 result.permit().then_some(()).ok_or_else(|| errno!(EACCES))
219}
220
221fn has_fs_node_permissions_dontaudit(
223 permission_check: &PermissionCheck<'_>,
224 _current_task: &CurrentTask,
225 subject_sid: SecurityId,
226 fs_node: &FsNode,
227 permissions: &[impl ForClass<FsNodeClass>],
228) -> Result<(), Errno> {
229 trace_duration!(
230 CATEGORY_STARNIX_SECURITY,
231 "security.selinux.has_fs_node_permissions_dontaudit"
232 );
233
234 if fs_node.is_private() {
235 return Ok(());
236 }
237
238 let target = fs_node_effective_sid_and_class(fs_node);
239 for permission in permissions {
240 if !permission_check
241 .has_permission(subject_sid, target.sid, permission.for_class(target.class))
242 .permit()
243 {
244 return error!(EACCES);
245 }
246 }
247
248 Ok(())
249}
250
251fn has_fs_node_permissions(
253 permission_check: &PermissionCheck<'_>,
254 current_task: &CurrentTask,
255 subject_sid: SecurityId,
256 fs_node: &FsNode,
257 permissions: &[impl ForClass<FsNodeClass>],
258 audit_context: Auditable<'_>,
259) -> Result<(), Errno> {
260 trace_duration!(CATEGORY_STARNIX_SECURITY, "security.selinux.has_fs_node_permissions");
261
262 if fs_node.is_private() {
263 return Ok(());
264 }
265
266 let target = fs_node_effective_sid_and_class(fs_node);
267
268 let fs = fs_node.fs();
269 let audit_context = [audit_context, fs_node.into(), fs.as_ref().into()];
270 for permission in permissions {
271 check_permission(
272 permission_check,
273 current_task,
274 subject_sid,
275 target.sid,
276 permission.for_class(target.class),
277 (&audit_context).into(),
278 )?;
279 }
280
281 Ok(())
282}
283
284#[allow(dead_code)]
286fn todo_has_fs_node_permissions(
287 bug: BugRef,
288 permission_check: &PermissionCheck<'_>,
289 current_task: &CurrentTask,
290 subject_sid: SecurityId,
291 fs_node: &FsNode,
292 permissions: &[impl ForClass<FsNodeClass>],
293 audit_context: Auditable<'_>,
294) -> Result<(), Errno> {
295 trace_duration!(CATEGORY_STARNIX_SECURITY, "security.selinux.todo_has_fs_node_permissions");
296
297 if fs_node.is_private() {
298 return Ok(());
299 }
300
301 let target = fs_node_effective_sid_and_class(fs_node);
302
303 let fs = fs_node.fs();
304 let audit_context = [audit_context, fs_node.into(), fs.as_ref().into()];
305 for permission in permissions {
306 todo_check_permission(
307 bug.clone(),
308 permission_check,
309 current_task,
310 subject_sid,
311 target.sid,
312 permission.for_class(target.class),
313 (&audit_context).into(),
314 )?;
315 }
316
317 Ok(())
318}
319
320fn file_class_from_file_mode(mode: FileMode) -> Result<FileClass, Errno> {
321 let file_type = mode.bits() & starnix_uapi::S_IFMT;
322 match file_type {
323 starnix_uapi::S_IFLNK => Ok(FileClass::LnkFile),
324 starnix_uapi::S_IFDIR => Ok(FileClass::Dir),
325 starnix_uapi::S_IFREG => Ok(FileClass::File),
326 starnix_uapi::S_IFCHR => Ok(FileClass::ChrFile),
327 starnix_uapi::S_IFBLK => Ok(FileClass::BlkFile),
328 starnix_uapi::S_IFIFO => Ok(FileClass::FifoFile),
329 starnix_uapi::S_IFSOCK => Ok(FileClass::SockFile),
330 0 => {
331 track_stub!(TODO("https://fxbug.dev/378864191"), "File with zero IFMT?");
332 Ok(FileClass::File)
333 }
334 _ => error!(EINVAL, format!("mode: {:?}", mode)),
335 }
336}
337
338#[macro_export]
339macro_rules! TODO_DENY {
340 ($bug_url:literal, $message:literal) => {{
341 use starnix_logging::bug_ref;
342 bug_ref!($bug_url)
343 }};
344}
345
346fn fs_node_effective_sid_and_class(fs_node: &FsNode) -> FsNodeSidAndClass {
349 let label_class = fs_node.security_state.0.read();
350 if matches!(label_class.label, FsNodeLabel::Uninitialized) {
351 if cfg!(any(test, debug_assertions)) {
353 panic!(
354 "Unlabeled FsNode@{} of class {:?} in {} (label {:?})",
355 fs_node.ino,
356 file_class_from_file_mode(fs_node.info().mode),
357 fs_node.fs().name(),
358 fs_node.fs().security_state.state.label(),
359 );
360 } else {
361 track_stub!(TODO("https://fxbug.dev/381210513"), "SID requested for unlabeled FsNode");
362 }
363 }
364 FsNodeSidAndClass { sid: label_class.sid(), class: label_class.class() }
365}
366
367fn todo_check_permission<P: ClassPermission + Into<KernelPermission> + Clone + 'static>(
370 bug: BugRef,
371 permission_check: &PermissionCheck<'_>,
372 current_task: &CurrentTask,
373 source_sid: SecurityId,
374 target_sid: SecurityId,
375 permission: P,
376 audit_context: Auditable<'_>,
377) -> Result<(), Errno> {
378 if is_internal_operation(current_task) {
379 return Ok(());
380 }
381 let kernel = current_task.kernel();
382 if kernel.features.selinux_test_suite {
383 check_permission(
384 permission_check,
385 current_task,
386 source_sid,
387 target_sid,
388 permission,
389 audit_context,
390 )
391 } else {
392 trace_duration!(CATEGORY_STARNIX_SECURITY, "security.selinux.todo_check_permission");
393
394 let result = permission_check.has_permission(source_sid, target_sid, permission.clone());
395
396 if result.audit {
397 audit_todo_decision(
398 current_task,
399 bug,
400 permission_check,
401 result,
402 source_sid,
403 target_sid,
404 permission.into(),
405 audit_context,
406 );
407 }
408
409 Ok(())
410 }
411}
412
413fn check_permission<P: ClassPermission + Into<KernelPermission> + Clone + 'static>(
415 permission_check: &PermissionCheck<'_>,
416 current_task: &CurrentTask,
417 source_sid: SecurityId,
418 target_sid: SecurityId,
419 permission: P,
420 audit_context: Auditable<'_>,
421) -> Result<(), Errno> {
422 trace_duration!(CATEGORY_STARNIX_SECURITY, "security.selinux.check_permission");
423
424 if is_internal_operation(current_task) {
425 return Ok(());
426 }
427 let result = permission_check.has_permission(source_sid, target_sid, permission.clone());
428
429 if result.audit {
430 if !result.permit() {
431 current_task
432 .kernel()
433 .security_state
434 .state
435 .as_ref()
436 .unwrap()
437 .access_denial_count
438 .fetch_add(1, Ordering::Release);
439 }
440
441 audit_decision(
442 current_task,
443 permission_check,
444 result.clone(),
445 source_sid,
446 target_sid,
447 permission.into(),
448 audit_context,
449 );
450 };
451
452 result.permit().then_some(()).ok_or_else(|| errno!(EACCES))
453}
454
455fn check_self_permission<P: ClassPermission + Into<KernelPermission> + Clone + 'static>(
457 permission_check: &PermissionCheck<'_>,
458 current_task: &CurrentTask,
459 subject_sid: SecurityId,
460 permission: P,
461 audit_context: Auditable<'_>,
462) -> Result<(), Errno> {
463 check_permission(
464 permission_check,
465 current_task,
466 subject_sid,
467 subject_sid,
468 permission,
469 audit_context,
470 )
471}
472
473async fn create_inspect_values(
474 security_server: Arc<SecurityServer>,
475) -> Result<fuchsia_inspect::Inspector, anyhow::Error> {
476 let inspector = fuchsia_inspect::Inspector::default();
477
478 let policy_bytes = if let Some(policy_data) = security_server.get_binary_policy() {
479 policy_data.len().try_into()?
480 } else {
481 0
482 };
483 inspector.root().record_uint("policy_bytes", policy_bytes);
484
485 Ok(inspector)
486}
487
488pub(super) fn kernel_init_security(
490 options: String,
491 exceptions: Vec<String>,
492 inspect_node: &fuchsia_inspect::Node,
493) -> KernelState {
494 let server = SecurityServer::new(options, exceptions);
495 let inspect_node = inspect_node.create_child("selinux");
496
497 let server_for_inspect = server.clone();
498 inspect_node.record_lazy_values("server", move || {
499 Box::pin(create_inspect_values(server_for_inspect.clone()))
500 });
501
502 KernelState {
503 server,
504 pending_file_systems: Mutex::default(),
505 selinuxfs_null: OnceLock::default(),
506 access_denial_count: AtomicU64::new(0u64),
507 has_policy: false.into(),
508 _inspect_node: inspect_node,
509 }
510}
511
512pub(super) struct KernelState {
514 pub(super) server: Arc<SecurityServer>,
516
517 pub(super) pending_file_systems: Mutex<IndexSet<WeakKey<FileSystem>>>,
522
523 pub(super) has_policy: AtomicBool,
525
526 pub(super) selinuxfs_null: OnceLock<FileHandle>,
529
530 pub(super) access_denial_count: AtomicU64,
532
533 pub(super) _inspect_node: fuchsia_inspect::Node,
535}
536
537impl KernelState {
538 pub(super) fn access_denial_count(&self) -> u64 {
539 self.access_denial_count.load(Ordering::Acquire)
540 }
541
542 pub(super) fn has_policy(&self) -> bool {
543 self.has_policy.load(Ordering::Acquire)
544 }
545}
546
547#[derive(Clone, Debug, PartialEq)]
549pub(super) struct PerfEventState {
550 sid: SecurityId,
551}
552
553pub(in crate::security) fn current_task_state(current_task: &CurrentTask) -> Ref<'_, TaskAttrs> {
554 Ref::map(current_task.current_creds(), |creds| &creds.security_state)
555}
556
557pub(in crate::security) fn task_consistent_attrs(current_task: &CurrentTask) -> Ref<'_, TaskAttrs> {
559 assert!(!current_task.has_overridden_creds());
560 current_task_state(current_task)
561}
562
563#[derive(Debug)]
566pub(super) struct FileObjectState {
567 sid: SecurityId,
568}
569
570#[derive(Debug)]
573pub(super) struct FileSystemState {
574 mount_options: FileSystemMountOptions,
576 pending_entries: Mutex<IndexSet<WeakKey<DirEntry>>>,
577
578 label: OnceLock<FileSystemLabel>,
580}
581
582impl FileSystemState {
583 fn new(mount_options: FileSystemMountOptions, _ops: &dyn FileSystemOps) -> Self {
584 let pending_entries = Mutex::new(IndexSet::new());
585 let label = OnceLock::new();
586
587 Self { mount_options, pending_entries, label }
588 }
589
590 pub fn label(&self) -> Option<&FileSystemLabel> {
592 self.label.get()
593 }
594
595 pub fn supports_relabel(&self) -> bool {
597 let Some(label) = self.label() else {
598 return false;
599 };
600 match label.scheme {
601 FileSystemLabelingScheme::Mountpoint { .. } => false,
602 FileSystemLabelingScheme::FsUse { .. } => true,
603 FileSystemLabelingScheme::GenFsCon { supports_seclabel } => supports_seclabel,
604 }
605 }
606
607 pub fn supports_xattr(&self) -> bool {
609 let Some(label) = self.label() else {
610 return false;
611 };
612 match label.scheme {
613 FileSystemLabelingScheme::Mountpoint { .. }
614 | FileSystemLabelingScheme::GenFsCon { .. } => false,
615 FileSystemLabelingScheme::FsUse { fs_use_type, .. } => fs_use_type == FsUseType::Xattr,
616 }
617 }
618}
619
620#[derive(Debug)]
622pub(super) struct FsNodeState {
623 label: RcuCell<FsNodeLabelAndClass>,
624 update_lock: Mutex<()>,
625}
626
627impl Default for FsNodeState {
628 fn default() -> Self {
629 Self {
630 label: RcuCell::new(FsNodeLabelAndClass {
631 label: FsNodeLabel::Uninitialized,
632 class: None,
633 }),
634 update_lock: Mutex::new(()),
635 }
636 }
637}
638
639impl FsNodeState {
640 pub(super) fn read(&self) -> RcuReadGuard<FsNodeLabelAndClass> {
641 self.label.read()
642 }
643
644 pub(super) fn update(&self, new_label: FsNodeLabel, new_class: FsNodeClass) {
645 let _lock = self.update_lock.lock();
646 let mut new_label_class = (*self.label.read()).clone();
647 new_label_class.label = new_label;
648 new_label_class.class = Some(new_class);
649 self.label.update(new_label_class);
650 }
651
652 pub(super) fn update_label(&self, new_label: FsNodeLabel) {
653 let _lock = self.update_lock.lock();
654 let mut new_label_class = (*self.label.read()).clone();
655 new_label_class.label = new_label;
656 self.label.update(new_label_class);
657 }
658
659 pub(super) fn update_class(&self, new_class: FsNodeClass) {
660 let _lock = self.update_lock.lock();
661 let mut new_label_class = (*self.label.read()).clone();
662 new_label_class.class = Some(new_class);
663 self.label.update(new_label_class);
664 }
665
666 #[cfg(test)]
667 pub(super) fn clear_label_for_test(&self) {
668 let _lock = self.update_lock.lock();
669 let class = self.label.read().class;
670 self.label.update(FsNodeLabelAndClass { label: FsNodeLabel::Uninitialized, class });
671 }
672}
673
674#[derive(Debug, Clone)]
676pub(super) enum FsNodeLabel {
677 Uninitialized,
678 SecurityId { sid: SecurityId },
679 FromTask { task_state: TaskPersistentInfo },
681}
682
683impl FsNodeLabel {
684 pub fn sid(&self) -> SecurityId {
685 match self {
686 FsNodeLabel::Uninitialized => InitialSid::Unlabeled.into(),
687 FsNodeLabel::SecurityId { sid } => *sid,
688 FsNodeLabel::FromTask { task_state } => {
689 task_state.real_creds().security_state.current_sid
690 }
691 }
692 }
693}
694
695#[derive(Debug, Clone)]
696pub(super) struct FsNodeLabelAndClass {
697 pub label: FsNodeLabel,
698 pub class: Option<FsNodeClass>,
699}
700
701impl FsNodeLabelAndClass {
702 pub fn class(&self) -> FsNodeClass {
703 self.class.unwrap_or(FsNodeClass::File(FileClass::File))
704 }
705
706 pub fn sid(&self) -> SecurityId {
707 self.label.sid()
708 }
709}
710
711#[derive(Debug, PartialEq)]
713pub(super) struct FsNodeSidAndClass {
714 pub sid: SecurityId,
715 pub class: FsNodeClass,
716}
717
718#[derive(Clone, Debug, PartialEq)]
721pub(super) struct BinderConnectionState {
722 sid: SecurityId,
723}
724
725#[derive(Debug, Default)]
728pub(super) struct SocketState {
729 peer_sid: Mutex<Option<SecurityId>>,
730}
731
732#[derive(Clone, Debug, PartialEq)]
735pub(super) struct BpfMapState {
736 sid: SecurityId,
737}
738
739#[derive(Clone, Debug, PartialEq)]
742pub(super) struct BpfProgState {
743 sid: SecurityId,
744}
745
746pub(super) fn set_cached_sid(fs_node: &FsNode, sid: SecurityId) {
750 fs_node.security_state.0.update_label(FsNodeLabel::SecurityId { sid });
751}
752
753fn fs_node_set_label_with_task(fs_node: &FsNode, task_persistent_info: &TaskPersistentInfo) {
757 fs_node
758 .security_state
759 .0
760 .update_label(FsNodeLabel::FromTask { task_state: task_persistent_info.clone() });
761}
762
763fn fs_node_ensure_class(fs_node: &FsNode) -> Result<FsNodeClass, Errno> {
767 let label_class = fs_node.security_state.0.read();
768 if let Some(class) = label_class.class {
769 return Ok(class);
770 }
771
772 let file_mode = fs_node.info().mode;
773 let _lock = fs_node.security_state.0.update_lock.lock();
774 let label_class = fs_node.security_state.0.read();
775 if let Some(class) = label_class.class {
776 return Ok(class);
777 }
778 let mut new_label_class = (*label_class).clone();
779 let class = file_class_from_file_mode(file_mode)?.into();
780 new_label_class.class = Some(class);
781 fs_node.security_state.0.label.update(new_label_class);
782 Ok(class)
783}
784
785#[cfg(test)]
786pub(super) fn get_cached_sid(fs_node: &FsNode) -> Option<SecurityId> {
788 let label_class = fs_node.security_state.0.read();
789 if !matches!(label_class.label, FsNodeLabel::Uninitialized) {
790 Some(label_class.sid())
791 } else {
792 None
793 }
794}
795
796#[derive(Debug)]
799pub enum PolicyCapSupport {
800 AlwaysOn(BugRef),
801 AlwaysOff(BugRef),
802 Configurable,
803 NotImplemented,
804}
805
806fn policycap_support(policy_cap: PolicyCap) -> PolicyCapSupport {
809 match policy_cap {
810 PolicyCap::AlwaysCheckNetwork => {
811 PolicyCapSupport::AlwaysOff(bug_ref!("https://fxbug.dev/452453565"))
812 }
813 PolicyCap::CgroupSeclabel => PolicyCapSupport::Configurable,
814 PolicyCap::ExtendedSocketClass => PolicyCapSupport::Configurable,
815 PolicyCap::FunctionfsSeclabel => PolicyCapSupport::Configurable,
816 PolicyCap::GenfsSeclabelSymlinks => PolicyCapSupport::Configurable,
817 PolicyCap::GenfsSeclabelWildcard => {
818 PolicyCapSupport::AlwaysOff(bug_ref!("https://fxbug.dev/452453565"))
819 }
820 PolicyCap::IoctlSkipCloexec => PolicyCapSupport::Configurable,
821 PolicyCap::MemfdClass => PolicyCapSupport::Configurable,
822 PolicyCap::NetifWildcard => {
823 PolicyCapSupport::AlwaysOff(bug_ref!("https://fxbug.dev/452453565"))
824 }
825 PolicyCap::NetlinkXperm => PolicyCapSupport::Configurable,
826 PolicyCap::NetworkPeerControls => PolicyCapSupport::NotImplemented,
827 PolicyCap::NnpNosuidTransition => PolicyCapSupport::Configurable,
828 PolicyCap::OpenPerms => PolicyCapSupport::AlwaysOn(bug_ref!("https://fxbug.dev/452453565")),
829 PolicyCap::UserspaceInitialContext => {
830 PolicyCapSupport::AlwaysOn(bug_ref!("https://fxbug.dev/452453565"))
831 }
832 }
833}