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