Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Truncate user and group ids for 64 bit Linux systems #7466

Conversation

klingtnet
Copy link
Contributor

@klingtnet klingtnet commented Dec 16, 2020

Calls to getuid, getgid and their eid variants fail to compile on
64bit Linux systems because the return value of the syscall is of
usize and needs to be truncated to fit the size of uid_t that is 32
bit.

Thanks to @FireFox317 for figuring this out in Zig's Discord channel!

TODO

  • squash commits
  • fix CI test
  • run regression test

Copy link
Contributor

@FireFox317 FireFox317 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fast PR @klingtnet ! I have a couple suggestions.

lib/std/os/linux.zig Outdated Show resolved Hide resolved
lib/std/os/linux.zig Outdated Show resolved Hide resolved
@klingtnet klingtnet force-pushed the truncate-linux-user-and-group-id-calls-for-64bit-systems branch 2 times, most recently from 38c5364 to b294e14 Compare December 16, 2020 21:29
Calls to `getuid`, `getgid` and their `eid` variants fail to compile on
64bit Linux systems because the return value of the syscall is of
`usize` and needs to be truncated to fit the size of `uid_t` that is 32
bit.

Thanks to @FireFox317 for figuring this out in Zig's Discord channel!
@klingtnet klingtnet force-pushed the truncate-linux-user-and-group-id-calls-for-64bit-systems branch from b294e14 to f1c40ba Compare December 16, 2020 21:30
@LemonBoy
Copy link
Contributor

What about a nice test in os/linux/test.zig so that it won't accidentally regress?
Something like:

test "" {
    expectEqual(getauxval(AT_UID), getuid());
    // same for AT_GID, AT_EUID, AT_EGID
}

lib/std/os/linux.zig Outdated Show resolved Hide resolved
@klingtnet
Copy link
Contributor Author

What about a nice test in os/linux/test.zig so that it won't accidentally regress?
Something like:

test "" {
    expectEqual(getauxval(AT_UID), getuid());
    // same for AT_GID, AT_EUID, AT_EGID
}

Sounds fine to me, will address this after work.

@klingtnet
Copy link
Contributor Author

I added a regression test as suggested, unfortunately I could not find any documentation on how to run them.

If it does not exist already then there should be some documentation for new contributors.

@LemonBoy
Copy link
Contributor

I added a regression test as suggested, unfortunately I could not find any documentation on how to run them.

If it does not exist already then there should be some documentation for new contributors.

You can simply run zig test <your .zig file>, that's much faster than running the whole test suite (that you can run with zig build --build-file ../build.zig test-std, YMMV).

@klingtnet
Copy link
Contributor Author

klingtnet commented Dec 17, 2020

I added a regression test as suggested, unfortunately I could not find any documentation on how to run them.
If it does not exist already then there should be some documentation for new contributors.

You can simply run zig test <your .zig file>, that's much faster than running the whole test suite (that you can run with zig build --build-file ../build.zig test-std, YMMV).

Thank you very much! Test's will probably fail with 0.7.1 so I need to wait until my fresh build is ready (required to install llvm and lld, luckily the latter one was mentioned in #419 ).

Side note:

The test does not compile with 0,7.1:

$ zig test lib/std/os/linux/test.zig
./lib/std/os/linux/test.zig:6:13: error: import of file outside package path: '../../std.zig'
const std = @import("../../std.zig");
            ^
./lib/std/os/linux/test.zig:13:12: note: referenced here
const fs = std.fs;
           ^
./lib/std/os/linux/test.zig:17:22: note: referenced here
    const file = try fs.cwd().createFile(path, .{ .truncate = true, .mode = 0o666 });

@klingtnet klingtnet force-pushed the truncate-linux-user-and-group-id-calls-for-64bit-systems branch from 26d7683 to e885958 Compare December 17, 2020 14:38
@LemonBoy
Copy link
Contributor

The test does not compile with 0,7.1:

Yes, some tests are not meant to be run stand-alone. You want to run lib/std/os.zig here.

This should be safe because `uid_t` will be 32-bit.
@klingtnet
Copy link
Contributor Author

So, to run the tests locally I needed to compile zig locally under Arch Linux. I will list the important steps here for documentation purposes:

$ pacman -S llvm clang lld
# follow the wiki instructions
$ cmake .. -DZIG_PREFER_CLANG_CPP_DYLIB=True
# wait ... done

The test still does not compile:

$ build/zig test lib/std/os/linux/test.zig
./lib/std/os/linux/test.zig:105:17: error: use of undeclared identifier 'getauxval'
    expectEqual(getauxval(AT_UID), getuid());
                ^

I imported getauxval from std.os.linux and then it fails with:

$ build/zig test lib/std/os/linux/test.zig | clipit
./lib/std/os/linux/test.zig:105:17: error: use of undeclared identifier 'getauxval'
    expectEqual(getauxval(AT_UID), getuid());
                ^

Unfortunately, I could not find a reference to AT_UID to import it.

@LemonBoy
Copy link
Contributor

I imported getauxval from std.os.linux and then it fails with:

You can use linux.getauxval instead of defining an extra const for something that's only used once.

I imported getauxval from std.os.linux and then it fails with:

Those are defined in std.elf... It makes no sense, I know.

@klingtnet
Copy link
Contributor Author

Seems to work fine now:

$ build/zig test lib/std/os/linux/test.zig
All 5 tests passed.
s1 alinz@kn-portable

@klingtnet
Copy link
Contributor Author

I need to fix the failing CI test:

1081/1637 os.linux.test.test "std-native-Debug-c-multi user and group ids"... expected 0, found 1001
/home/vsts/work/1/s/lib/std/testing.zig:74:32: 0x44178f in testing.expectEqual (test)
                std.debug.panic("expected {}, found {}", .{ expected, actual });
                               ^
/home/vsts/work/1/s/lib/std/os/linux/test.zig:105:16: 0x38807e in os.linux.test.test "std-native-Debug-c-multi user and group ids" (test)
    expectEqual(linux.getauxval(elf.AT_UID), linux.getuid());
               ^
/home/vsts/work/1/s/lib/std/special/test_runner.zig:61:28: 0x3c0a58 in std.special.main (test)
        } else test_fn.func();
                           ^
/home/vsts/work/1/s/lib/std/start.zig:344:37: 0x3c27a1 in start.main (test)
            const result = root.main() catch |err| {
                                    ^
error: the following test command crashed:
/home/vsts/work/1/s/zig-cache/o/590cc85149a19cdf50140d5408f6d1bb/test
The following command exited with error code 1:
/home/vsts/work/1/s/build/zig test /home/vsts/work/1/s/lib/std/std.zig -lc --test-name-prefix std-native-Debug-c-multi  --cache-dir /home/vsts/work/1/s/zig-cache --global-cache-dir /home/vsts/.cache/zig --name test -I /home/vsts/work/1/s/test --override-lib-dir /home/vsts/work/1/s/lib 
error: the following build command failed with exit code 1:
/home/vsts/work/1/s/zig-cache/o/b44c2f8e472997c666788c7413e997b6/build /home/vsts/work/1/s/build/zig /home/vsts/work/1/s /home/vsts/work/1/s/zig-cache /home/vsts/.cache/zig test -Denable-qemu -Denable-wasmtime

@FireFox317
Copy link
Contributor

The problem is in the getauxval function:

zig/lib/std/os/linux.zig

Lines 37 to 49 in 506af7e

/// Set by startup code, used by `getauxval`.
pub var elf_aux_maybe: ?[*]std.elf.Auxv = null;
/// See `std.elf` for the constants.
pub fn getauxval(index: usize) usize {
const auxv = elf_aux_maybe orelse return 0;
var i: usize = 0;
while (auxv[i].a_type != std.elf.AT_NULL) : (i += 1) {
if (auxv[i].a_type == index)
return auxv[i].a_un.a_val;
}
return 0;
}

As you can see the elf_aux_maybe is populated by the start.zig file and I'm pretty sure this startup code is not run when we do zig test. So it looks like we cannot test this (or somebody else knows a solution to this).

@LemonBoy
Copy link
Contributor

Oh this is some other std.os bullshit, slap a if (builtin.link_libc) return error.SkipZigTest; and let's call it a day, this is a test for our direct syscall wrappers after all.

@Vexu Vexu merged commit 7e63f7a into ziglang:master Dec 23, 2020
aarvay pushed a commit to aarvay/zig that referenced this pull request Jan 4, 2021
* Truncate user and group ids

Calls to `getuid`, `getgid` and their `eid` variants fail to compile on
64bit Linux systems because the return value of the syscall is of
`usize` and needs to be truncated to fit the size of `uid_t` that is 32
bit.

Thanks to @FireFox317 for figuring this out in Zig's Discord channel!

* Add a regression test for user and group ids

* Replace @truncate with @intcast

This should be safe because `uid_t` will be 32-bit.

* Add missing import for getauxval

* Add missing package names

* Revert "Add missing import for getauxval"

This reverts commit 38f93dc.

* Skip user and group test if builtin.link_libc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants