Skip to content

Commit 7bc7d25

Browse files
authored
Add set{u,g}id syscalls (#510)
Signed-off-by: Alex Saveau <saveau.alexandre@gmail.com>
1 parent f3c5527 commit 7bc7d25

File tree

6 files changed

+102
-5
lines changed

6 files changed

+102
-5
lines changed

src/backend/libc/thread/syscalls.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,3 +319,17 @@ pub(crate) fn capset(
319319
let header: *mut _ = header;
320320
unsafe { syscall_ret(c::syscall(c::SYS_capset, header, data.as_ptr())) }
321321
}
322+
323+
#[cfg(any(target_os = "android", target_os = "linux"))]
324+
#[inline]
325+
#[must_use]
326+
pub(crate) fn setuid_thread(uid: crate::process::Uid) -> io::Result<()> {
327+
unsafe { syscall_ret(c::syscall(c::SYS_setuid, uid.as_raw())) }
328+
}
329+
330+
#[cfg(any(target_os = "android", target_os = "linux"))]
331+
#[inline]
332+
#[must_use]
333+
pub(crate) fn setgid_thread(gid: crate::process::Gid) -> io::Result<()> {
334+
unsafe { syscall_ret(c::syscall(c::SYS_setgid, gid.as_raw())) }
335+
}

src/backend/linux_raw/conv.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,20 @@ impl<'a, Num: ArgNumber> From<crate::backend::fs::types::UnmountFlags> for ArgRe
699699
}
700700
}
701701

702+
impl<'a, Num: ArgNumber> From<crate::process::Uid> for ArgReg<'a, Num> {
703+
#[inline]
704+
fn from(t: crate::process::Uid) -> Self {
705+
c_uint(t.as_raw())
706+
}
707+
}
708+
709+
impl<'a, Num: ArgNumber> From<crate::process::Gid> for ArgReg<'a, Num> {
710+
#[inline]
711+
fn from(t: crate::process::Gid) -> Self {
712+
c_uint(t.as_raw())
713+
}
714+
}
715+
702716
/// Convert a `usize` returned from a syscall that effectively returns `()` on
703717
/// success.
704718
///

src/backend/linux_raw/thread/syscalls.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,3 +314,13 @@ pub(crate) fn capset(
314314
let header: *mut _ = header;
315315
unsafe { ret(syscall!(__NR_capset, header, data.as_ptr())) }
316316
}
317+
318+
#[inline]
319+
pub(crate) fn setuid_thread(uid: crate::process::Uid) -> io::Result<()> {
320+
unsafe { ret(syscall_readonly!(__NR_setuid, uid)) }
321+
}
322+
323+
#[inline]
324+
pub(crate) fn setgid_thread(gid: crate::process::Gid) -> io::Result<()> {
325+
unsafe { ret(syscall_readonly!(__NR_setgid, gid)) }
326+
}

src/thread/id.rs

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
use crate::backend;
2-
use crate::process::Pid;
1+
use crate::process::{Gid, Pid, Uid};
2+
use crate::{backend, io};
33

44
/// `gettid()`—Returns the thread ID.
55
///
@@ -15,3 +15,53 @@ use crate::process::Pid;
1515
pub fn gettid() -> Pid {
1616
backend::thread::syscalls::gettid()
1717
}
18+
19+
/// `setuid(uid)`
20+
///
21+
/// # Warning
22+
///
23+
/// This is not the setxid you are looking for... POSIX requires xids to be
24+
/// process granular, but on Linux they are per-thread. Thus, this call only
25+
/// changes the xid for the current *thread*, not the entire process even though
26+
/// that is in violation of the POSIX standard.
27+
///
28+
/// For details on this distinction, see the C library vs. kernel differences in
29+
/// the [man page][linux_notes]. This call implements the kernel behavior.
30+
///
31+
/// # References
32+
/// - [POSIX]
33+
/// - [Linux]
34+
///
35+
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setuid.html
36+
/// [Linux]: https://man7.org/linux/man-pages/man2/setuid.2.html
37+
/// [linux_notes]: https://man7.org/linux/man-pages/man2/setuid.2.html#NOTES
38+
#[inline]
39+
#[must_use]
40+
pub fn set_thread_uid(uid: Uid) -> io::Result<()> {
41+
backend::thread::syscalls::setuid_thread(uid)
42+
}
43+
44+
/// `setgid(gid)`
45+
///
46+
/// # Warning
47+
///
48+
/// This is not the setxid you are looking for... POSIX requires xids to be
49+
/// process granular, but on Linux they are per-thread. Thus, this call only
50+
/// changes the xid for the current *thread*, not the entire process even though
51+
/// that is in violation of the POSIX standard.
52+
///
53+
/// For details on this distinction, see the C library vs. kernel differences in
54+
/// the [man page][linux_notes]. This call implements the kernel behavior.
55+
///
56+
/// # References
57+
/// - [POSIX]
58+
/// - [Linux]
59+
///
60+
/// [POSIX]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/setgid.html
61+
/// [Linux]: https://man7.org/linux/man-pages/man2/setgid.2.html
62+
/// [linux_notes]: https://man7.org/linux/man-pages/man2/setgid.2.html#NOTES
63+
#[inline]
64+
#[must_use]
65+
pub fn set_thread_gid(gid: Gid) -> io::Result<()> {
66+
backend::thread::syscalls::setgid_thread(gid)
67+
}

src/thread/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub use clock::{nanosleep, NanosleepRelativeResult, Timespec};
3030
#[cfg(linux_raw)]
3131
pub use futex::{futex, FutexFlags, FutexOperation};
3232
#[cfg(any(target_os = "android", target_os = "linux"))]
33-
pub use id::gettid;
33+
pub use id::{gettid, set_thread_gid, set_thread_uid};
3434
#[cfg(any(target_os = "android", target_os = "linux"))]
3535
pub use libcap::{capabilities, set_capabilities, CapabilityFlags, CapabilitySets};
3636
#[cfg(any(target_os = "android", target_os = "linux"))]

tests/thread/id.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1-
use rustix::thread;
1+
use rustix::{process, thread};
22

3-
#[cfg(any(target_os = "android", target_os = "linux"))]
43
#[test]
54
fn test_gettid() {
65
assert_eq!(thread::gettid(), thread::gettid());
76
}
7+
8+
#[test]
9+
fn test_setuid() {
10+
thread::set_thread_uid(process::getuid()).unwrap();
11+
}
12+
13+
#[test]
14+
fn test_setgid() {
15+
thread::set_thread_gid(process::getgid()).unwrap();
16+
}

0 commit comments

Comments
 (0)