diff --git a/src/libnss.zig b/src/libnss.zig index b20b260..eedc850 100644 --- a/src/libnss.zig +++ b/src/libnss.zig @@ -87,9 +87,13 @@ fn init() void { ); } } - //if (os.argv.len == 0) break :blk false; - //break :blk mem.eql(u8, mem.sliceTo(os.argv[0], 0), "id"); - break :blk false; // https://github.com/ziglang/zig/issues/4524#issuecomment-1184748756 + + // argv does not exist because + // https://github.com/ziglang/zig/issues/4524#issuecomment-1184748756 + // so reading /proc/self/cmdline because + const fd = os.openZ("/proc/self/cmdline", os.O.RDONLY, 0) catch break :blk false; + defer os.close(fd); + break :blk isId(fd); }; const fname = if (getenv(ENV_DB)) |env| @@ -540,6 +544,25 @@ fn getDBErrno(errnop: *c_int) ?*const DB { } } +// isId tells if this command is "id". Reads the cmdline +// from the given fd. Returns false on any error. +fn isId(fd: os.fd_t) bool { + var cmdline: [256]u8 = undefined; + const nb = os.read(fd, cmdline[0..]) catch return false; + const arg0 = mem.sliceTo(cmdline[0..nb], 0); + + if (arg0.len < 2) + return false; + + if (!mem.eql(u8, arg0[arg0.len - 2 .. arg0.len], "id")) + return false; + + if (arg0.len == 2) + return true; + + return arg0[arg0.len - 3] == '/'; +} + const testing = std.testing; test "libnss getpwuid_r and getpwnam_r" { @@ -675,3 +698,27 @@ test "libnss initgroups_dyn" { try testing.expectEqual(@as(u32, 9999), groups[1]); try testing.expectEqual(@as(u32, 100000), groups[2]); } + +test "libnss isId" { + const examples = [_]struct { + cmdline: []const u8, + want: bool, + }{ + .{ .want = true, .cmdline = "id\x00foo" }, + .{ .want = true, .cmdline = "/usr/bin/id\x00foo" }, + .{ .want = true, .cmdline = "id" }, + .{ .want = true, .cmdline = "/usr/bin/id" }, + .{ .want = false, .cmdline = "" }, + .{ .want = false, .cmdline = "d\x00" }, + .{ .want = false, .cmdline = "/fakeid" }, + }; + + for (examples) |tt| { + const fd = try os.memfd_create("test_libnss_isId", 0); + defer os.close(fd); + _ = try os.write(fd, tt.cmdline); + try os.lseek_SET(fd, 0); + const got = isId(fd); + try testing.expectEqual(tt.want, got); + } +}