You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by ya...@apache.org on 2017/02/09 21:47:56 UTC

[1/3] mesos git commit: Revert "Revert "Use the stout ELF parser to collect rootfs files."".

Repository: mesos
Updated Branches:
  refs/heads/master c2388a511 -> 484435384


Revert "Revert "Use the stout ELF parser to collect rootfs files."".

This reverts commit 273aca1d2df1553df5fbf27c3e7479d5dc0f5dbb.

Review: https://reviews.apache.org/r/56472/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/48443538
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/48443538
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/48443538

Branch: refs/heads/master
Commit: 4844353847657e9449de433172905a8659033d0e
Parents: 0c0080e
Author: James Peach <jp...@apache.org>
Authored: Thu Feb 9 13:39:35 2017 -0800
Committer: Jiang Yan Xu <xu...@apple.com>
Committed: Thu Feb 9 13:40:51 2017 -0800

----------------------------------------------------------------------
 src/tests/containerizer/rootfs.cpp | 154 ++++++++++++++++++--------------
 src/tests/containerizer/rootfs.hpp |  14 ++-
 2 files changed, 100 insertions(+), 68 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/48443538/src/tests/containerizer/rootfs.cpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/rootfs.cpp b/src/tests/containerizer/rootfs.cpp
index f11f126..513c1b5 100644
--- a/src/tests/containerizer/rootfs.cpp
+++ b/src/tests/containerizer/rootfs.cpp
@@ -23,6 +23,15 @@
 #include <stout/os.hpp>
 #include <stout/strings.hpp>
 
