From 7270828db756eb9cee80859b3bd3c6954532af20 Mon Sep 17 00:00:00 2001 From: Ben Hoyt Date: Mon, 10 Jun 2024 20:25:18 +1200 Subject: [PATCH 1/2] fix: work around issue with user.Lookup not returning UnknownUserError Per https://github.com/golang/go/issues/67912, under some circumstances (on my machine) user.Lookup isn't returning UnknownUserError when it should. --- internals/osutil/user.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/internals/osutil/user.go b/internals/osutil/user.go index 464c5b244..6c6c8e975 100644 --- a/internals/osutil/user.go +++ b/internals/osutil/user.go @@ -19,6 +19,7 @@ import ( "os" "os/user" "strconv" + "strings" "github.com/canonical/pebble/internals/osutil/sys" ) @@ -56,6 +57,12 @@ func RealUser() (*user.User, error) { if _, ok := err.(user.UnknownUserError); ok { return cur, nil } + // Workaround for https://github.com/golang/go/issues/67912, until our + // minimum Go version has a fix for that. In short, user.Lookup sometimes + // doesn't return UnknownUserError when it should. + if err != nil && strings.Contains(err.Error(), "no such file or directory") { + return cur, nil + } if err != nil { return nil, err } @@ -90,6 +97,10 @@ func NormalizeUidGid(uid, gid *int, username, group string) (*int, *int, error) if username != "" { u, err := userLookup(username) if err != nil { + if strings.Contains(err.Error(), "no such file or directory") { + // Better error message to work around https://github.com/golang/go/issues/67912 + return nil, nil, user.UnknownUserError(username) + } return nil, nil, err } n, _ := strconv.Atoi(u.Uid) @@ -107,6 +118,10 @@ func NormalizeUidGid(uid, gid *int, username, group string) (*int, *int, error) if group != "" { g, err := userLookupGroup(group) if err != nil { + if strings.Contains(err.Error(), "no such file or directory") { + // Better error message to work around https://github.com/golang/go/issues/67912 + return nil, nil, user.UnknownGroupError(group) + } return nil, nil, err } n, _ := strconv.Atoi(g.Gid) From d0df08fc22315f04bc11b53b6be7ef3d63b6889c Mon Sep 17 00:00:00 2001 From: Ben Hoyt Date: Tue, 11 Jun 2024 12:57:19 +1200 Subject: [PATCH 2/2] Use syscall.ENOENT.Error() instead of hard-coded error messages --- internals/osutil/user.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internals/osutil/user.go b/internals/osutil/user.go index 6c6c8e975..c2b0879d4 100644 --- a/internals/osutil/user.go +++ b/internals/osutil/user.go @@ -20,6 +20,7 @@ import ( "os/user" "strconv" "strings" + "syscall" "github.com/canonical/pebble/internals/osutil/sys" ) @@ -28,6 +29,8 @@ var ( userCurrent = user.Current userLookup = user.Lookup userLookupGroup = user.LookupGroup + + enoentMessage = syscall.ENOENT.Error() ) // RealUser finds the user behind a sudo invocation when root, if applicable @@ -60,7 +63,7 @@ func RealUser() (*user.User, error) { // Workaround for https://github.com/golang/go/issues/67912, until our // minimum Go version has a fix for that. In short, user.Lookup sometimes // doesn't return UnknownUserError when it should. - if err != nil && strings.Contains(err.Error(), "no such file or directory") { + if err != nil && strings.Contains(err.Error(), enoentMessage) { return cur, nil } if err != nil { @@ -97,7 +100,7 @@ func NormalizeUidGid(uid, gid *int, username, group string) (*int, *int, error) if username != "" { u, err := userLookup(username) if err != nil { - if strings.Contains(err.Error(), "no such file or directory") { + if strings.Contains(err.Error(), enoentMessage) { // Better error message to work around https://github.com/golang/go/issues/67912 return nil, nil, user.UnknownUserError(username) } @@ -118,7 +121,7 @@ func NormalizeUidGid(uid, gid *int, username, group string) (*int, *int, error) if group != "" { g, err := userLookupGroup(group) if err != nil { - if strings.Contains(err.Error(), "no such file or directory") { + if strings.Contains(err.Error(), enoentMessage) { // Better error message to work around https://github.com/golang/go/issues/67912 return nil, nil, user.UnknownGroupError(group) }