Skip to content

Instantly share code, notes, and snippets.

@musaprg
Created July 31, 2022 10:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save musaprg/e94f89f54252fbaa2b8116475640ceeb to your computer and use it in GitHub Desktop.
Save musaprg/e94f89f54252fbaa2b8116475640ceeb to your computer and use it in GitHub Desktop.
const std = @import("std");
const os = std.os;
const fs = std.fs;
const fmt = std.fmt;
const heap = std.heap;
const ArenaAllocator = heap.ArenaAllocator;
const linux = os.linux;
const print = std.debug.print;
// no interface natively in zig for now
// imported from https://github.com/ziglang/zig/blob/0.9.x/lib/libc/include/any-linux-any/linux/capability.h
const CAP_SETGID = 6;
const CAP_SETUID = 7;
const _LINUX_CAPABILITY_VERSION_3 = 0x20080522;
const _LINUX_CAPABILITY_U32S_3 = 2;
fn parent(cpid: os.pid_t) !void {
print("parent pid: {}\n", .{linux.getpid()});
print("child pid: {}\n", .{cpid});
var result = os.waitpid(cpid, 0); // i'm not sure how to handle WaitPidResult.status with zig, there's no macro like WIFEXITED
_ = result.status;
}
fn child(allocator: std.mem.Allocator) !void {
const flags = linux.CLONE.NEWIPC | linux.CLONE.NEWNET | linux.CLONE.NEWUSER;
if (linux.unshare(flags) == -1) {
print("unshare failed\n", .{});
os.exit(1);
}
// Get current capabilities
var chdrp = try allocator.create(linux.cap_user_header_t);
var cdatap = try allocator.create(linux.cap_user_data_t);
if (linux.capget(chdrp, cdatap) == -1) {
print("capget failed\n", .{});
os.exit(1);
}
// https://man7.org/linux/man-pages/man7/capabilities.7.html
// Set CAP_SETGID and CAP_SETUID
var hdrp = linux.cap_user_header_t{
.version = _LINUX_CAPABILITY_VERSION_3,
.pid = 0,
};
var datap = linux.cap_user_data_t{
.effective = cdatap.effective | CAP_SETGID | CAP_SETUID,
.permitted = cdatap.permitted | CAP_SETGID | CAP_SETUID,
.inheritable = cdatap.inheritable | CAP_SETGID | CAP_SETUID,
};
if (linux.capset(&hdrp, &datap) == -1) {
print("capset failed\n", .{});
os.exit(1);
}
_ = allocator;
var uid = linux.getuid();
var gid = linux.getgid();
print("uid: {}\n", .{uid});
print("gid: {}\n", .{gid});
var pid = linux.getpid();
var string_pid = try fmt.allocPrint(allocator, "{}", .{pid});
defer allocator.free(string_pid);
//var uid_map_path = fs.path.join(allocator, &[_][]const u8{ "/proc", string_pid, "uid_map" }) catch unreachable;
//var gid_map_path = fs.path.join(allocator, &[_][]const u8{ "/proc", string_pid, "gid_map" }) catch unreachable;
var uid_map_path = fs.path.join(allocator, &[_][]const u8{ "/proc", "self", "uid_map" }) catch unreachable;
var gid_map_path = fs.path.join(allocator, &[_][]const u8{ "/proc", "self", "gid_map" }) catch unreachable;
print("uid_map_path: {s}\n", .{uid_map_path});
print("gid_map_path: {s}\n", .{gid_map_path});
var uid_map = try fs.openFileAbsolute(uid_map_path, .{ .write = true });
defer uid_map.close();
var gid_map = try fs.openFileAbsolute(gid_map_path, .{ .write = true });
defer gid_map.close();
var uid_map_contents = try fmt.allocPrint(allocator, "0 {} 1", .{uid});
defer allocator.free(uid_map_contents);
var gid_map_contents = try fmt.allocPrint(allocator, "0 {} 1", .{gid});
defer allocator.free(gid_map_contents);
try uid_map.writer().writeAll(uid_map_contents);
try gid_map.writer().writeAll(gid_map_contents);
const child_args = [_:null]?[*:0]const u8{ "/bin/sh", null };
const envp = [_:null]?[*:0]const u8{null};
try os.execveZ("/bin/sh", &child_args, &envp) catch return;
}
// Use fork and unshare to create a new process with a new PID
// youki: https://github.com/containers/youki/blob/619ae7d1eccbd82fd116465ed25ef410ace2a2a1/crates/libcontainer/src/process/container_main_process.rs#L206-L240
pub fn main() !void {
var arena = ArenaAllocator.init(std.heap.page_allocator);
defer arena.deinit();
const allocator = arena.allocator();
var pid = os.fork() catch {
print("fork failed\n", .{});
os.exit(1);
};
if (pid == 0) { // child
try child(allocator);
} else { // parent
try parent(pid);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment