authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-03 18:05:59-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2020-09-03 18:05:59-04:00
log10344591704b9d7317eeaca44681eabd769c4486
tree46422640076b0d5182f12788440154475d893ebe
parent17f36566de1cf549907d20dfd963596784691c73
parentd0d6647fdbfbe1a5764c2624e46eee35052d0da6
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #6243 from ifreund/uid-gid-cleanup

std: clean up usage of uid_t/gid_t, add seteuid/setegid to std.os

9 files changed, 101 insertions(+), 52 deletions(-)

lib/std/child_process.zig+2-2
......@@ -44,10 +44,10 @@ pub const ChildProcess = struct {
4444 stderr_behavior: StdIo,
4545
4646 /// Set to change the user id when spawning the child process.
47 uid: if (builtin.os.tag == .windows) void else ?u32,
47 uid: if (builtin.os.tag == .windows or builtin.os.tag == .wasi) void else ?os.uid_t,
4848
4949 /// Set to change the group id when spawning the child process.
50 gid: if (builtin.os.tag == .windows) void else ?u32,
50 gid: if (builtin.os.tag == .windows or builtin.os.tag == .wasi) void else ?os.gid_t,
5151
5252 /// Set to change the current working directory when spawning the child process.
5353 cwd: ?[]const u8,
lib/std/os.zig+26-7
......@@ -2512,13 +2512,14 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read
25122512 }
25132513}
25142514
2515pub const SetIdError = error{
2516 ResourceLimitReached,
2515pub const SetEidError = error{
25172516 InvalidUserId,
25182517 PermissionDenied,
2519} || UnexpectedError;
2518};
2519
2520pub const SetIdError = error{ResourceLimitReached} || SetEidError || UnexpectedError;
25202521
2521pub fn setuid(uid: u32) SetIdError!void {
2522pub fn setuid(uid: uid_t) SetIdError!void {
25222523 switch (errno(system.setuid(uid))) {
25232524 0 => return,
25242525 EAGAIN => return error.ResourceLimitReached,
......@@ -2528,7 +2529,16 @@ pub fn setuid(uid: u32) SetIdError!void {
25282529 }
25292530}
25302531
2531pub fn setreuid(ruid: u32, euid: u32) SetIdError!void {
2532pub fn seteuid(uid: uid_t) SetEidError!void {
2533 switch (errno(system.seteuid(uid))) {
2534 0 => return,
2535 EINVAL => return error.InvalidUserId,
2536 EPERM => return error.PermissionDenied,
2537 else => |err| return unexpectedErrno(err),
2538 }
2539}
2540
2541pub fn setreuid(ruid: uid_t, euid: uid_t) SetIdError!void {
25322542 switch (errno(system.setreuid(ruid, euid))) {
25332543 0 => return,
25342544 EAGAIN => return error.ResourceLimitReached,
......@@ -2538,7 +2548,7 @@ pub fn setreuid(ruid: u32, euid: u32) SetIdError!void {
25382548 }
25392549}
25402550
2541pub fn setgid(gid: u32) SetIdError!void {
2551pub fn setgid(gid: gid_t) SetIdError!void {
25422552 switch (errno(system.setgid(gid))) {
25432553 0 => return,
25442554 EAGAIN => return error.ResourceLimitReached,
......@@ -2548,7 +2558,16 @@ pub fn setgid(gid: u32) SetIdError!void {
25482558 }
25492559}
25502560
2551pub fn setregid(rgid: u32, egid: u32) SetIdError!void {
2561pub fn setegid(uid: uid_t) SetEidError!void {
2562 switch (errno(system.setegid(uid))) {
2563 0 => return,
2564 EINVAL => return error.InvalidUserId,
2565 EPERM => return error.PermissionDenied,
2566 else => |err| return unexpectedErrno(err),
2567 }
2568}
2569
2570pub fn setregid(rgid: gid_t, egid: gid_t) SetIdError!void {
25522571 switch (errno(system.setregid(rgid, egid))) {
25532572 0 => return,
25542573 EAGAIN => return error.ResourceLimitReached,
lib/std/os/bits/darwin.zig+6-2
......@@ -7,9 +7,13 @@ const std = @import("../../std.zig");
77const assert = std.debug.assert;
88const maxInt = std.math.maxInt;
99
10// See: https://opensource.apple.com/source/xnu/xnu-6153.141.1/bsd/sys/_types.h.auto.html
11// TODO: audit mode_t/pid_t, should likely be u16/i32
1012pub const fd_t = c_int;
1113pub const pid_t = c_int;
1214pub const mode_t = c_uint;
15pub const uid_t = u32;
16pub const gid_t = u32;
1317
1418pub const in_port_t = u16;
1519pub const sa_family_t = u8;
......@@ -79,8 +83,8 @@ pub const Stat = extern struct {
7983 mode: u16,
8084 nlink: u16,
8185 ino: ino_t,
82 uid: u32,
83 gid: u32,
86 uid: uid_t,
87 gid: gid_t,
8488 rdev: i32,
8589 atimesec: isize,
8690 atimensec: isize,
lib/std/os/bits/dragonfly.zig+10-3
......@@ -9,10 +9,17 @@ const maxInt = std.math.maxInt;
99pub fn S_ISCHR(m: u32) bool {
1010 return m & S_IFMT == S_IFCHR;
1111}
12
13// See:
14// - https://gitweb.dragonflybsd.org/dragonfly.git/blob/HEAD:/include/unistd.h
15// - https://gitweb.dragonflybsd.org/dragonfly.git/blob/HEAD:/sys/sys/types.h
16// TODO: mode_t should probably be changed to a u16, audit pid_t/off_t as well
1217pub const fd_t = c_int;
1318pub const pid_t = c_int;
1419pub const off_t = c_long;
1520pub const mode_t = c_uint;
21pub const uid_t = u32;
22pub const gid_t = u32;
1623
1724pub const ENOTSUP = EOPNOTSUPP;
1825pub const EWOULDBLOCK = EAGAIN;
......@@ -151,8 +158,8 @@ pub const Stat = extern struct {
151158 dev: c_uint,
152159 mode: c_ushort,
153160 padding1: u16,
154 uid: c_uint,
155 gid: c_uint,
161 uid: uid_t,
162 gid: gid_t,
156163 rdev: c_uint,
157164 atim: timespec,
158165 mtim: timespec,
......@@ -511,7 +518,7 @@ pub const siginfo_t = extern struct {
511518 si_errno: c_int,
512519 si_code: c_int,
513520 si_pid: c_int,
514 si_uid: c_uint,
521 si_uid: uid_t,
515522 si_status: c_int,
516523 si_addr: ?*c_void,
517524 si_value: union_sigval,
lib/std/os/bits/freebsd.zig+6-2
......@@ -6,8 +6,12 @@
66const std = @import("../../std.zig");
77const maxInt = std.math.maxInt;
88
9// See https://svnweb.freebsd.org/base/head/sys/sys/_types.h?view=co
10// TODO: audit pid_t/mode_t. They should likely be i32 and u16, respectively
911pub const fd_t = c_int;
1012pub const pid_t = c_int;
13pub const uid_t = u32;
14pub const gid_t = u32;
1115pub const mode_t = c_uint;
1216
1317pub const socklen_t = u32;
......@@ -128,8 +132,8 @@ pub const Stat = extern struct {
128132
129133 mode: u16,
130134 __pad0: u16,
131 uid: u32,
132 gid: u32,
135 uid: uid_t,
136 gid: gid_t,
133137 __pad1: u32,
134138 rdev: u64,
135139
lib/std/os/bits/linux.zig+4-4
......@@ -29,7 +29,7 @@ const is_mips = builtin.arch.isMIPS();
2929
3030pub const pid_t = i32;
3131pub const fd_t = i32;
32pub const uid_t = i32;
32pub const uid_t = u32;
3333pub const gid_t = u32;
3434pub const clock_t = isize;
3535
......@@ -853,7 +853,7 @@ pub const signalfd_siginfo = extern struct {
853853 errno: i32,
854854 code: i32,
855855 pid: u32,
856 uid: u32,
856 uid: uid_t,
857857 fd: i32,
858858 tid: u32,
859859 band: u32,
......@@ -1491,10 +1491,10 @@ pub const Statx = extern struct {
14911491 nlink: u32,
14921492
14931493 /// User ID of owner
1494 uid: u32,
1494 uid: uid_t,
14951495
14961496 /// Group ID of owner
1497 gid: u32,
1497 gid: gid_t,
14981498
14991499 /// File type and mode
15001500 mode: u16,
lib/std/os/bits/linux/x86_64.zig+3-2
......@@ -7,6 +7,7 @@
77const std = @import("../../../std.zig");
88const pid_t = linux.pid_t;
99const uid_t = linux.uid_t;
10const gid_t = linux.gid_t;
1011const clock_t = linux.clock_t;
1112const stack_t = linux.stack_t;
1213const sigset_t = linux.sigset_t;
......@@ -523,8 +524,8 @@ pub const Stat = extern struct {
523524 nlink: usize,
524525
525526 mode: u32,
526 uid: u32,
527 gid: u32,
527 uid: uid_t,
528 gid: gid_t,
528529 __pad0: u32,
529530 rdev: u64,
530531 size: off_t,
lib/std/os/linux.zig+40-26
......@@ -655,7 +655,7 @@ pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
655655 return syscall2(.nanosleep, @ptrToInt(req), @ptrToInt(rem));
656656}
657657
658pub fn setuid(uid: u32) usize {
658pub fn setuid(uid: uid_t) usize {
659659 if (@hasField(SYS, "setuid32")) {
660660 return syscall1(.setuid32, uid);
661661 } else {
......@@ -663,7 +663,7 @@ pub fn setuid(uid: u32) usize {
663663 }
664664}
665665
666pub fn setgid(gid: u32) usize {
666pub fn setgid(gid: gid_t) usize {
667667 if (@hasField(SYS, "setgid32")) {
668668 return syscall1(.setgid32, gid);
669669 } else {
......@@ -671,7 +671,7 @@ pub fn setgid(gid: u32) usize {
671671 }
672672}
673673
674pub fn setreuid(ruid: u32, euid: u32) usize {
674pub fn setreuid(ruid: uid_t, euid: uid_t) usize {
675675 if (@hasField(SYS, "setreuid32")) {
676676 return syscall2(.setreuid32, ruid, euid);
677677 } else {
......@@ -679,7 +679,7 @@ pub fn setreuid(ruid: u32, euid: u32) usize {
679679 }
680680}
681681
682pub fn setregid(rgid: u32, egid: u32) usize {
682pub fn setregid(rgid: gid_t, egid: gid_t) usize {
683683 if (@hasField(SYS, "setregid32")) {
684684 return syscall2(.setregid32, rgid, egid);
685685 } else {
......@@ -687,47 +687,61 @@ pub fn setregid(rgid: u32, egid: u32) usize {
687687 }
688688}
689689
690pub fn getuid() u32 {
690pub fn getuid() uid_t {
691691 if (@hasField(SYS, "getuid32")) {
692 return @as(u32, syscall0(.getuid32));
692 return @as(uid_t, syscall0(.getuid32));
693693 } else {
694 return @as(u32, syscall0(.getuid));
694 return @as(uid_t, syscall0(.getuid));
695695 }
696696}
697697
698pub fn getgid() u32 {
698pub fn getgid() gid_t {
699699 if (@hasField(SYS, "getgid32")) {
700 return @as(u32, syscall0(.getgid32));
700 return @as(gid_t, syscall0(.getgid32));
701701 } else {
702 return @as(u32, syscall0(.getgid));
702 return @as(gid_t, syscall0(.getgid));
703703 }
704704}
705705
706pub fn geteuid() u32 {
706pub fn geteuid() uid_t {
707707 if (@hasField(SYS, "geteuid32")) {
708 return @as(u32, syscall0(.geteuid32));
708 return @as(uid_t, syscall0(.geteuid32));
709709 } else {
710 return @as(u32, syscall0(.geteuid));
710 return @as(uid_t, syscall0(.geteuid));
711711 }
712712}
713713
714pub fn getegid() u32 {
714pub fn getegid() gid_t {
715715 if (@hasField(SYS, "getegid32")) {
716 return @as(u32, syscall0(.getegid32));
716 return @as(gid_t, syscall0(.getegid32));
717717 } else {
718 return @as(u32, syscall0(.getegid));
718 return @as(gid_t, syscall0(.getegid));
719719 }
720720}
721721
722pub fn seteuid(euid: u32) usize {
723 return setreuid(std.math.maxInt(u32), euid);
722pub fn seteuid(euid: uid_t) usize {
723 // We use setresuid here instead of setreuid to ensure that the saved uid
724 // is not changed. This is what musl and recent glibc versions do as well.
725 //
726 // The setresuid(2) man page says that if -1 is passed the corresponding
727 // id will not be changed. Since uid_t is unsigned, this wraps around to the
728 // max value in C.
729 comptime assert(@typeInfo(uid_t) == .Int and !@typeInfo(uid_t).Int.is_signed);
730 return setresuid(std.math.maxInt(uid_t), euid, std.math.maxInt(uid_t));
724731}
725732
726pub fn setegid(egid: u32) usize {
727 return setregid(std.math.maxInt(u32), egid);
733pub fn setegid(egid: gid_t) usize {
734 // We use setresgid here instead of setregid to ensure that the saved uid
735 // is not changed. This is what musl and recent glibc versions do as well.
736 //
737 // The setresgid(2) man page says that if -1 is passed the corresponding
738 // id will not be changed. Since gid_t is unsigned, this wraps around to the
739 // max value in C.
740 comptime assert(@typeInfo(uid_t) == .Int and !@typeInfo(uid_t).Int.is_signed);
741 return setresgid(std.math.maxInt(gid_t), egid, std.math.maxInt(gid_t));
728742}
729743
730pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {
744pub fn getresuid(ruid: *uid_t, euid: *uid_t, suid: *uid_t) usize {
731745 if (@hasField(SYS, "getresuid32")) {
732746 return syscall3(.getresuid32, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid));
733747 } else {
......@@ -735,7 +749,7 @@ pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {
735749 }
736750}
737751
738pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {
752pub fn getresgid(rgid: *gid_t, egid: *gid_t, sgid: *gid_t) usize {
739753 if (@hasField(SYS, "getresgid32")) {
740754 return syscall3(.getresgid32, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid));
741755 } else {
......@@ -743,7 +757,7 @@ pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {
743757 }
744758}
745759
746pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {
760pub fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) usize {
747761 if (@hasField(SYS, "setresuid32")) {
748762 return syscall3(.setresuid32, ruid, euid, suid);
749763 } else {
......@@ -751,7 +765,7 @@ pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {
751765 }
752766}
753767
754pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {
768pub fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) usize {
755769 if (@hasField(SYS, "setresgid32")) {
756770 return syscall3(.setresgid32, rgid, egid, sgid);
757771 } else {
......@@ -759,7 +773,7 @@ pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {
759773 }
760774}
761775
762pub fn getgroups(size: usize, list: *u32) usize {
776pub fn getgroups(size: usize, list: *gid_t) usize {
763777 if (@hasField(SYS, "getgroups32")) {
764778 return syscall2(.getgroups32, size, @ptrToInt(list));
765779 } else {
......@@ -767,7 +781,7 @@ pub fn getgroups(size: usize, list: *u32) usize {
767781 }
768782}
769783
770pub fn setgroups(size: usize, list: *const u32) usize {
784pub fn setgroups(size: usize, list: *const gid_t) usize {
771785 if (@hasField(SYS, "setgroups32")) {
772786 return syscall2(.setgroups32, size, @ptrToInt(list));
773787 } else {
lib/std/process.zig+4-4
......@@ -578,8 +578,8 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons
578578}
579579
580580pub const UserInfo = struct {
581 uid: u32,
582 gid: u32,
581 uid: os.uid_t,
582 gid: os.gid_t,
583583};
584584
585585/// POSIX function which gets a uid from username.
......@@ -607,8 +607,8 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
607607 var buf: [std.mem.page_size]u8 = undefined;
608608 var name_index: usize = 0;
609609 var state = State.Start;
610 var uid: u32 = 0;
611 var gid: u32 = 0;
610 var uid: os.uid_t = 0;
611 var gid: os.gid_t = 0;
612612
613613 while (true) {
614614 const amt_read = try reader.read(buf[0..]);