mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 00:43:24 +00:00
Implement atomic wrapper for integer-like type
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
a7cb71161d
commit
21fedd1b60
@ -2,6 +2,7 @@
|
||||
|
||||
use core::sync::atomic::{AtomicU64, Ordering};
|
||||
|
||||
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
|
||||
use bitflags::bitflags;
|
||||
|
||||
bitflags! {
|
||||
@ -53,6 +54,8 @@ bitflags! {
|
||||
}
|
||||
|
||||
impl CapSet {
|
||||
const MASK: u64 = (1 << (CapSet::most_significant_bit() + 1)) - 1;
|
||||
|
||||
/// Converts the capability set to a `u32`. The higher bits are truncated.
|
||||
pub fn as_u32(&self) -> u32 {
|
||||
self.bits() as u32
|
||||
@ -64,31 +67,37 @@ impl CapSet {
|
||||
}
|
||||
|
||||
/// The most significant bit in a 64-bit `CapSet` that may be set to represent a Linux capability.
|
||||
pub fn most_significant_bit() -> u8 {
|
||||
pub const fn most_significant_bit() -> u8 {
|
||||
// CHECKPOINT_RESTORE is the Linux capability with the largest numerical value
|
||||
40
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AtomicCapSet(AtomicU64);
|
||||
impl TryFrom<u64> for CapSet {
|
||||
type Error = &'static str;
|
||||
|
||||
impl AtomicCapSet {
|
||||
pub const fn new(capset: CapSet) -> Self {
|
||||
Self(AtomicU64::new(capset.bits))
|
||||
}
|
||||
|
||||
pub fn set(&self, capset: CapSet) {
|
||||
self.0.store(capset.bits(), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn get(&self) -> CapSet {
|
||||
CapSet::from_bits_truncate(self.0.load(Ordering::Relaxed))
|
||||
fn try_from(value: u64) -> Result<Self, Self::Error> {
|
||||
if value & !CapSet::MASK != 0 {
|
||||
Err("Invalid CapSet.")
|
||||
} else {
|
||||
Ok(CapSet { bits: value })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CapSet> for u64 {
|
||||
fn from(value: CapSet) -> Self {
|
||||
value.bits()
|
||||
}
|
||||
}
|
||||
|
||||
define_atomic_version_of_integer_like_type!(CapSet, try_from = true, {
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AtomicCapSet(AtomicU64);
|
||||
});
|
||||
|
||||
impl Clone for AtomicCapSet {
|
||||
fn clone(&self) -> Self {
|
||||
Self::new(self.get())
|
||||
Self::new(self.load(Ordering::Relaxed))
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use core::sync::atomic::Ordering;
|
||||
|
||||
use ostd::sync::{RwLockReadGuard, RwLockWriteGuard};
|
||||
|
||||
use super::{group::AtomicGid, user::AtomicUid, Gid, Uid};
|
||||
@ -75,28 +77,28 @@ impl Credentials_ {
|
||||
// ******* Uid methods *******
|
||||
|
||||
pub(super) fn ruid(&self) -> Uid {
|
||||
self.ruid.get()
|
||||
self.ruid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn euid(&self) -> Uid {
|
||||
self.euid.get()
|
||||
self.euid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn suid(&self) -> Uid {
|
||||
self.suid.get()
|
||||
self.suid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn fsuid(&self) -> Uid {
|
||||
self.fsuid.get()
|
||||
self.fsuid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn set_uid(&self, uid: Uid) {
|
||||
if self.is_privileged() {
|
||||
self.ruid.set(uid);
|
||||
self.euid.set(uid);
|
||||
self.suid.set(uid);
|
||||
self.ruid.store(uid, Ordering::Relaxed);
|
||||
self.euid.store(uid, Ordering::Relaxed);
|
||||
self.suid.store(uid, Ordering::Relaxed);
|
||||
} else {
|
||||
self.euid.set(uid);
|
||||
self.euid.store(uid, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -108,13 +110,13 @@ impl Credentials_ {
|
||||
self.set_resuid_unchecked(ruid, euid, None);
|
||||
|
||||
if should_set_suid {
|
||||
self.suid.set(self.euid());
|
||||
self.suid.store(self.euid(), Ordering::Release);
|
||||
}
|
||||
|
||||
// FIXME: should we set fsuid here? The linux document for syscall `setfsuid` is contradictory
|
||||
// with the document of syscall `setreuid`. The `setfsuid` document says the `fsuid` is always
|
||||
// the same as `euid`, but `setreuid` does not mention the `fsuid` should be set.
|
||||
self.fsuid.set(self.euid());
|
||||
self.fsuid.store(self.euid(), Ordering::Release);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -129,7 +131,7 @@ impl Credentials_ {
|
||||
|
||||
self.set_resuid_unchecked(ruid, euid, suid);
|
||||
|
||||
self.fsuid.set(self.euid());
|
||||
self.fsuid.store(self.euid(), Ordering::Release);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -142,7 +144,7 @@ impl Credentials_ {
|
||||
};
|
||||
|
||||
if self.is_privileged() {
|
||||
self.fsuid.set(fsuid);
|
||||
self.fsuid.store(fsuid, Ordering::Release);
|
||||
return Ok(old_fsuid);
|
||||
}
|
||||
|
||||
@ -153,17 +155,17 @@ impl Credentials_ {
|
||||
)
|
||||
}
|
||||
|
||||
self.fsuid.set(fsuid);
|
||||
self.fsuid.store(fsuid, Ordering::Release);
|
||||
|
||||
Ok(old_fsuid)
|
||||
}
|
||||
|
||||
pub(super) fn set_euid(&self, euid: Uid) {
|
||||
self.euid.set(euid);
|
||||
self.euid.store(euid, Ordering::Release);
|
||||
}
|
||||
|
||||
pub(super) fn set_suid(&self, suid: Uid) {
|
||||
self.suid.set(suid);
|
||||
self.suid.store(suid, Ordering::Release);
|
||||
}
|
||||
|
||||
// For `setreuid`, ruid can *NOT* be set to old suid,
|
||||
@ -217,43 +219,43 @@ impl Credentials_ {
|
||||
|
||||
fn set_resuid_unchecked(&self, ruid: Option<Uid>, euid: Option<Uid>, suid: Option<Uid>) {
|
||||
if let Some(ruid) = ruid {
|
||||
self.ruid.set(ruid);
|
||||
self.ruid.store(ruid, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
if let Some(euid) = euid {
|
||||
self.euid.set(euid);
|
||||
self.euid.store(euid, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
if let Some(suid) = suid {
|
||||
self.suid.set(suid);
|
||||
self.suid.store(suid, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
// ******* Gid methods *******
|
||||
|
||||
pub(super) fn rgid(&self) -> Gid {
|
||||
self.rgid.get()
|
||||
self.rgid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn egid(&self) -> Gid {
|
||||
self.egid.get()
|
||||
self.egid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn sgid(&self) -> Gid {
|
||||
self.sgid.get()
|
||||
self.sgid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn fsgid(&self) -> Gid {
|
||||
self.fsgid.get()
|
||||
self.fsgid.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn set_gid(&self, gid: Gid) {
|
||||
if self.is_privileged() {
|
||||
self.rgid.set(gid);
|
||||
self.egid.set(gid);
|
||||
self.sgid.set(gid);
|
||||
self.rgid.store(gid, Ordering::Relaxed);
|
||||
self.egid.store(gid, Ordering::Relaxed);
|
||||
self.sgid.store(gid, Ordering::Relaxed);
|
||||
} else {
|
||||
self.egid.set(gid);
|
||||
self.egid.store(gid, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,10 +267,10 @@ impl Credentials_ {
|
||||
self.set_resgid_unchecked(rgid, egid, None);
|
||||
|
||||
if should_set_sgid {
|
||||
self.sgid.set(self.egid());
|
||||
self.sgid.store(self.egid(), Ordering::Relaxed);
|
||||
}
|
||||
|
||||
self.fsgid.set(self.egid());
|
||||
self.fsgid.store(self.egid(), Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -283,7 +285,7 @@ impl Credentials_ {
|
||||
|
||||
self.set_resgid_unchecked(rgid, egid, sgid);
|
||||
|
||||
self.fsgid.set(self.egid());
|
||||
self.fsgid.store(self.egid(), Ordering::Relaxed);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@ -296,7 +298,7 @@ impl Credentials_ {
|
||||
};
|
||||
|
||||
if self.is_privileged() {
|
||||
self.fsgid.set(fsgid);
|
||||
self.fsgid.store(fsgid, Ordering::Relaxed);
|
||||
return Ok(old_fsgid);
|
||||
}
|
||||
|
||||
@ -307,17 +309,17 @@ impl Credentials_ {
|
||||
)
|
||||
}
|
||||
|
||||
self.fsgid.set(fsgid);
|
||||
self.fsgid.store(fsgid, Ordering::Relaxed);
|
||||
|
||||
Ok(old_fsgid)
|
||||
}
|
||||
|
||||
pub(super) fn set_egid(&self, egid: Gid) {
|
||||
self.egid.set(egid);
|
||||
self.egid.store(egid, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(super) fn set_sgid(&self, sgid: Gid) {
|
||||
self.sgid.set(sgid);
|
||||
self.sgid.store(sgid, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
// For `setregid`, rgid can *NOT* be set to old sgid,
|
||||
@ -371,15 +373,15 @@ impl Credentials_ {
|
||||
|
||||
fn set_resgid_unchecked(&self, rgid: Option<Gid>, egid: Option<Gid>, sgid: Option<Gid>) {
|
||||
if let Some(rgid) = rgid {
|
||||
self.rgid.set(rgid);
|
||||
self.rgid.store(rgid, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
if let Some(egid) = egid {
|
||||
self.egid.set(egid);
|
||||
self.egid.store(egid, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
if let Some(sgid) = sgid {
|
||||
self.sgid.set(sgid);
|
||||
self.sgid.store(sgid, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
@ -396,27 +398,30 @@ impl Credentials_ {
|
||||
// ******* Linux Capability methods *******
|
||||
|
||||
pub(super) fn inheritable_capset(&self) -> CapSet {
|
||||
self.inheritable_capset.get()
|
||||
self.inheritable_capset.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn permitted_capset(&self) -> CapSet {
|
||||
self.permitted_capset.get()
|
||||
self.permitted_capset.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn effective_capset(&self) -> CapSet {
|
||||
self.effective_capset.get()
|
||||
self.effective_capset.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub(super) fn set_inheritable_capset(&self, inheritable_capset: CapSet) {
|
||||
self.inheritable_capset.set(inheritable_capset);
|
||||
self.inheritable_capset
|
||||
.store(inheritable_capset, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(super) fn set_permitted_capset(&self, permitted_capset: CapSet) {
|
||||
self.permitted_capset.set(permitted_capset);
|
||||
self.permitted_capset
|
||||
.store(permitted_capset, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub(super) fn set_effective_capset(&self, effective_capset: CapSet) {
|
||||
self.effective_capset.set(effective_capset);
|
||||
self.effective_capset
|
||||
.store(effective_capset, Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, Pod, Default, PartialEq, Eq, PartialOrd, Ord)]
|
||||
@ -17,10 +19,6 @@ impl Gid {
|
||||
Self(ROOT_GID)
|
||||
}
|
||||
|
||||
pub const fn as_u32(&self) -> u32 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub const fn is_root(&self) -> bool {
|
||||
self.0 == ROOT_GID
|
||||
}
|
||||
@ -28,25 +26,25 @@ impl Gid {
|
||||
|
||||
const ROOT_GID: u32 = 0;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AtomicGid(AtomicU32);
|
||||
|
||||
impl AtomicGid {
|
||||
pub const fn new(gid: Gid) -> Self {
|
||||
Self(AtomicU32::new(gid.as_u32()))
|
||||
}
|
||||
|
||||
pub fn set(&self, gid: Gid) {
|
||||
self.0.store(gid.as_u32(), Ordering::Relaxed)
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Gid {
|
||||
Gid(self.0.load(Ordering::Relaxed))
|
||||
impl From<u32> for Gid {
|
||||
fn from(value: u32) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Gid> for u32 {
|
||||
fn from(value: Gid) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
define_atomic_version_of_integer_like_type!(Gid, {
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AtomicGid(AtomicU32);
|
||||
});
|
||||
|
||||
impl Clone for AtomicGid {
|
||||
fn clone(&self) -> Self {
|
||||
Self(AtomicU32::new(self.0.load(Ordering::Relaxed)))
|
||||
Self::new(self.load(Ordering::Relaxed))
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
use core::sync::atomic::{AtomicU32, Ordering};
|
||||
|
||||
use atomic_integer_wrapper::define_atomic_version_of_integer_like_type;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Pod)]
|
||||
@ -22,35 +24,33 @@ impl Uid {
|
||||
pub const fn is_root(&self) -> bool {
|
||||
self.0 == ROOT_UID
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn as_u32(&self) -> u32 {
|
||||
self.0
|
||||
impl From<u32> for Uid {
|
||||
fn from(value: u32) -> Self {
|
||||
Self::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AtomicUid(AtomicU32);
|
||||
impl From<Uid> for u32 {
|
||||
fn from(value: Uid) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
define_atomic_version_of_integer_like_type!(Uid, {
|
||||
#[derive(Debug)]
|
||||
pub(super) struct AtomicUid(AtomicU32);
|
||||
});
|
||||
|
||||
impl AtomicUid {
|
||||
pub const fn new(uid: Uid) -> Self {
|
||||
Self(AtomicU32::new(uid.as_u32()))
|
||||
}
|
||||
|
||||
pub fn set(&self, uid: Uid) {
|
||||
self.0.store(uid.as_u32(), Ordering::Release)
|
||||
}
|
||||
|
||||
pub fn get(&self) -> Uid {
|
||||
Uid(self.0.load(Ordering::Acquire))
|
||||
}
|
||||
|
||||
pub fn is_root(&self) -> bool {
|
||||
self.get().is_root()
|
||||
self.load(Ordering::Acquire).is_root()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for AtomicUid {
|
||||
fn clone(&self) -> Self {
|
||||
Self(AtomicU32::new(self.0.load(Ordering::Acquire)))
|
||||
Self::new(self.load(Ordering::Acquire))
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user