summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Reams <jbreams@mongodb.com>2018-10-19 14:26:52 -0400
committerJonathan Reams <jbreams@mongodb.com>2018-11-30 13:25:44 -0500
commite2aff9fe8ac530d215917d35efcc179b9b6996e2 (patch)
tree4354fd9d59fe1590e0787e3727771878f83e8ddb
parent5e74cc18e7165e40d209ab7de41a527d0f6f0e31 (diff)
downloadmongo-e2aff9fe8ac530d215917d35efcc179b9b6996e2.tar.gz
SERVER-36977 Set process umask before creating log file
(cherry picked from commit a15cf62de1d5de973160ec1a23609aaf6f0f500f)
-rw-r--r--jstests/noPassthrough/umask.js78
-rw-r--r--src/mongo/db/initialize_server_global_state.cpp13
-rw-r--r--src/mongo/shell/shell_utils_extended.cpp39
3 files changed, 124 insertions, 6 deletions
diff --git a/jstests/noPassthrough/umask.js b/jstests/noPassthrough/umask.js
new file mode 100644
index 00000000000..94787f973a0
--- /dev/null
+++ b/jstests/noPassthrough/umask.js
@@ -0,0 +1,78 @@
+/*
+ * This test makes sure that the log files created by the server correctly honor the server's umask
+ * as set in SERVER-22829
+ */
+(function() {
+ 'use strict';
+ // We only test this on POSIX since that's the only platform where umasks make sense
+ if (_isWindows()) {
+ return;
+ }
+
+ const oldUmask = new Number(umask(0));
+ jsTestLog("Setting umask to really permissive 000 mode, old mode was " + oldUmask.toString(8));
+
+ const defaultUmask = Number.parseInt("600", 8);
+ const permissiveUmask = Number.parseInt("666", 8);
+
+ // Any files that have some explicit permissions set on them should be added to this list
+ const exceptions = [
+ // The lock file gets created with explicit 644 permissions
+ 'mongod.lock',
+ // Mobile se files get created with 644 permissions when honoring the system umask
+ 'mobile.sqlite',
+ 'mobile.sqlite-shm',
+ 'mobile.sqlite-wal',
+ ];
+
+ let mongodOptions = MongoRunner.mongodOptions({
+ useLogFiles: true,
+ cleanData: true,
+ });
+
+ if (buildInfo()["modules"].some((mod) => {
+ return mod == "enterprise";
+ })) {
+ mongodOptions.auditDestination = "file";
+ mongodOptions.auditPath = mongodOptions.dbpath + "/audit.log";
+ mongodOptions.auditFormat = "JSON";
+ }
+
+ const checkMask = (topDir, expected, honoringUmask) => {
+ const maybeNot = honoringUmask ? "" : " not";
+ const processDirectory = (dir) => {
+ jsTestLog(`Checking ${dir}`);
+ ls(dir).forEach((file) => {
+ if (file.endsWith("/")) {
+ return processDirectory(file);
+ } else if (exceptions.some((exception) => {
+ return file.endsWith(exception);
+ })) {
+ return;
+ }
+ const mode = new Number(getFileMode(file));
+ const modeStr = mode.toString(8);
+ const msg = `Mode for ${file} is ${modeStr} when${maybeNot} honoring system umask`;
+ assert.eq(mode.valueOf(), expected, msg);
+ });
+ };
+
+ processDirectory(topDir);
+ };
+
+ // First we start up the mongod normally, all the files except mongod.lock should have the mode
+ // 0600
+ let conn = MongoRunner.runMongod(mongodOptions);
+
+ checkMask(conn.fullOptions.dbpath, defaultUmask, false);
+
+ MongoRunner.stopMongod(conn);
+
+ // Restart the mongod with honorSystemUmask, all files should have the mode 0666
+ mongodOptions.setParameter = {honorSystemUmask: true};
+ conn = MongoRunner.runMongod(mongodOptions);
+ checkMask(conn.fullOptions.dbpath, permissiveUmask, false);
+
+ MongoRunner.stopMongod(conn);
+ umask(oldUmask.valueOf());
+})();
diff --git a/src/mongo/db/initialize_server_global_state.cpp b/src/mongo/db/initialize_server_global_state.cpp
index e1a4c159eed..cb0f45b8be9 100644
--- a/src/mongo/db/initialize_server_global_state.cpp
+++ b/src/mongo/db/initialize_server_global_state.cpp
@@ -209,7 +209,7 @@ void forkServerOrDie() {
}
MONGO_INITIALIZER_GENERAL(ServerLogRedirection,
- ("GlobalLogManager", "EndStartupOptionHandling", "ForkServer"),
+ ("GlobalLogManager", "EndStartupOptionHandling", "ForkServer", "MungeUmask"),
("default"))
(InitializerContext*) {
using logger::LogManager;
@@ -347,17 +347,22 @@ MONGO_INITIALIZER(RegisterShortCircuitExitHandler)(InitializerContext*) {
// restrictions we want to apply and set it back. The overall effect
// is to set the bits for 'other' and 'group', but leave umask bits
// bits for 'user' unaltered.
-#ifndef _WIN32
namespace {
+#ifndef _WIN32
MONGO_EXPORT_STARTUP_SERVER_PARAMETER(honorSystemUmask, bool, false);
-MONGO_INITIALIZER(MungeUmask)(InitializerContext*) {
+#endif
+
+MONGO_INITIALIZER_WITH_PREREQUISITES(MungeUmask, ("EndStartupOptionHandling"))
+(InitializerContext*) {
+#ifndef _WIN32
if (!honorSystemUmask) {
umask(umask(S_IRWXU | S_IRWXG | S_IRWXO) | S_IRWXG | S_IRWXO);
}
+#endif
+
return Status::OK();
}
} // namespace
-#endif
bool initializeServerGlobalState() {
Listener::globalTicketHolder.resize(serverGlobalParams.maxConns).transitional_ignore();
diff --git a/src/mongo/shell/shell_utils_extended.cpp b/src/mongo/shell/shell_utils_extended.cpp
index 5ec4692cb9f..acb6ce04234 100644
--- a/src/mongo/shell/shell_utils_extended.cpp
+++ b/src/mongo/shell/shell_utils_extended.cpp
@@ -33,8 +33,12 @@
#include "mongo/platform/basic.h"
-#include <boost/filesystem/convenience.hpp>
-#include <boost/filesystem/fstream.hpp>
+#ifndef _WIN32
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif
+
+#include <boost/filesystem.hpp>
#include <fstream>
#include "mongo/scripting/engine.h"
@@ -302,6 +306,35 @@ BSONObj getHostName(const BSONObj& a, void* data) {
return BSON("" << buf);
}
+BSONObj changeUmask(const BSONObj& a, void* data) {
+#ifdef _WIN32
+ uasserted(50977, "umask is not supported on windows");
+#else
+ uassert(50976,
+ "umask takes 1 argument, the octal mode of the umask",
+ a.nFields() == 1 && isNumericBSONType(a.firstElementType()));
+ auto val = a.firstElement().Number();
+ return BSON("" << umask(static_cast<mode_t>(val)));
+#endif
+}
+
+BSONObj getFileMode(const BSONObj& a, void* data) {
+ uassert(50975,
+ "getFileMode() takes one argument, the absolute path to a file",
+ a.nFields() == 1 && a.firstElementType() == String);
+ auto pathStr = a.firstElement().checkAndGetStringData();
+ boost::filesystem::path path(pathStr.rawData());
+ boost::system::error_code ec;
+ auto fileStatus = boost::filesystem::status(path, ec);
+ if (ec) {
+ uasserted(50974,
+ str::stream() << "Unable to get status for file \"" << pathStr << "\": "
+ << ec.message());
+ }
+
+ return BSON("" << fileStatus.permissions());
+}
+
void installShellUtilsExtended(Scope& scope) {
scope.injectNative("getHostName", getHostName);
scope.injectNative("removeFile", removeFile);
@@ -315,6 +348,8 @@ void installShellUtilsExtended(Scope& scope) {
scope.injectNative("hostname", hostname);
scope.injectNative("md5sumFile", md5sumFile);
scope.injectNative("mkdir", mkdir);
+ scope.injectNative("umask", changeUmask);
+ scope.injectNative("getFileMode", getFileMode);
}
}
}