Fix some set uid behaviors

This commit is contained in:
Chen Chengjun 2025-09-26 05:18:24 +00:00 committed by Jianfeng Jiang
parent 728b8d1b5a
commit 9a99af1170
2 changed files with 75 additions and 26 deletions

View File

@ -102,10 +102,7 @@ impl Credentials_ {
pub(super) fn set_uid(&self, uid: Uid) {
if self.is_privileged() {
self.ruid.store(uid, Ordering::Relaxed);
self.euid.store(uid, Ordering::Relaxed);
self.suid.store(uid, Ordering::Relaxed);
self.fsuid.store(uid, Ordering::Relaxed);
self.set_resuid_unchecked(Some(uid), Some(uid), Some(uid));
} else {
// Unprivileged processes can only switch between ruid, euid, suid
if uid != self.ruid.load(Ordering::Relaxed)
@ -115,15 +112,10 @@ impl Credentials_ {
// No permission to set to this UID
return;
}
self.euid.store(uid, Ordering::Relaxed);
self.fsuid.store(uid, Ordering::Relaxed);
self.set_resuid_unchecked(None, Some(uid), None)
}
if !self.keep_capabilities.load(Ordering::Relaxed) {
self.set_permitted_capset(CapSet::empty());
self.set_inheritable_capset(CapSet::empty());
}
// Always clear the effective capabilities when changing the UID
self.set_effective_capset(CapSet::empty());
self.set_fsuid_unchecked(uid)
}
pub(super) fn set_reuid(&self, ruid: Option<Uid>, euid: Option<Uid>) -> Result<()> {
@ -140,7 +132,7 @@ impl Credentials_ {
// 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.store(self.euid(), Ordering::Release);
self.set_fsuid_unchecked(self.euid());
Ok(())
}
@ -155,7 +147,7 @@ impl Credentials_ {
self.set_resuid_unchecked(ruid, euid, suid);
self.fsuid.store(self.euid(), Ordering::Release);
self.set_fsuid_unchecked(self.euid());
Ok(())
}
@ -179,17 +171,17 @@ impl Credentials_ {
)
}
self.fsuid.store(fsuid, Ordering::Release);
self.set_fsuid_unchecked(fsuid);
Ok(old_fsuid)
}
pub(super) fn set_euid(&self, euid: Uid) {
self.euid.store(euid, Ordering::Release);
self.set_resuid_unchecked(None, Some(euid), None);
}
pub(super) fn set_suid(&self, suid: Uid) {
self.suid.store(suid, Ordering::Release);
self.set_resuid_unchecked(None, None, Some(suid));
}
// For `setreuid`, ruid can *NOT* be set to old suid,
@ -242,16 +234,73 @@ impl Credentials_ {
}
fn set_resuid_unchecked(&self, ruid: Option<Uid>, euid: Option<Uid>, suid: Option<Uid>) {
if let Some(ruid) = ruid {
let old_ruid = self.ruid();
let old_euid = self.euid();
let old_suid = self.suid();
let new_ruid = if let Some(ruid) = ruid {
self.ruid.store(ruid, Ordering::Relaxed);
}
ruid
} else {
old_ruid
};
if let Some(euid) = euid {
let new_euid = if let Some(euid) = euid {
self.euid.store(euid, Ordering::Relaxed);
}
euid
} else {
old_euid
};
if let Some(suid) = suid {
let new_suid = if let Some(suid) = suid {
self.suid.store(suid, Ordering::Relaxed);
suid
} else {
old_suid
};
// Begin to adjust capabilities.
// Reference: The "Effect of user ID changes on capabilities" section in
// https://man7.org/linux/man-pages/man7/capabilities.7.html
let had_root = old_ruid.is_root() || old_euid.is_root() || old_suid.is_root();
let all_nonroot = !new_ruid.is_root() && !new_euid.is_root() && !new_suid.is_root();
if had_root && all_nonroot {
if !self.keep_capabilities() {
self.set_permitted_capset(CapSet::empty());
self.set_inheritable_capset(CapSet::empty());
// TODO: Also need to clear ambient capabilities when we support it
}
self.set_effective_capset(CapSet::empty());
} else {
if old_euid.is_root() && !new_euid.is_root() {
self.set_effective_capset(CapSet::empty());
}
if !old_euid.is_root() && new_euid.is_root() {
let permitted = self.permitted_capset();
self.set_effective_capset(permitted);
}
}
}
fn set_fsuid_unchecked(&self, fsuid: Uid) {
let old_uid = self.fsuid.swap(fsuid, Ordering::Relaxed);
if old_uid.is_root() && !fsuid.is_root() {
// Reference: The "Effect of user ID changes on capabilities" section in
// https://man7.org/linux/man-pages/man7/capabilities.7.html
let cap_to_remove = CapSet::CHOWN
| CapSet::DAC_OVERRIDE
| CapSet::FOWNER
| CapSet::DAC_READ_SEARCH
| CapSet::FSETID
| CapSet::LINUX_IMMUTABLE
| CapSet::MAC_OVERRIDE
| CapSet::MKNOD;
let old_cap = self.effective_capset();
self.set_effective_capset(old_cap - cap_to_remove);
}
}

View File

@ -1419,7 +1419,7 @@ setregid01
# setresuid01
# setresuid01_16
# setresuid02
setresuid02
# setresuid02_16
setresuid03
# setresuid03_16
@ -1434,11 +1434,11 @@ setreuid01
# setreuid02_16
# setreuid03
# setreuid03_16
# setreuid04
setreuid04
# setreuid04_16
# setreuid05
# setreuid05_16
# setreuid06
setreuid06
# setreuid06_16
# setreuid07
# setreuid07_16
@ -1470,7 +1470,7 @@ setuid01
# setuid01_16
# setuid03
# setuid03_16
# setuid04
setuid04
# setuid04_16
# setxattr01