+#include <stout/os/stat.hpp>
+
+#include "linux/ldd.hpp"
+
+using std::string;
+using std::vector;
+
+using process::Owned;
+
 namespace mesos {
 namespace internal {
 namespace tests {
@@ -35,50 +44,71 @@ Rootfs::~Rootfs()
 }
 
 
-Try<Nothing> Rootfs::add(const std::string& path)
+Try<Nothing> Rootfs::add(const string& path)
 {
-  if (!os::exists(path)) {
-    return Error("File or directory not found on the host");
+  Option<string> source = None();
+
+  // If we are copying a symlink, follow it and copy the
+  // target instead. While this is a little inefficient on
+  // disk space, it avoids complexity in dealing with chains
+  // of symlinks and symlinks in intermediate path components.
+  if (os::stat::islink(path)) {
+    Result<string> target = os::realpath(path);
+    if (target.isNone()) {
+      return Error("Failed to resolve '" + path + "'");
+    }
+
+    if (target.isError()) {
+      return Error("Failed to resolve '" + path + "': " + target.error());
+    }
+
+    source = target.get();
   }
 
-  if (!strings::startsWith(path, "/")) {
-    return Error("Not an absolute path");
+  Try<Nothing> copy = copyPath(source.isSome() ? source.get() : path, path);
+  if (copy.isError()) {
+    return Error("Failed to copy '" + path + "' to rootfs: " + copy.error());
   }
 
-  std::string dirname = Path(path).dirname();
-  std::string target = path::join(root, dirname);
+  return Nothing();
+}
 
-  if (!os::exists(target)) {
-    Try<Nothing> mkdir = os::mkdir(target);
+
+Try<Nothing> Rootfs::copyPath(const string& source, const string& destination)
+{
+  if (!os::exists(source)) {
+    return Error("'" + source + "' not found");
+  }
+
+  if (!strings::startsWith(source, "/")) {
+    return Error("'" + source + "' is not an absolute path");
+  }
+
+  string rootfsDestination = path::join(root, destination);
+  string rootfsDirectory = Path(rootfsDestination).dirname();
+
+  if (!os::exists(rootfsDirectory)) {
+    Try<Nothing> mkdir = os::mkdir(rootfsDirectory);
     if (mkdir.isError()) {
-      return Error("Failed to create directory in rootfs: " +
-                    mkdir.error());
+      return Error(
+          "Failed to create directory '" + rootfsDirectory +
+          "': " + mkdir.error());
     }
   }
 
-  // TODO(jieyu): Make sure 'path' is not under 'root'.
-
-  // Copy the files. We perserve all attributes so that e.g., `ping`
+  // Copy the files. We preserve all attributes so that e.g., `ping`
   // keeps its file-based capabilities.
-  if (os::stat::isdir(path)) {
-    if (os::system(strings::format(
-            "cp -r --preserve=all '%s' '%s'",
-            path, target).get()) != 0) {
-      return ErrnoError("Failed to copy '" + path + "' to rootfs");
-    }
-  } else {
-    if (os::system(strings::format(
-            "cp --preserve=all '%s' '%s'",
-            path, target).get()) != 0) {
-      return ErrnoError("Failed to copy '" + path + "' to rootfs");
-    }
+  if (os::spawn(
+          "cp",
+          {"cp", "-r", "--preserve=all", source, rootfsDestination}) != 0) {
+    return Error("Failed to copy '" + source + "' to rootfs");
   }
 
   return Nothing();
 }
 
 
-Try<process::Owned<Rootfs>> LinuxRootfs::create(const std::string& root)
+Try<process::Owned<Rootfs>> LinuxRootfs::create(const string& root)
 {
   process::Owned<Rootfs> rootfs(new LinuxRootfs(root));
 
@@ -89,64 +119,56 @@ Try<process::Owned<Rootfs>> LinuxRootfs::create(const std::string& root)
     }
   }
 
-  std::vector<std::string> files = {
+  Try<vector<ldcache::Entry>> cache = ldcache::parse();
+
+  if (cache.isError()) {
+    return Error("Failed to parse ld.so cache: " + cache.error());
+  }
+
+  const std::vector<string> programs = {
     "/bin/echo",
     "/bin/ls",
     "/bin/ping",
     "/bin/sh",
     "/bin/sleep",
-    "/usr/bin/sh",
-    "/lib/x86_64-linux-gnu",
-    "/lib64/ld-linux-x86-64.so.2",
-    "/lib64/libc.so.6",
-    "/lib64/libdl.so.2",
-    "/lib64/libidn.so.11",
-    "/lib64/libtinfo.so.5",
-    "/lib64/libselinux.so.1",
-    "/lib64/libpcre.so.1",
-    "/lib64/liblzma.so.5",
-    "/lib64/libpthread.so.0",
-    "/lib64/libcap.so.2",
-    "/lib64/libacl.so.1",
-    "/lib64/libattr.so.1",
-    "/lib64/librt.so.1",
+  };
+
+  hashset<string> files = {
     "/etc/passwd"
   };
 
-  foreach (const std::string& file, files) {
-    // Some linux distros are moving all binaries and libraries to
-    // /usr, in which case /bin, /lib, and /lib64 will be symlinks
-    // to their equivalent directories in /usr.
-    Result<std::string> realpath = os::realpath(file);
-    if (realpath.isSome()) {
-      Try<Nothing> result = rootfs->add(realpath.get());
-      if (result.isError()) {
-        return Error("Failed to add '" + realpath.get() +
-                     "' to rootfs: " + result.error());
-      }
-
-      if (file != realpath.get()) {
-        result = rootfs->add(file);
-        if (result.isError()) {
-          return Error("Failed to add '" + file + "' to rootfs: " +
-                       result.error());
-        }
-      }
+  foreach (const string& program, programs) {
+    Try<hashset<string>> dependencies = ldd(program, cache.get());
+    if (dependencies.isError()) {
+      return Error(
+          "Failed to find dependencies for '" + program + "': " +
+          dependencies.error());
+    }
+
+    files |= dependencies.get();
+    files.insert(program);
+  }
+
+  foreach (const string& file, files) {
+    Try<Nothing> result = rootfs->add(file);
+    if (result.isError()) {
+      return Error(result.error());
     }
   }
 
-  std::vector<std::string> directories = {
+  const std::vector<string> directories = {
     "/proc",
     "/sys",
     "/dev",
     "/tmp"
   };
 
-  foreach (const std::string& directory, directories) {
+  foreach (const string& directory, directories) {
     Try<Nothing> mkdir = os::mkdir(path::join(root, directory));
     if (mkdir.isError()) {
-      return Error("Failed to create '" + directory +
-                   "' in rootfs: " + mkdir.error());
+      return Error(
+          "Failed to create '" + directory + "' in rootfs: " +
+          mkdir.error());
     }
   }
 

http://git-wip-us.apache.org/repos/asf/mesos/blob/48443538/src/tests/containerizer/rootfs.hpp
----------------------------------------------------------------------
diff --git a/src/tests/containerizer/rootfs.hpp b/src/tests/containerizer/rootfs.hpp
index 9648638..8835a92 100644
--- a/src/tests/containerizer/rootfs.hpp
+++ b/src/tests/containerizer/rootfs.hpp
@@ -17,6 +17,10 @@
 #ifndef __TEST_ROOTFS_HPP__
 #define __TEST_ROOTFS_HPP__
 
+#ifndef __linux__
+#error "tests/containerizer/rootfs.hpp is only available on Linux systems"
+#endif
+
 #include <string>
 
 #include <process/owned.hpp>
@@ -32,14 +36,20 @@ class Rootfs {
 public:
   virtual ~Rootfs();
 
-  // Add a host directory or file to the root filesystem. Note that
-  // the host directory or file needs to be an absolute path.
+  // Add a host path to the root filesystem. If the given
+  // host path is a symlink, both the link target and the
+  // link itself will be copied into the root.
   Try<Nothing> add(const std::string& path);
 
   const std::string root;
 
 protected:
   Rootfs(const std::string& _root) : root(_root) {}
+
+private:
+  Try<Nothing> copyPath(
+      const std::string& source,
+      const std::string& destination);
 };
 
 


[2/3] mesos git commit: Capture ELF interpreters in the ldd utility.

Posted by ya...@apache.org.
Capture ELF interpreters in the ldd utility.

The ELF interpreter (ie. program loader) path is not necessarily
specified in the ELF dependencies section but we still need
to capture is as a dependency of an executable program.

Review: https://reviews.apache.org/r/56466/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/0c0080e7
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/0c0080e7
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/0c0080e7

Branch: refs/heads/master
Commit: 0c0080e7ec2c2bbd4f935824217119ead0b8c7c6
Parents: 96f4991
Author: James Peach <jp...@apache.org>
Authored: Thu Feb 9 13:39:16 2017 -0800
Committer: Jiang Yan Xu <xu...@apple.com>
Committed: Thu Feb 9 13:40:51 2017 -0800

----------------------------------------------------------------------
 src/linux/ldd.cpp | 11 +++++++++++
 1 file changed, 11 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/0c0080e7/src/linux/ldd.cpp
----------------------------------------------------------------------
diff --git a/src/linux/ldd.cpp b/src/linux/ldd.cpp
index dd5c9c5..fead938 100644
--- a/src/linux/ldd.cpp
+++ b/src/linux/ldd.cpp
@@ -82,6 +82,17 @@ Try<hashset<string>> ldd(
         return Error("'" + dependency + "' is not in the ld.so cache");
       }
 
+      // If this ELF object has an interpreter (e.g. ld-linux-x86-64.so.2),
+      // inspect that too. We need both to be able to run an executable program.
+      // NOTE: The same object may be specified as a dependency too but on some
+      // systems (e.g. Ubuntu), the exact path of the two can differ even though
+      // they link to the the same file (see MESOS-7060). We however need the
+      // exact path specified in the interpreter section to run the executable.
+      Result<string> interpreter = elf->get_interpreter();
+      if (interpreter.isSome()) {
+        candidates.push_back(interpreter.get());
+      }
+
       candidates.push_back(entry->path);
     }
 


[3/3] mesos git commit: Add support for the ELF .interp section.

Posted by ya...@apache.org.
Add support for the ELF .interp section.

Review: https://reviews.apache.org/r/56465/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/96f49919
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/96f49919
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/96f49919

Branch: refs/heads/master
Commit: 96f49919325f383e4f7f557fe61a267ee808aefb
Parents: c2388a5
Author: James Peach <jp...@apache.org>
Authored: Thu Feb 9 13:39:10 2017 -0800
Committer: Jiang Yan Xu <xu...@apple.com>
Committed: Thu Feb 9 13:40:51 2017 -0800

----------------------------------------------------------------------
 3rdparty/stout/include/stout/elf.hpp | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/96f49919/3rdparty/stout/include/stout/elf.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/stout/include/stout/elf.hpp b/3rdparty/stout/include/stout/elf.hpp
index 2bf91a0..da2ce0c 100644
--- a/3rdparty/stout/include/stout/elf.hpp
+++ b/3rdparty/stout/include/stout/elf.hpp
@@ -46,6 +46,7 @@ enum class SectionType
 {
   DYNAMIC = SHT_DYNAMIC,
   NOTE = SHT_NOTE,
+  PROGBITS = SHT_PROGBITS,
 };
 
 enum class DynamicTag
@@ -150,7 +151,7 @@ public:
     }
 
     if (SectionType(section->get_type()) != SectionType::NOTE) {
-      return Error("Section '.note.ABI-tag' is not a NOTE");
+      return Error("Section '.note.ABI-tag' is not a NOTE section");
     }
 
     auto accessor = ELFIO::note_section_accessor(elf, section);
@@ -197,6 +198,26 @@ public:
     return Version(version[1], version[2], version[3]);
   }
 
+  // Return the contents of the .interp section, if such a
+  // section exits. For Linux ELF executables, the .interp
+  // section contains the path to the program loader.
+  //
+  // https://refspecs.linuxfoundation.org/LSB_1.2.0/gLSB/specialsections.html
+  Result<std::string> get_interpreter() const
+  {
+    ELFIO::section* section = elf.sections[".interp"];
+
+    if (section == nullptr) {
+      return None();
+    }
+
+    if (SectionType(section->get_type()) != SectionType::PROGBITS) {
+      return Error("Section '.interp' is not a PROGBITS section");
+    }
+
+    return std::string(section->get_data(), section->get_size());
+  }
+
 private:
   explicit File() {}