forked from kmcallister/tiny-rust-demo
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtinyrust.rs
78 lines (66 loc) · 2.27 KB
/
tinyrust.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#![crate_type="rlib"]
#![feature(core)]
#[macro_use] extern crate syscall;
use std::{mem, raw, intrinsics};
fn exit(n: usize) -> ! {
unsafe {
syscall!(EXIT, n);
intrinsics::unreachable()
}
}
// This is here in case you need a way to add debugging prints to this
// code.
fn write(fd: usize, buf: &[u8]) -> usize {
unsafe {
return syscall!(WRITE, fd, buf.as_ptr(), buf.len())
}
}
fn setuid(n: usize) -> usize {
unsafe {
return syscall!(SETUID, n)
}
}
fn unshare(n: usize) -> usize {
unsafe {
return syscall!(UNSHARE, n)
}
}
#[no_mangle]
pub fn main() {
// The purpose of main() is to verify that UID namespaces work
// when not root, so we make sure we're not root.
// We will:
//
// - exit(0) if we confirm user namespaces work great as non-root.
//
// - exit non-zero if anything else happens.
// Since I started this codebase by forking Keegan McAllister's
// tinyrust project, it comes bundled with a string constant
// ("Hello!\n"). We capture that message here, not because we use
// it in this program, but because while modifying this code, it
// can be helpful to be able to write() it for debugging's sake.
// Make a Rust value representing the string constant we stashed
// in the ELF file header.
let message: &'static [u8] = unsafe {
mem::transmute(raw::Slice {
data: 0x00400008 as *const u8,
len: 7,
})
};
// First, check if we are root. If we are, we setuid to 65534
// (which is just a dummy non-root user ID, which also happens to
// usually be "nobody"), since we want to find out if
// unshare(CLONE_NEWUSER) works when we are not root. If we are already
// non-root, setuid() will fail, but that's fine because we didn't need it
// anyway in that case, so we just ignore it.
setuid(65534);
// Now that we're not root, we can try to unshare(CLONE_NEWUSER).
// CLONE_NEWUSER is 0x10000000.
//
// We pass unshare()'s return code directly to exit(). It exits 0
// in the case of success! And if the kernel gives us a non-zero
// exit code, then we exit non-zero.
//
// Note that if we overflow, we'll be a little sad. Oh, well.
exit(unshare(0x10000000));
}