Skip to main content

starnix_core/mm/
protection_flags.rs

1// Copyright 2025 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
5use bitflags::bitflags;
6use starnix_uapi::{PROT_EXEC, PROT_GROWSDOWN, PROT_READ, PROT_WRITE};
7
8bitflags! {
9    #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
10    pub struct ProtectionFlags: u32 {
11      const READ = PROT_READ;
12      const WRITE = PROT_WRITE;
13      const EXEC = PROT_EXEC;
14      const GROWSDOWN = PROT_GROWSDOWN;
15    }
16}
17
18impl ProtectionFlags {
19    pub const ACCESS_FLAGS: Self =
20        Self::from_bits_truncate(Self::READ.bits() | Self::WRITE.bits() | Self::EXEC.bits());
21
22    pub fn to_vmar_flags(self) -> zx::VmarFlags {
23        let mut vmar_flags = zx::VmarFlags::empty();
24        if self.contains(ProtectionFlags::READ) {
25            vmar_flags |= zx::VmarFlags::PERM_READ;
26        }
27        if self.contains(ProtectionFlags::WRITE) {
28            vmar_flags |= zx::VmarFlags::PERM_READ | zx::VmarFlags::PERM_WRITE;
29        }
30        if self.contains(ProtectionFlags::EXEC) {
31            vmar_flags |= zx::VmarFlags::PERM_EXECUTE | zx::VmarFlags::PERM_READ_IF_XOM_UNSUPPORTED;
32        }
33        vmar_flags
34    }
35
36    pub fn from_vmar_flags(vmar_flags: zx::VmarFlags) -> ProtectionFlags {
37        let mut prot_flags = ProtectionFlags::empty();
38        if vmar_flags.contains(zx::VmarFlags::PERM_READ) {
39            prot_flags |= ProtectionFlags::READ;
40        }
41        if vmar_flags.contains(zx::VmarFlags::PERM_WRITE) {
42            prot_flags |= ProtectionFlags::WRITE;
43        }
44        if vmar_flags.contains(zx::VmarFlags::PERM_EXECUTE) {
45            prot_flags |= ProtectionFlags::EXEC;
46        }
47        prot_flags
48    }
49
50    pub fn from_access_bits(prot: u32) -> Option<Self> {
51        if let Some(flags) = ProtectionFlags::from_bits(prot) {
52            if flags.contains(Self::ACCESS_FLAGS.complement()) { None } else { Some(flags) }
53        } else {
54            None
55        }
56    }
57
58    pub fn access_flags(&self) -> Self {
59        *self & Self::ACCESS_FLAGS
60    }
61}