| From e3ef0d12c3ee16085fdd89e748203394129a14fc Mon Sep 17 00:00:00 2001 |
| From: Akihiro Suda <suda.akihiro@lab.ntt.co.jp> |
| Date: Fri, 16 Dec 2016 09:50:14 +0000 |
| Subject: [PATCH] gcplogs: forcibly set HOME on static UNIX binary |
| |
| Fix #29344 |
| |
| If HOME is not set, the gcplogs logging driver will call os/user.Current() via oauth2/google. |
| However, in static binary, os/user.Current() leads to segfault due to a glibc issue that won't be fixed |
| in a short term. (golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341) |
| So we forcibly set HOME so as to avoid call to os/user/Current(). |
| |
| Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp> |
| Signed-off-by: Andrey Ulanov <andreyu@google.com> |
| --- |
| daemon/logger/gcplogs/gcplogging.go | 9 +++++++++ |
| daemon/logger/gcplogs/gcplogging_linux.go | 31 ++++++++++++++++++++++++++++++ |
| daemon/logger/gcplogs/gcplogging_others.go | 7 +++++++ |
| pkg/homedir/homedir_linux.go | 23 ++++++++++++++++++++++ |
| pkg/homedir/homedir_others.go | 13 +++++++++++++ |
| 5 files changed, 83 insertions(+) |
| create mode 100644 daemon/logger/gcplogs/gcplogging_linux.go |
| create mode 100644 daemon/logger/gcplogs/gcplogging_others.go |
| create mode 100644 pkg/homedir/homedir_linux.go |
| create mode 100644 pkg/homedir/homedir_others.go |
| |
| diff --git a/daemon/logger/gcplogs/gcplogging.go b/daemon/logger/gcplogs/gcplogging.go |
| index 781642bb5..9414f5804 100644 |
| --- a/daemon/logger/gcplogs/gcplogging.go |
| +++ b/daemon/logger/gcplogs/gcplogging.go |
| @@ -111,6 +111,15 @@ func New(ctx logger.Context) (logger.Logger, error) { |
| return nil, fmt.Errorf("No project was specified and couldn't read project from the meatadata server. Please specify a project") |
| } |
| |
| + // Issue #29344: gcplogs segfaults (static binary) |
| + // If HOME is not set, logging.NewClient() will call os/user.Current() via oauth2/google. |
| + // However, in static binary, os/user.Current() leads to segfault due to a glibc issue that won't be fixed |
| + // in a short term. (golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341) |
| + // So we forcibly set HOME so as to avoid call to os/user/Current() |
| + if err := ensureHomeIfIAmStatic(); err != nil { |
| + return nil, err |
| + } |
| + |
| c, err := logging.NewClient(context.Background(), project, "gcplogs-docker-driver") |
| if err != nil { |
| return nil, err |
| diff --git a/daemon/logger/gcplogs/gcplogging_linux.go b/daemon/logger/gcplogs/gcplogging_linux.go |
| new file mode 100644 |
| index 000000000..9af8b3c17 |
| --- /dev/null |
| +++ b/daemon/logger/gcplogs/gcplogging_linux.go |
| @@ -0,0 +1,31 @@ |
| +// +build linux |
| + |
| +package gcplogs |
| + |
| +import ( |
| + "os" |
| + |
| + "github.com/Sirupsen/logrus" |
| + "github.com/docker/docker/dockerversion" |
| + "github.com/docker/docker/pkg/homedir" |
| +) |
| + |
| +// ensureHomeIfIAmStatic ensure $HOME to be set if dockerversion.IAmStatic is "true". |
| +// See issue #29344: gcplogs segfaults (static binary) |
| +// If HOME is not set, logging.NewClient() will call os/user.Current() via oauth2/google. |
| +// However, in static binary, os/user.Current() leads to segfault due to a glibc issue that won't be fixed |
| +// in a short term. (golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341) |
| +// So we forcibly set HOME so as to avoid call to os/user/Current() |
| +func ensureHomeIfIAmStatic() error { |
| + // Note: dockerversion.IAmStatic and homedir.GetStatic() is only available for linux. |
| + // So we need to use them in this gcplogging_linux.go rather than in gcplogging.go |
| + if dockerversion.IAmStatic == "true" && os.Getenv("HOME") == "" { |
| + home, err := homedir.GetStatic() |
| + if err != nil { |
| + return err |
| + } |
| + logrus.Warnf("gcplogs requires HOME to be set for static daemon binary. Forcibly setting HOME to %s.", home) |
| + os.Setenv("HOME", home) |
| + } |
| + return nil |
| +} |
| diff --git a/daemon/logger/gcplogs/gcplogging_others.go b/daemon/logger/gcplogs/gcplogging_others.go |
| new file mode 100644 |
| index 000000000..45e3b8d6d |
| --- /dev/null |
| +++ b/daemon/logger/gcplogs/gcplogging_others.go |
| @@ -0,0 +1,7 @@ |
| +// +build !linux |
| + |
| +package gcplogs |
| + |
| +func ensureHomeIfIAmStatic() error { |
| + return nil |
| +} |
| diff --git a/pkg/homedir/homedir_linux.go b/pkg/homedir/homedir_linux.go |
| new file mode 100644 |
| index 000000000..6bb052c12 |
| --- /dev/null |
| +++ b/pkg/homedir/homedir_linux.go |
| @@ -0,0 +1,23 @@ |
| +// +build linux |
| + |
| +package homedir |
| + |
| +import ( |
| + "os" |
| + |
| + "github.com/opencontainers/runc/libcontainer/user" |
| +) |
| + |
| +// GetStatic returns the home directory for the current user without calling |
| +// os/user.Current(). This is useful for static-linked binary on glibc-based |
| +// system, because a call to os/user.Current() in a static binary leads to |
| +// segfault due to a glibc issue that won't be fixed in a short term. |
| +// (#29344, golang/go#13470, https://sourceware.org/bugzilla/show_bug.cgi?id=19341) |
| +func GetStatic() (string, error) { |
| + uid := os.Getuid() |
| + usr, err := user.LookupUid(uid) |
| + if err != nil { |
| + return "", err |
| + } |
| + return usr.Home, nil |
| +} |
| diff --git a/pkg/homedir/homedir_others.go b/pkg/homedir/homedir_others.go |
| new file mode 100644 |
| index 000000000..6b96b856f |
| --- /dev/null |
| +++ b/pkg/homedir/homedir_others.go |
| @@ -0,0 +1,13 @@ |
| +// +build !linux |
| + |
| +package homedir |
| + |
| +import ( |
| + "errors" |
| +) |
| + |
| +// GetStatic is not needed for non-linux systems. |
| +// (Precisely, it is needed only for glibc-based linux systems.) |
| +func GetStatic() (string, error) { |
| + return "", errors.New("homedir.GetStatic() is not supported on this system") |
| +} |
| -- |
| 2.12.2.715.g7642488e1d-goog |
| |