Skip to content

Commit

Permalink
client: defer nobody user lookup so Windows doesn't panic
Browse files Browse the repository at this point in the history
In #14742 we introduced a cached lookup of the `nobody` user, which is only ever
called on Unixish machines. But the initial caching was being done in an `init`
block, which meant it was being run on Windows as well. This prevents the Nomad
agent from starting on Windows.

An alternative fix here would be to have a separate `init` block for Windows and
Unix, but this potentially masks incorrect behavior if we accidentally added a
call to the `Nobody()` method on Windows later. This way we're forced to handle
the error in the caller.
  • Loading branch information
tgross committed Oct 4, 2022
1 parent d063845 commit 46c2a1f
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 13 deletions.
9 changes: 6 additions & 3 deletions client/allocdir/fs_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,17 @@ func dropDirPermissions(path string, desired os.FileMode) error {
return nil
}

nobody := users.Nobody()
nobody, err := users.Nobody()
if err != nil {
return err
}

uid, err := getUid(&nobody)
uid, err := getUid(nobody)
if err != nil {
return err
}

gid, err := getGid(&nobody)
gid, err := getGid(nobody)
if err != nil {
return err
}
Expand Down
20 changes: 10 additions & 10 deletions helper/users/lookup.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package users

import (
"fmt"
"os/user"
"sync"
)
Expand All @@ -12,22 +11,23 @@ var lock *sync.Mutex

// nobody is a cached copy of the nobody user, which is going to be looked-up
// frequently and is unlikely to be modified on the underlying system.
var nobody user.User
var nobody *user.User

// Nobody returns User data for the "nobody" user on the system, bypassing the
// locking / file read / NSS lookup.
func Nobody() user.User {
// original is immutable via copy by value
return nobody
func Nobody() (*user.User, error) {
lock.Lock()
defer lock.Unlock()
if nobody != nil {
return nobody, nil
}
u, err := Lookup("nobody")
nobody = u
return u, err
}

func init() {
lock = new(sync.Mutex)
u, err := Lookup("nobody")
if err != nil {
panic(fmt.Sprintf("unable to lookup the nobody user: %v", err))
}
nobody = *u
}

// Lookup username while holding a global process lock.
Expand Down

0 comments on commit 46c2a1f

Please sign in to comment.