-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
os/user: LookupId() returns unexpected results if $USER doesn't reflect current UID #27524
Comments
I tested it as follow but did't have this problem:
Did i miss something? |
CC: @bradfitz @kevinburke |
Here's my repro on a fresh install of CentOS 7.5:
ETA: I noticed here that the initial report isn't quite correct. The repro is just to |
To be clear - this is running with cgo disabled, right? With cgo enabled you should get the cgo_lookup_unix behavior, which uses the same process to retrieve users whether they're the current user or not. |
Change https://golang.org/cl/134218 mentions this issue: |
To muddy the water, POSIX says it's LOGNAME that holds the user's login name and does not define USER. http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08 |
Oh man. I'm not sure I've ever seen that defined in the wild. |
Oh, it's definitely used. environ(7) here on Arch Linux says it's System-V compared to BSD for USER. |
Interesting! What should the priority order be then ? The value in /etc/passwd seems like it's still the best, if it's present. |
Hi Kevin, yes, I agree, a match for the numeric UID in /etc/passwd is best, but then I'd suggest POSIX's LOGNAME should trump USER; that seems to be the consensus from a quick survey, the initial results above. |
What version of Go are you using (
go version
)?go1.10.3
Does this issue reproduce with the latest release?
Have not tried it, but the code appears to be the same in 1.11.
What operating system and processor architecture are you using (
go env
)?linux/amd64
What did you do?
On some Linux distributions (e.g., CentOS 7),
su
does not change the $USER variable to root, but preserves the $USER who invoked it. (In this case,su -
will change $USER.)If a Go program is run from an environment like this, wherein $USER does not match the current UID, a call to
user.LookupId()
with the current UID will return a bad result. TheUser
struct will contain the requested UID, but the username from $USER. (E.g., if Isu
and then invoke my program to lookup UID 0, I'll get back something like&{0 0 casey /root}
.)This is because of the
Current()
cache inos/user/lookup.go
and the implementation ofcurrent()
inos/user/lookup_stubs.go
, which "looks up" the current user by mixing the current UID withos.Getenv("USER")
to build theUser
struct instead of opening/etc/passwd
. Of course, this only affects the current UID, and all other users are correctly scraped from/etc/passwd
.I think I understand the reasoning behind the optimization, but the result seems wrong, particularly when querying a whole range of users on the system. I did not expect
os/user
to depend on the "correctness" of my environment variables, but just the contents of/etc/passwd
.What did you expect to see?
user.LookupId("0")
should return&User{0, 0, root, /root}
What did you see instead?
If
$USER
iscasey
butcurrentUID()
is 0,user.LookupId("0")
returns&User{0, 0, "casey", "", "/root"}
The text was updated successfully, but these errors were encountered: