From 44c8acff166bafea8d4283a7b945c9786b69849c Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Sat, 18 Oct 2025 12:03:48 +0200 Subject: [PATCH] Open new log file handle after fork() This would also need to be done in the nested fork() calls. Signed-off-by: AnErrupTion --- src/auth.zig | 6 +++++ src/main.zig | 64 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/src/auth.zig b/src/auth.zig index 6e6a2a9..62edbfa 100644 --- a/src/auth.zig +++ b/src/auth.zig @@ -57,25 +57,31 @@ pub fn authenticate(allocator: std.mem.Allocator, log_writer: *std.Io.Writer, op }; var handle: ?*interop.pam.pam_handle = undefined; + try log_writer.writeAll("[pam] starting session\n"); var status = interop.pam.pam_start(options.service_name, null, &conv, &handle); if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status); defer _ = interop.pam.pam_end(handle, status); // Set PAM_TTY as the current TTY. This is required in case it isn't being set by another PAM module + try log_writer.writeAll("[pam] setting tty\n"); status = interop.pam.pam_set_item(handle, interop.pam.PAM_TTY, pam_tty_str.ptr); if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status); // Do the PAM routine + try log_writer.writeAll("[pam] authenticating\n"); status = interop.pam.pam_authenticate(handle, 0); if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status); + try log_writer.writeAll("[pam] validating account\n"); status = interop.pam.pam_acct_mgmt(handle, 0); if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status); + try log_writer.writeAll("[pam] setting credentials\n"); status = interop.pam.pam_setcred(handle, interop.pam.PAM_ESTABLISH_CRED); if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status); defer status = interop.pam.pam_setcred(handle, interop.pam.PAM_DELETE_CRED); + try log_writer.writeAll("[pam] opening session\n"); status = interop.pam.pam_open_session(handle, 0); if (status != interop.pam.PAM_SUCCESS) return pamDiagnose(status); defer status = interop.pam.pam_close_session(handle, 0); diff --git a/src/main.zig b/src/main.zig index b69c669..decc6d3 100644 --- a/src/main.zig +++ b/src/main.zig @@ -264,29 +264,9 @@ pub fn main() !void { var log_file: std.fs.File = undefined; defer log_file.close(); - var could_open_log_file = true; - open_log_file: { - log_file = std.fs.cwd().openFile(config.ly_log, .{ .mode = .write_only }) catch std.fs.cwd().createFile(config.ly_log, .{ .mode = 0o666 }) catch { - // If we could neither open an existing log file nor create a new - // one, abort. - could_open_log_file = false; - break :open_log_file; - }; - } - - if (!could_open_log_file) { - log_file = try std.fs.openFileAbsolute("/dev/null", .{ .mode = .write_only }); - } - var log_buffer: [1024]u8 = undefined; - var log_file_writer = log_file.writer(&log_buffer); - - // Seek to the end of the log file - if (could_open_log_file) { - const stat = try log_file.stat(); - try log_file_writer.seekTo(stat.size); - } - + var log_file_writer: std.fs.File.Writer = undefined; + var could_open_log_file = try openLogFile(config.ly_log, &log_file, &log_buffer, &log_file_writer); var log_writer = &log_file_writer.interface; // These strings only end up getting freed if the user quits Ly using Ctrl+C, which is fine since in the other cases @@ -937,6 +917,8 @@ pub fn main() !void { defer shared_err.deinit(); { + log_file.close(); + session_pid = try std.posix.fork(); if (session_pid == 0) { const current_environment = session.label.list.items[session.label.current].environment; @@ -960,10 +942,18 @@ pub fn main() !void { }; std.posix.sigaction(std.posix.SIG.CHLD, &tty_control_transfer_act, null); + could_open_log_file = try openLogFile(config.ly_log, &log_file, &log_buffer, &log_file_writer); + log_writer = &log_file_writer.interface; + defer log_file.close(); + auth.authenticate(allocator, log_writer, auth_options, current_environment, login.getCurrentUsername(), password.text.items) catch |err| { shared_err.writeError(err); + + try log_writer.flush(); std.process.exit(1); }; + + try log_writer.flush(); std.process.exit(0); } @@ -972,6 +962,9 @@ pub fn main() !void { // This is a workaround to ensure the session process has exited before re-initializing the TTY. std.Thread.sleep(std.time.ns_per_s * 1); session_pid = -1; + + could_open_log_file = try openLogFile(config.ly_log, &log_file, &log_buffer, &log_file_writer); + log_writer = &log_file_writer.interface; } // Take back control of the TTY @@ -1060,6 +1053,33 @@ pub fn main() !void { } } +fn openLogFile(path: []const u8, log_file: *std.fs.File, buffer: []u8, writer: *std.fs.File.Writer) !bool { + var could_open_log_file = true; + open_log_file: { + log_file.* = std.fs.cwd().openFile(path, .{ .mode = .write_only }) catch std.fs.cwd().createFile(path, .{ .mode = 0o666 }) catch { + // If we could neither open an existing log file nor create a new + // one, abort. + could_open_log_file = false; + break :open_log_file; + }; + } + + if (!could_open_log_file) { + log_file.* = try std.fs.openFileAbsolute("/dev/null", .{ .mode = .write_only }); + } + + var log_file_writer = log_file.writer(buffer); + + // Seek to the end of the log file + if (could_open_log_file) { + const stat = try log_file.stat(); + try log_file_writer.seekTo(stat.size); + } + + writer.* = log_file_writer; + return could_open_log_file; +} + fn configErrorHandler(type_name: []const u8, key: []const u8, value: []const u8, err: anyerror) void { config_errors.append(temporary_allocator, .{ .type_name = temporary_allocator.dupe(u8, type_name) catch return,