| ... | @@ -1,10 +1,8 @@ | ... | @@ -1,10 +1,8 @@ |
| 1 | //! This file provides the system interface functions for Linux matching those | 1 | //! This file provides the system interface functions for Linux matching those |
| 2 | //! that are provided by libc, whether or not libc is linked. The following | 2 | //! that are provided by libc, whether or not libc is linked. The following |
| 3 | //! abstractions are made: | 3 | //! abstractions are made: |
| 4 | //! * Work around kernel bugs and limitations. For example, see sendmmsg. | | |
| 5 | //! * Implement all the syscalls in the same way that libc functions will | 4 | //! * Implement all the syscalls in the same way that libc functions will |
| 6 | //! provide `rename` when only the `renameat` syscall exists. | 5 | //! provide `rename` when only the `renameat` syscall exists. |
| 7 | //! * Does not support POSIX thread cancellation. | | |
| 8 | const std = @import("../std.zig"); | 6 | const std = @import("../std.zig"); |
| 9 | const builtin = @import("builtin"); | 7 | const builtin = @import("builtin"); |
| 10 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
| ... | @@ -1836,7 +1834,7 @@ pub fn seteuid(euid: uid_t) usize { | ... | @@ -1836,7 +1834,7 @@ pub fn seteuid(euid: uid_t) usize { |
| 1836 | // id will not be changed. Since uid_t is unsigned, this wraps around to the | 1834 | // id will not be changed. Since uid_t is unsigned, this wraps around to the |
| 1837 | // max value in C. | 1835 | // max value in C. |
| 1838 | comptime assert(@typeInfo(uid_t) == .int and @typeInfo(uid_t).int.signedness == .unsigned); | 1836 | comptime assert(@typeInfo(uid_t) == .int and @typeInfo(uid_t).int.signedness == .unsigned); |
| 1839 | return setresuid(std.math.maxInt(uid_t), euid, std.math.maxInt(uid_t)); | 1837 | return setresuid(maxInt(uid_t), euid, maxInt(uid_t)); |
| 1840 | } | 1838 | } |
| 1841 | | 1839 | |
| 1842 | pub fn setegid(egid: gid_t) usize { | 1840 | pub fn setegid(egid: gid_t) usize { |
| ... | @@ -1847,7 +1845,7 @@ pub fn setegid(egid: gid_t) usize { | ... | @@ -1847,7 +1845,7 @@ pub fn setegid(egid: gid_t) usize { |
| 1847 | // id will not be changed. Since gid_t is unsigned, this wraps around to the | 1845 | // id will not be changed. Since gid_t is unsigned, this wraps around to the |
| 1848 | // max value in C. | 1846 | // max value in C. |
| 1849 | comptime assert(@typeInfo(uid_t) == .int and @typeInfo(uid_t).int.signedness == .unsigned); | 1847 | comptime assert(@typeInfo(uid_t) == .int and @typeInfo(uid_t).int.signedness == .unsigned); |
| 1850 | return setresgid(std.math.maxInt(gid_t), egid, std.math.maxInt(gid_t)); | 1848 | return setresgid(maxInt(gid_t), egid, maxInt(gid_t)); |
| 1851 | } | 1849 | } |
| 1852 | | 1850 | |
| 1853 | pub fn getresuid(ruid: *uid_t, euid: *uid_t, suid: *uid_t) usize { | 1851 | pub fn getresuid(ruid: *uid_t, euid: *uid_t, suid: *uid_t) usize { |
| ... | @@ -2081,44 +2079,13 @@ pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize { | ... | @@ -2081,44 +2079,13 @@ pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize { |
| 2081 | } | 2079 | } |
| 2082 | } | 2080 | } |
| 2083 | | 2081 | |
| | 2082 | /// Warning: libc is defined to have incompatible integer types with the |
| | 2083 | /// corresponding kernel data structures for this syscall. |
| | 2084 | /// |
| | 2085 | /// Warning: on 64-bit systems, if any message length would exceed `maxInt(i32)`, |
| | 2086 | /// number of bytes sent cannot be determined, because the kernel uses `ssize_t` |
| | 2087 | /// for `sendmsg` return value but `int` for the corresponding values here. |
| 2084 | pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize { | 2088 | pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize { |
| 2085 | if (@typeInfo(usize).int.bits > @typeInfo(@typeInfo(mmsghdr).@"struct".fields[1].type).int.bits) { | | |
| 2086 | // workaround kernel brokenness: | | |
| 2087 | // if adding up all iov_len overflows a i32 then split into multiple calls | | |
| 2088 | // see https://www.openwall.com/lists/musl/2014/06/07/5 | | |
| 2089 | const kvlen = if (vlen > IOV_MAX) IOV_MAX else vlen; // matches kernel | | |
| 2090 | var next_unsent: usize = 0; | | |
| 2091 | for (msgvec[0..kvlen], 0..) |*msg, i| { | | |
| 2092 | var size: i32 = 0; | | |
| 2093 | const msg_iovlen = @as(usize, @intCast(msg.hdr.iovlen)); // kernel side this is treated as unsigned | | |
| 2094 | for (msg.hdr.iov[0..msg_iovlen]) |iov| { | | |
| 2095 | if (iov.len > std.math.maxInt(i32) or @addWithOverflow(size, @as(i32, @intCast(iov.len)))[1] != 0) { | | |
| 2096 | // batch-send all messages up to the current message | | |
| 2097 | if (next_unsent < i) { | | |
| 2098 | const batch_size = i - next_unsent; | | |
| 2099 | const r = syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(&msgvec[next_unsent]), batch_size, flags); | | |
| 2100 | if (E.init(r) != .SUCCESS) return next_unsent; | | |
| 2101 | if (r < batch_size) return next_unsent + r; | | |
| 2102 | } | | |
| 2103 | // send current message as own packet | | |
| 2104 | const r = sendmsg(fd, &msg.hdr, flags); | | |
| 2105 | if (E.init(r) != .SUCCESS) return r; | | |
| 2106 | // Linux limits the total bytes sent by sendmsg to INT_MAX, so this cast is safe. | | |
| 2107 | msg.len = @as(u32, @intCast(r)); | | |
| 2108 | next_unsent = i + 1; | | |
| 2109 | break; | | |
| 2110 | } | | |
| 2111 | size += @intCast(iov.len); | | |
| 2112 | } | | |
| 2113 | } | | |
| 2114 | if (next_unsent < kvlen or next_unsent == 0) { // want to make sure at least one syscall occurs (e.g. to trigger MSG.EOR) | | |
| 2115 | const batch_size = kvlen - next_unsent; | | |
| 2116 | const r = syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(&msgvec[next_unsent]), batch_size, flags); | | |
| 2117 | if (E.init(r) != .SUCCESS) return r; | | |
| 2118 | return next_unsent + r; | | |
| 2119 | } | | |
| 2120 | return kvlen; | | |
| 2121 | } | | |
| 2122 | return syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(msgvec), vlen, flags); | 2089 | return syscall4(.sendmmsg, @as(usize, @bitCast(@as(isize, fd))), @intFromPtr(msgvec), vlen, flags); |
| 2123 | } | 2090 | } |
| 2124 | | 2091 | |
| ... | @@ -8700,7 +8667,7 @@ pub const PR = enum(i32) { | ... | @@ -8700,7 +8667,7 @@ pub const PR = enum(i32) { |
| 8700 | pub const SET_MM_MAP = 14; | 8667 | pub const SET_MM_MAP = 14; |
| 8701 | pub const SET_MM_MAP_SIZE = 15; | 8668 | pub const SET_MM_MAP_SIZE = 15; |
| 8702 | | 8669 | |
| 8703 | pub const SET_PTRACER_ANY = std.math.maxInt(c_ulong); | 8670 | pub const SET_PTRACER_ANY = maxInt(c_ulong); |
| 8704 | | 8671 | |
| 8705 | pub const FP_MODE_FR = 1 << 0; | 8672 | pub const FP_MODE_FR = 1 << 0; |
| 8706 | pub const FP_MODE_FRE = 1 << 1; | 8673 | pub const FP_MODE_FRE = 1 << 1; |