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 {...@@ -44,10 +44,10 @@ pub const ChildProcess = struct {
44 stderr_behavior: StdIo,44 stderr_behavior: StdIo,
4545
46 /// Set to change the user id when spawning the child process.46 /// 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
49 /// Set to change the group id when spawning the child process.49 /// 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
52 /// Set to change the current working directory when spawning the child process.52 /// Set to change the current working directory when spawning the child process.
53 cwd: ?[]const u8,53 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...@@ -2512,13 +2512,14 @@ pub fn readlinkatZ(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) Read
2512 }2512 }
2513}2513}
25142514
2515pub const SetIdError = error{2515pub const SetEidError = error{
2516 ResourceLimitReached,
2517 InvalidUserId,2516 InvalidUserId,
2518 PermissionDenied,2517 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 {
2522 switch (errno(system.setuid(uid))) {2523 switch (errno(system.setuid(uid))) {
2523 0 => return,2524 0 => return,
2524 EAGAIN => return error.ResourceLimitReached,2525 EAGAIN => return error.ResourceLimitReached,
...@@ -2528,7 +2529,16 @@ pub fn setuid(uid: u32) SetIdError!void {...@@ -2528,7 +2529,16 @@ pub fn setuid(uid: u32) SetIdError!void {
2528 }2529 }
2529}2530}
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 {
2532 switch (errno(system.setreuid(ruid, euid))) {2542 switch (errno(system.setreuid(ruid, euid))) {
2533 0 => return,2543 0 => return,
2534 EAGAIN => return error.ResourceLimitReached,2544 EAGAIN => return error.ResourceLimitReached,
...@@ -2538,7 +2548,7 @@ pub fn setreuid(ruid: u32, euid: u32) SetIdError!void {...@@ -2538,7 +2548,7 @@ pub fn setreuid(ruid: u32, euid: u32) SetIdError!void {
2538 }2548 }
2539}2549}
25402550
2541pub fn setgid(gid: u32) SetIdError!void {2551pub fn setgid(gid: gid_t) SetIdError!void {
2542 switch (errno(system.setgid(gid))) {2552 switch (errno(system.setgid(gid))) {
2543 0 => return,2553 0 => return,
2544 EAGAIN => return error.ResourceLimitReached,2554 EAGAIN => return error.ResourceLimitReached,
...@@ -2548,7 +2558,16 @@ pub fn setgid(gid: u32) SetIdError!void {...@@ -2548,7 +2558,16 @@ pub fn setgid(gid: u32) SetIdError!void {
2548 }2558 }
2549}2559}
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 {
2552 switch (errno(system.setregid(rgid, egid))) {2571 switch (errno(system.setregid(rgid, egid))) {
2553 0 => return,2572 0 => return,
2554 EAGAIN => return error.ResourceLimitReached,2573 EAGAIN => return error.ResourceLimitReached,
lib/std/os/bits/darwin.zig+6-2
...@@ -7,9 +7,13 @@ const std = @import("../../std.zig");...@@ -7,9 +7,13 @@ const std = @import("../../std.zig");
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const maxInt = std.math.maxInt;8const 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
10pub const fd_t = c_int;12pub const fd_t = c_int;
11pub const pid_t = c_int;13pub const pid_t = c_int;
12pub const mode_t = c_uint;14pub const mode_t = c_uint;
15pub const uid_t = u32;
16pub const gid_t = u32;
1317
14pub const in_port_t = u16;18pub const in_port_t = u16;
15pub const sa_family_t = u8;19pub const sa_family_t = u8;
...@@ -79,8 +83,8 @@ pub const Stat = extern struct {...@@ -79,8 +83,8 @@ pub const Stat = extern struct {
79 mode: u16,83 mode: u16,
80 nlink: u16,84 nlink: u16,
81 ino: ino_t,85 ino: ino_t,
82 uid: u32,86 uid: uid_t,
83 gid: u32,87 gid: gid_t,
84 rdev: i32,88 rdev: i32,
85 atimesec: isize,89 atimesec: isize,
86 atimensec: isize,90 atimensec: isize,
lib/std/os/bits/dragonfly.zig+10-3
...@@ -9,10 +9,17 @@ const maxInt = std.math.maxInt;...@@ -9,10 +9,17 @@ const maxInt = std.math.maxInt;
9pub fn S_ISCHR(m: u32) bool {9pub fn S_ISCHR(m: u32) bool {
10 return m & S_IFMT == S_IFCHR;10 return m & S_IFMT == S_IFCHR;
11}11}
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
12pub const fd_t = c_int;17pub const fd_t = c_int;
13pub const pid_t = c_int;18pub const pid_t = c_int;
14pub const off_t = c_long;19pub const off_t = c_long;
15pub const mode_t = c_uint;20pub const mode_t = c_uint;
21pub const uid_t = u32;
22pub const gid_t = u32;
1623
17pub const ENOTSUP = EOPNOTSUPP;24pub const ENOTSUP = EOPNOTSUPP;
18pub const EWOULDBLOCK = EAGAIN;25pub const EWOULDBLOCK = EAGAIN;
...@@ -151,8 +158,8 @@ pub const Stat = extern struct {...@@ -151,8 +158,8 @@ pub const Stat = extern struct {
151 dev: c_uint,158 dev: c_uint,
152 mode: c_ushort,159 mode: c_ushort,
153 padding1: u16,160 padding1: u16,
154 uid: c_uint,161 uid: uid_t,
155 gid: c_uint,162 gid: gid_t,
156 rdev: c_uint,163 rdev: c_uint,
157 atim: timespec,164 atim: timespec,
158 mtim: timespec,165 mtim: timespec,
...@@ -511,7 +518,7 @@ pub const siginfo_t = extern struct {...@@ -511,7 +518,7 @@ pub const siginfo_t = extern struct {
511 si_errno: c_int,518 si_errno: c_int,
512 si_code: c_int,519 si_code: c_int,
513 si_pid: c_int,520 si_pid: c_int,
514 si_uid: c_uint,521 si_uid: uid_t,
515 si_status: c_int,522 si_status: c_int,
516 si_addr: ?*c_void,523 si_addr: ?*c_void,
517 si_value: union_sigval,524 si_value: union_sigval,
lib/std/os/bits/freebsd.zig+6-2
...@@ -6,8 +6,12 @@...@@ -6,8 +6,12 @@
6const std = @import("../../std.zig");6const std = @import("../../std.zig");
7const maxInt = std.math.maxInt;7const 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
9pub const fd_t = c_int;11pub const fd_t = c_int;
10pub const pid_t = c_int;12pub const pid_t = c_int;
13pub const uid_t = u32;
14pub const gid_t = u32;
11pub const mode_t = c_uint;15pub const mode_t = c_uint;
1216
13pub const socklen_t = u32;17pub const socklen_t = u32;
...@@ -128,8 +132,8 @@ pub const Stat = extern struct {...@@ -128,8 +132,8 @@ pub const Stat = extern struct {
128132
129 mode: u16,133 mode: u16,
130 __pad0: u16,134 __pad0: u16,
131 uid: u32,135 uid: uid_t,
132 gid: u32,136 gid: gid_t,
133 __pad1: u32,137 __pad1: u32,
134 rdev: u64,138 rdev: u64,
135139
lib/std/os/bits/linux.zig+4-4
...@@ -29,7 +29,7 @@ const is_mips = builtin.arch.isMIPS();...@@ -29,7 +29,7 @@ const is_mips = builtin.arch.isMIPS();
2929
30pub const pid_t = i32;30pub const pid_t = i32;
31pub const fd_t = i32;31pub const fd_t = i32;
32pub const uid_t = i32;32pub const uid_t = u32;
33pub const gid_t = u32;33pub const gid_t = u32;
34pub const clock_t = isize;34pub const clock_t = isize;
3535
...@@ -853,7 +853,7 @@ pub const signalfd_siginfo = extern struct {...@@ -853,7 +853,7 @@ pub const signalfd_siginfo = extern struct {
853 errno: i32,853 errno: i32,
854 code: i32,854 code: i32,
855 pid: u32,855 pid: u32,
856 uid: u32,856 uid: uid_t,
857 fd: i32,857 fd: i32,
858 tid: u32,858 tid: u32,
859 band: u32,859 band: u32,
...@@ -1491,10 +1491,10 @@ pub const Statx = extern struct {...@@ -1491,10 +1491,10 @@ pub const Statx = extern struct {
1491 nlink: u32,1491 nlink: u32,
14921492
1493 /// User ID of owner1493 /// User ID of owner
1494 uid: u32,1494 uid: uid_t,
14951495
1496 /// Group ID of owner1496 /// Group ID of owner
1497 gid: u32,1497 gid: gid_t,
14981498
1499 /// File type and mode1499 /// File type and mode
1500 mode: u16,1500 mode: u16,
lib/std/os/bits/linux/x86_64.zig+3-2
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7const std = @import("../../../std.zig");7const std = @import("../../../std.zig");
8const pid_t = linux.pid_t;8const pid_t = linux.pid_t;
9const uid_t = linux.uid_t;9const uid_t = linux.uid_t;
10const gid_t = linux.gid_t;
10const clock_t = linux.clock_t;11const clock_t = linux.clock_t;
11const stack_t = linux.stack_t;12const stack_t = linux.stack_t;
12const sigset_t = linux.sigset_t;13const sigset_t = linux.sigset_t;
...@@ -523,8 +524,8 @@ pub const Stat = extern struct {...@@ -523,8 +524,8 @@ pub const Stat = extern struct {
523 nlink: usize,524 nlink: usize,
524525
525 mode: u32,526 mode: u32,
526 uid: u32,527 uid: uid_t,
527 gid: u32,528 gid: gid_t,
528 __pad0: u32,529 __pad0: u32,
529 rdev: u64,530 rdev: u64,
530 size: off_t,531 size: off_t,
lib/std/os/linux.zig+40-26
...@@ -655,7 +655,7 @@ pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {...@@ -655,7 +655,7 @@ pub fn nanosleep(req: *const timespec, rem: ?*timespec) usize {
655 return syscall2(.nanosleep, @ptrToInt(req), @ptrToInt(rem));655 return syscall2(.nanosleep, @ptrToInt(req), @ptrToInt(rem));
656}656}
657657
658pub fn setuid(uid: u32) usize {658pub fn setuid(uid: uid_t) usize {
659 if (@hasField(SYS, "setuid32")) {659 if (@hasField(SYS, "setuid32")) {
660 return syscall1(.setuid32, uid);660 return syscall1(.setuid32, uid);
661 } else {661 } else {
...@@ -663,7 +663,7 @@ pub fn setuid(uid: u32) usize {...@@ -663,7 +663,7 @@ pub fn setuid(uid: u32) usize {
663 }663 }
664}664}
665665
666pub fn setgid(gid: u32) usize {666pub fn setgid(gid: gid_t) usize {
667 if (@hasField(SYS, "setgid32")) {667 if (@hasField(SYS, "setgid32")) {
668 return syscall1(.setgid32, gid);668 return syscall1(.setgid32, gid);
669 } else {669 } else {
...@@ -671,7 +671,7 @@ pub fn setgid(gid: u32) usize {...@@ -671,7 +671,7 @@ pub fn setgid(gid: u32) usize {
671 }671 }
672}672}
673673
674pub fn setreuid(ruid: u32, euid: u32) usize {674pub fn setreuid(ruid: uid_t, euid: uid_t) usize {
675 if (@hasField(SYS, "setreuid32")) {675 if (@hasField(SYS, "setreuid32")) {
676 return syscall2(.setreuid32, ruid, euid);676 return syscall2(.setreuid32, ruid, euid);
677 } else {677 } else {
...@@ -679,7 +679,7 @@ pub fn setreuid(ruid: u32, euid: u32) usize {...@@ -679,7 +679,7 @@ pub fn setreuid(ruid: u32, euid: u32) usize {
679 }679 }
680}680}
681681
682pub fn setregid(rgid: u32, egid: u32) usize {682pub fn setregid(rgid: gid_t, egid: gid_t) usize {
683 if (@hasField(SYS, "setregid32")) {683 if (@hasField(SYS, "setregid32")) {
684 return syscall2(.setregid32, rgid, egid);684 return syscall2(.setregid32, rgid, egid);
685 } else {685 } else {
...@@ -687,47 +687,61 @@ pub fn setregid(rgid: u32, egid: u32) usize {...@@ -687,47 +687,61 @@ pub fn setregid(rgid: u32, egid: u32) usize {
687 }687 }
688}688}
689689
690pub fn getuid() u32 {690pub fn getuid() uid_t {
691 if (@hasField(SYS, "getuid32")) {691 if (@hasField(SYS, "getuid32")) {
692 return @as(u32, syscall0(.getuid32));692 return @as(uid_t, syscall0(.getuid32));
693 } else {693 } else {
694 return @as(u32, syscall0(.getuid));694 return @as(uid_t, syscall0(.getuid));
695 }695 }
696}696}
697697
698pub fn getgid() u32 {698pub fn getgid() gid_t {
699 if (@hasField(SYS, "getgid32")) {699 if (@hasField(SYS, "getgid32")) {
700 return @as(u32, syscall0(.getgid32));700 return @as(gid_t, syscall0(.getgid32));
701 } else {701 } else {
702 return @as(u32, syscall0(.getgid));702 return @as(gid_t, syscall0(.getgid));
703 }703 }
704}704}
705705
706pub fn geteuid() u32 {706pub fn geteuid() uid_t {
707 if (@hasField(SYS, "geteuid32")) {707 if (@hasField(SYS, "geteuid32")) {
708 return @as(u32, syscall0(.geteuid32));708 return @as(uid_t, syscall0(.geteuid32));
709 } else {709 } else {
710 return @as(u32, syscall0(.geteuid));710 return @as(uid_t, syscall0(.geteuid));
711 }711 }
712}712}
713713
714pub fn getegid() u32 {714pub fn getegid() gid_t {
715 if (@hasField(SYS, "getegid32")) {715 if (@hasField(SYS, "getegid32")) {
716 return @as(u32, syscall0(.getegid32));716 return @as(gid_t, syscall0(.getegid32));
717 } else {717 } else {
718 return @as(u32, syscall0(.getegid));718 return @as(gid_t, syscall0(.getegid));
719 }719 }
720}720}
721721
722pub fn seteuid(euid: u32) usize {722pub fn seteuid(euid: uid_t) usize {
723 return setreuid(std.math.maxInt(u32), euid);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));
724}731}
725732
726pub fn setegid(egid: u32) usize {733pub fn setegid(egid: gid_t) usize {
727 return setregid(std.math.maxInt(u32), egid);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));
728}742}
729743
730pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {744pub fn getresuid(ruid: *uid_t, euid: *uid_t, suid: *uid_t) usize {
731 if (@hasField(SYS, "getresuid32")) {745 if (@hasField(SYS, "getresuid32")) {
732 return syscall3(.getresuid32, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid));746 return syscall3(.getresuid32, @ptrToInt(ruid), @ptrToInt(euid), @ptrToInt(suid));
733 } else {747 } else {
...@@ -735,7 +749,7 @@ pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {...@@ -735,7 +749,7 @@ pub fn getresuid(ruid: *u32, euid: *u32, suid: *u32) usize {
735 }749 }
736}750}
737751
738pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {752pub fn getresgid(rgid: *gid_t, egid: *gid_t, sgid: *gid_t) usize {
739 if (@hasField(SYS, "getresgid32")) {753 if (@hasField(SYS, "getresgid32")) {
740 return syscall3(.getresgid32, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid));754 return syscall3(.getresgid32, @ptrToInt(rgid), @ptrToInt(egid), @ptrToInt(sgid));
741 } else {755 } else {
...@@ -743,7 +757,7 @@ pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {...@@ -743,7 +757,7 @@ pub fn getresgid(rgid: *u32, egid: *u32, sgid: *u32) usize {
743 }757 }
744}758}
745759
746pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {760pub fn setresuid(ruid: uid_t, euid: uid_t, suid: uid_t) usize {
747 if (@hasField(SYS, "setresuid32")) {761 if (@hasField(SYS, "setresuid32")) {
748 return syscall3(.setresuid32, ruid, euid, suid);762 return syscall3(.setresuid32, ruid, euid, suid);
749 } else {763 } else {
...@@ -751,7 +765,7 @@ pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {...@@ -751,7 +765,7 @@ pub fn setresuid(ruid: u32, euid: u32, suid: u32) usize {
751 }765 }
752}766}
753767
754pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {768pub fn setresgid(rgid: gid_t, egid: gid_t, sgid: gid_t) usize {
755 if (@hasField(SYS, "setresgid32")) {769 if (@hasField(SYS, "setresgid32")) {
756 return syscall3(.setresgid32, rgid, egid, sgid);770 return syscall3(.setresgid32, rgid, egid, sgid);
757 } else {771 } else {
...@@ -759,7 +773,7 @@ pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {...@@ -759,7 +773,7 @@ pub fn setresgid(rgid: u32, egid: u32, sgid: u32) usize {
759 }773 }
760}774}
761775
762pub fn getgroups(size: usize, list: *u32) usize {776pub fn getgroups(size: usize, list: *gid_t) usize {
763 if (@hasField(SYS, "getgroups32")) {777 if (@hasField(SYS, "getgroups32")) {
764 return syscall2(.getgroups32, size, @ptrToInt(list));778 return syscall2(.getgroups32, size, @ptrToInt(list));
765 } else {779 } else {
...@@ -767,7 +781,7 @@ pub fn getgroups(size: usize, list: *u32) usize {...@@ -767,7 +781,7 @@ pub fn getgroups(size: usize, list: *u32) usize {
767 }781 }
768}782}
769783
770pub fn setgroups(size: usize, list: *const u32) usize {784pub fn setgroups(size: usize, list: *const gid_t) usize {
771 if (@hasField(SYS, "setgroups32")) {785 if (@hasField(SYS, "setgroups32")) {
772 return syscall2(.setgroups32, size, @ptrToInt(list));786 return syscall2(.setgroups32, size, @ptrToInt(list));
773 } else {787 } else {
lib/std/process.zig+4-4
...@@ -578,8 +578,8 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons...@@ -578,8 +578,8 @@ fn testWindowsCmdLine(input_cmd_line: [*]const u8, expected_args: []const []cons
578}578}
579579
580pub const UserInfo = struct {580pub const UserInfo = struct {
581 uid: u32,581 uid: os.uid_t,
582 gid: u32,582 gid: os.gid_t,
583};583};
584584
585/// POSIX function which gets a uid from username.585/// POSIX function which gets a uid from username.
...@@ -607,8 +607,8 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {...@@ -607,8 +607,8 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
607 var buf: [std.mem.page_size]u8 = undefined;607 var buf: [std.mem.page_size]u8 = undefined;
608 var name_index: usize = 0;608 var name_index: usize = 0;
609 var state = State.Start;609 var state = State.Start;
610 var uid: u32 = 0;610 var uid: os.uid_t = 0;
611 var gid: u32 = 0;611 var gid: os.gid_t = 0;
612612
613 while (true) {613 while (true) {
614 const amt_read = try reader.read(buf[0..]);614 const amt_read = try reader.read(buf[0..]);