aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main
diff options
context:
space:
mode:
authorGravatar Laszlo Csomor <laszlocsomor@google.com>2016-11-17 10:18:34 +0000
committerGravatar Kristina Chodorow <kchodorow@google.com>2016-11-17 18:18:28 +0000
commit8a48f616bc1e6df70a30c416268f2c1323ffa9b0 (patch)
tree92766d72a73136159772488a87c0214b79c17aaf /src/main
parentcc3d79cca775cad9e9193d38bedf4df51a5c8a50 (diff)
Bazel client: no more `stat` usage
-- MOS_MIGRATED_REVID=139436876
Diffstat (limited to 'src/main')
-rw-r--r--src/main/cpp/blaze.cc83
-rw-r--r--src/main/cpp/blaze_util_platform.h5
-rw-r--r--src/main/cpp/blaze_util_posix.cc43
-rw-r--r--src/main/cpp/blaze_util_windows.cc50
-rw-r--r--src/main/cpp/util/file_platform.h9
-rw-r--r--src/main/cpp/util/file_posix.cc14
-rw-r--r--src/main/cpp/util/file_windows.cc10
7 files changed, 153 insertions, 61 deletions
diff --git a/src/main/cpp/blaze.cc b/src/main/cpp/blaze.cc
index d95ba05b06..39d1165c5e 100644
--- a/src/main/cpp/blaze.cc
+++ b/src/main/cpp/blaze.cc
@@ -40,8 +40,6 @@
#include <sys/resource.h>
#include <sys/select.h>
#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/statvfs.h>
#include <sys/time.h>
#include <sys/un.h>
#include <time.h>
@@ -945,8 +943,7 @@ static void ActuallyExtractData(const string &argv0,
// Populates globals->extracted_binaries with their extracted locations.
static void ExtractData(const string &self_path) {
// If the install dir doesn't exist, create it, if it does, we know it's good.
- struct stat buf;
- if (stat(globals->options->install_base.c_str(), &buf) == -1) {
+ if (!blaze_util::PathExists(globals->options->install_base)) {
uint64_t st = GetMillisecondsMonotonic();
// Work in a temp dir to avoid races.
string tmp_install = globals->options->install_base + ".tmp." +
@@ -967,7 +964,7 @@ static void ExtractData(const string &self_path) {
tmp_install.c_str());
}
} else {
- if (!S_ISDIR(buf.st_mode)) {
+ if (!blaze_util::IsDirectory(globals->options->install_base)) {
die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
"Error: Install base directory '%s' could not be created. "
"It exists but is not a directory.",
@@ -981,19 +978,28 @@ static void ExtractData(const string &self_path) {
for (const auto& it : globals->extracted_binaries) {
string path = blaze_util::JoinPath(real_install_dir, it);
// Check that the file exists and is readable.
- if (stat(path.c_str(), &buf) == -1) {
+ if (!blaze_util::CanAccess(path, true, false, false)) {
die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
"Error: corrupt installation: file '%s' missing."
" Please remove '%s' and try again.",
path.c_str(), globals->options->install_base.c_str());
}
- // Check that the timestamp is in the future. A past timestamp would indicate
- // that the file has been tampered with. See ActuallyExtractData().
- if (!S_ISDIR(buf.st_mode) && buf.st_mtime <= time_now) {
- die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
- "Error: corrupt installation: file '%s' "
- "modified. Please remove '%s' and try again.",
- path.c_str(), globals->options->install_base.c_str());
+ // Check that the timestamp is in the future. A past timestamp would
+ // indicate that the file has been tampered with.
+ // See ActuallyExtractData().
+ if (!blaze_util::IsDirectory(path)) {
+ time_t mtime = blaze_util::GetMtimeMillisec(path);
+ if (mtime == -1) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "Error: could not retrieve mtime of file '%s'. "
+ "Please remove '%s' and try again.",
+ path.c_str(), globals->options->install_base.c_str());
+ } else if (mtime <= time_now) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "Error: corrupt installation: file '%s' "
+ "modified. Please remove '%s' and try again.",
+ path.c_str(), globals->options->install_base.c_str());
+ }
}
}
}
@@ -1292,16 +1298,15 @@ static void ComputeBaseDirectories(const string &self_path) {
globals->options->output_user_root, globals->workspace);
}
- struct stat buf;
const char *output_base = globals->options->output_base.c_str();
- if (stat(output_base, &buf) == -1) {
+ if (!blaze_util::PathExists(globals->options->output_base)) {
if (MakeDirectories(globals->options->output_base, 0777) == -1) {
pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
"Output base directory '%s' could not be created",
output_base);
}
} else {
- if (!S_ISDIR(buf.st_mode)) {
+ if (!blaze_util::IsDirectory(globals->options->output_base)) {
die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
"Error: Output base directory '%s' could not be created. "
"It exists but is not a directory.",
@@ -1393,50 +1398,6 @@ static void CheckBinaryPath(const string& argv0) {
}
}
-// Create the user's directory where we keep state, installations etc.
-// Typically, this happens inside a temp directory, so we have to be
-// careful about symlink attacks.
-static void CreateSecureOutputRoot() {
- const char* root = globals->options->output_user_root.c_str();
- struct stat fileinfo = {};
-
- if (MakeDirectories(root, 0755) == -1) {
- pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "mkdir('%s')", root);
- }
-
- // The path already exists.
- // Check ownership and mode, and verify that it is a directory.
-
- if (lstat(root, &fileinfo) < 0) {
- pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "lstat('%s')", root);
- }
-
- if (fileinfo.st_uid != geteuid()) {
- die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "'%s' is not owned by me",
- root);
- }
-
- if ((fileinfo.st_mode & 022) != 0) {
- int new_mode = fileinfo.st_mode & (~022);
- if (chmod(root, new_mode) < 0) {
- die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
- "'%s' has mode %o, chmod to %o failed", root,
- fileinfo.st_mode & 07777, new_mode);
- }
- }
-
- if (stat(root, &fileinfo) < 0) {
- pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "stat('%s')", root);
- }
-
- if (!S_ISDIR(fileinfo.st_mode)) {
- die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "'%s' is not a directory",
- root);
- }
-
- ExcludePathFromBackup(root);
-}
-
// TODO(bazel-team): Execute the server as a child process and write its exit
// code to a file. In case the server becomes unresonsive or terminates
// unexpectedly (in a way that isn't already handled), we can observe the file,
@@ -1453,7 +1414,7 @@ int Main(int argc, const char *argv[], OptionProcessor *option_processor) {
debug_log("Debug logging active");
CheckEnvironment();
- CreateSecureOutputRoot();
+ blaze::CreateSecureOutputRoot(globals->options->output_user_root);
const string self_path = GetSelfPath();
ComputeBaseDirectories(self_path);
diff --git a/src/main/cpp/blaze_util_platform.h b/src/main/cpp/blaze_util_platform.h
index 40b000bcc9..6a818e5e0c 100644
--- a/src/main/cpp/blaze_util_platform.h
+++ b/src/main/cpp/blaze_util_platform.h
@@ -141,6 +141,11 @@ void ExcludePathFromBackup(const std::string& path);
std::string GetHashedBaseDir(const std::string& root,
const std::string& hashable);
+// Create a safe installation directory where we keep state, installations etc.
+// This method ensures that the directory is created, is owned by the current
+// user, and not accessible to anyone else.
+void CreateSecureOutputRoot(const std::string& path);
+
} // namespace blaze
#endif // BAZEL_SRC_MAIN_CPP_BLAZE_UTIL_PLATFORM_H_
diff --git a/src/main/cpp/blaze_util_posix.cc b/src/main/cpp/blaze_util_posix.cc
index b0cb90d3d8..4c9ce44159 100644
--- a/src/main/cpp/blaze_util_posix.cc
+++ b/src/main/cpp/blaze_util_posix.cc
@@ -17,6 +17,7 @@
#include <limits.h> // PATH_MAX
#include <signal.h>
#include <stdio.h>
+#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
@@ -31,6 +32,7 @@
namespace blaze {
+using blaze_util::die;
using blaze_util::pdie;
using std::string;
@@ -226,4 +228,45 @@ string GetHashedBaseDir(const string& root, const string& hashable) {
return root + "/" + digest.String();
}
+void CreateSecureOutputRoot(const string& path) {
+ const char* root = path.c_str();
+ struct stat fileinfo = {};
+
+ if (MakeDirectories(root, 0755) == -1) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "mkdir('%s')", root);
+ }
+
+ // The path already exists.
+ // Check ownership and mode, and verify that it is a directory.
+
+ if (lstat(root, &fileinfo) < 0) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "lstat('%s')", root);
+ }
+
+ if (fileinfo.st_uid != geteuid()) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "'%s' is not owned by me",
+ root);
+ }
+
+ if ((fileinfo.st_mode & 022) != 0) {
+ int new_mode = fileinfo.st_mode & (~022);
+ if (chmod(root, new_mode) < 0) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "'%s' has mode %o, chmod to %o failed", root,
+ fileinfo.st_mode & 07777, new_mode);
+ }
+ }
+
+ if (stat(root, &fileinfo) < 0) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "stat('%s')", root);
+ }
+
+ if (!S_ISDIR(fileinfo.st_mode)) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "'%s' is not a directory",
+ root);
+ }
+
+ ExcludePathFromBackup(root);
+}
+
} // namespace blaze.
diff --git a/src/main/cpp/blaze_util_windows.cc b/src/main/cpp/blaze_util_windows.cc
index 87fe5facbe..737c02a30c 100644
--- a/src/main/cpp/blaze_util_windows.cc
+++ b/src/main/cpp/blaze_util_windows.cc
@@ -19,6 +19,7 @@
#ifndef COMPILER_MSVC
#include <sys/cygwin.h>
#include <sys/socket.h>
+#include <sys/stat.h>
#include <sys/statfs.h>
#include <unistd.h>
#endif // COMPILER_MSVC
@@ -851,6 +852,55 @@ string GetHashedBaseDir(const string& root, const string& hashable) {
return root + "/" + string(coded_name);
}
+void CreateSecureOutputRoot(const string& path) {
+ // TODO(bazel-team) 2016-11-26: implement this function without using the
+ // POSIX API, then get rid of the POSIX version, which is a copy of the
+ // blaze_util_posix version of the same method.
+
+#ifdef COMPILER_MSVC
+ pdie(255, "blaze::CreateSecureOutputRoot is not implemented on Windows");
+#else // not COMPILER_MSVC
+ const char* root = path.c_str();
+ struct stat fileinfo = {};
+
+ if (MakeDirectories(root, 0755) == -1) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "mkdir('%s')", root);
+ }
+
+ // The path already exists.
+ // Check ownership and mode, and verify that it is a directory.
+
+ if (lstat(root, &fileinfo) < 0) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "lstat('%s')", root);
+ }
+
+ if (fileinfo.st_uid != geteuid()) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "'%s' is not owned by me",
+ root);
+ }
+
+ if ((fileinfo.st_mode & 022) != 0) {
+ int new_mode = fileinfo.st_mode & (~022);
+ if (chmod(root, new_mode) < 0) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR,
+ "'%s' has mode %o, chmod to %o failed", root,
+ fileinfo.st_mode & 07777, new_mode);
+ }
+ }
+
+ if (stat(root, &fileinfo) < 0) {
+ pdie(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "stat('%s')", root);
+ }
+
+ if (!S_ISDIR(fileinfo.st_mode)) {
+ die(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR, "'%s' is not a directory",
+ root);
+ }
+
+ ExcludePathFromBackup(root);
+#endif // COMPILER_MSVC
+}
+
LARGE_INTEGER WindowsClock::GetFrequency() {
LARGE_INTEGER result;
if (!QueryPerformanceFrequency(&result)) {
diff --git a/src/main/cpp/util/file_platform.h b/src/main/cpp/util/file_platform.h
index c43be7932a..fd725518e0 100644
--- a/src/main/cpp/util/file_platform.h
+++ b/src/main/cpp/util/file_platform.h
@@ -15,6 +15,8 @@
#ifndef BAZEL_SRC_MAIN_CPP_UTIL_FILE_PLATFORM_H_
#define BAZEL_SRC_MAIN_CPP_UTIL_FILE_PLATFORM_H_
+#include <stdint.h>
+
#include <string>
namespace blaze_util {
@@ -34,6 +36,13 @@ bool PathExists(const std::string& path);
// openable.
bool CanAccess(const std::string& path, bool read, bool write, bool exec);
+// Returns true if `path` refers to a directory or a symlink/junction to one.
+bool IsDirectory(const std::string& path);
+
+// Returns the last modification time of `path` in milliseconds since the Epoch.
+// Returns -1 upon failure.
+time_t GetMtimeMillisec(const std::string& path);
+
// Returns the current working directory.
std::string GetCwd();
diff --git a/src/main/cpp/util/file_posix.cc b/src/main/cpp/util/file_posix.cc
index 32f86da7a4..7691ee976a 100644
--- a/src/main/cpp/util/file_posix.cc
+++ b/src/main/cpp/util/file_posix.cc
@@ -73,6 +73,20 @@ bool CanAccess(const string& path, bool read, bool write, bool exec) {
return access(path.c_str(), mode) == 0;
}
+bool IsDirectory(const string& path) {
+ struct stat buf;
+ return stat(path.c_str(), &buf) == 0 && S_ISDIR(buf.st_mode);
+}
+
+time_t GetMtimeMillisec(const string& path) {
+ struct stat buf;
+ if (stat(path.c_str(), &buf)) {
+ return -1;
+ } else {
+ return buf.st_mtime;
+ }
+}
+
string GetCwd() {
char cwdbuf[PATH_MAX];
if (getcwd(cwdbuf, sizeof cwdbuf) == NULL) {
diff --git a/src/main/cpp/util/file_windows.cc b/src/main/cpp/util/file_windows.cc
index c9df3af3c9..eb0efd271a 100644
--- a/src/main/cpp/util/file_windows.cc
+++ b/src/main/cpp/util/file_windows.cc
@@ -33,6 +33,16 @@ bool CanAccess(const string& path, bool read, bool write, bool exec) {
pdie(255, "blaze_util::CanAccess is not implemented on Windows");
}
+bool IsDirectory(const string& path) {
+ // TODO(bazel-team): implement this.
+ pdie(255, "blaze_util::IsDirectory is not implemented on Windows");
+}
+
+time_t GetMtimeMillisec(const string& path) {
+ // TODO(bazel-team): implement this.
+ pdie(255, "blaze_util::GetMtimeMillisec is not implemented on Windows");
+}
+
string GetCwd() {
// TODO(bazel-team): implement this.
pdie(255, "blaze_util::GetCwd is not implemented on Windows");