blob: cb305c02d98a2103b66bf673b5aff288b3cfd4b3 [file] [log] [blame]
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