Skip to content
Permalink
Browse files Browse the repository at this point in the history
SERVER-25335 avoid group and other permissions when creating .dbshell…
… history file
  • Loading branch information
devkev committed Sep 6, 2016
1 parent 078f29b commit 035cf2a
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 2 deletions.
103 changes: 103 additions & 0 deletions jstests/noPassthrough/shell_history.js
@@ -0,0 +1,103 @@
// Test that when running the shell for the first time creates the ~/.dbshell file, and it has
// appropriate permissions (where relevant).

(function() {
"use strict";

// Use dataPath because it includes the trailing "/" or "\".
var tmpHome = MongoRunner.dataPath;
// Ensure it exists and is a dir (eg. if running without resmoke.py and /data/db doesn't exist).
mkdir(tmpHome);
removeFile(tmpHome + ".dbshell");

var args = [];
var cmdline = "mongo --nodb";
var redirection = "";
var env = {};
if (_isWindows()) {
args.push("cmd.exe");
args.push("/c");

// Input is set to NUL. The output must also be redirected to NUL, otherwise running the
// jstest manually has strange terminal IO behaviour.
redirection = "< NUL > NUL";

// USERPROFILE set to the tmp homedir.
// Since NUL is a character device, isatty() will return true, which means that .mongorc.js
// will be created in the HOMEDRIVE + HOMEPATH location, so we must set them also.
if (tmpHome.match("^[a-zA-Z]:")) {
var tmpHomeDrive = tmpHome.substr(0, 2);
var tmpHomePath = tmpHome.substr(2);
} else {
var _pwd = pwd();
assert(_pwd.match("^[a-zA-Z]:"), "pwd must include drive");
var tmpHomeDrive = _pwd.substr(0, 2);
var tmpHomePath = tmpHome;
}
env = {USERPROFILE: tmpHome, HOMEDRIVE: tmpHomeDrive, HOMEPATH: tmpHomePath};

} else {
args.push("sh");
args.push("-c");

// Use the mongo shell from the current dir, same as resmoke.py does.
// Doesn't handle resmoke's --mongo= option.
cmdline = "./" + cmdline;

// Set umask to 0 prior to running the shell.
cmdline = "umask 0 ; " + cmdline;

// stdin is /dev/null.
redirection = "< /dev/null";

// HOME set to the tmp homedir.
if (!tmpHome.startsWith("/")) {
tmpHome = pwd() + "/" + tmpHome;
}
env = {HOME: tmpHome};
}

// Add redirection to cmdline, and add cmdline to args.
cmdline += " " + redirection;
args.push(cmdline);
jsTestLog("Running args:\n " + tojson(args) + "\nwith env:\n " + tojson(env));
var pid = _startMongoProgram({args, env});
var rc = waitProgram(pid);

assert.eq(rc, 0);

var files = listFiles(tmpHome);
jsTestLog(tojson(files));

var findFile = function(baseName) {
for (var i = 0; i < files.length; i++) {
if (files[i].baseName === baseName) {
return files[i];
}
}
return undefined;
};

var targetFile = ".dbshell";
var file = findFile(targetFile);

assert.neq(typeof(file), "undefined", targetFile + " should exist, but it doesn't");
assert.eq(file.isDirectory, false, targetFile + " should not be a directory, but it is");
assert.eq(file.size, 0, targetFile + " should be empty, but it isn't");

if (!_isWindows()) {
// On Unix, check that the file has the correct mode (permissions).
// The shell has no way to stat a file.
// There is no stat utility in POSIX.
// `ls -l` is POSIX, so this is the best that we have.
// Check for exactly "-rw-------".
clearRawMongoProgramOutput();
var rc = runProgram("ls", "-l", file.name);
assert.eq(rc, 0);
var output = rawMongoProgramOutput();
var fields = output.split(" ");
// First field is the prefix, second field is the `ls -l` permissions.
assert.eq(fields[1], "-rw-------", targetFile + " has bad permissions");
}

})();
14 changes: 12 additions & 2 deletions src/mongo/shell/linenoise.cpp
Expand Up @@ -2762,7 +2762,17 @@ int linenoiseHistorySetMaxLen(int len) {
/* Save the history in the specified file. On success 0 is returned
* otherwise -1 is returned. */
int linenoiseHistorySave(const char* filename) {
FILE* fp = fopen(filename, "wt");
FILE* fp;
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
int fd = open(filename, O_CREAT, S_IRUSR | S_IWUSR);
if (fd == -1) {
// report errno somehow?
return -1;
}
fp = fdopen(fd, "wt");
#else
fp = fopen(filename, "wt");
#endif // _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _POSIX_SOURCE
if (fp == NULL) {
return -1;
}
Expand All @@ -2772,7 +2782,7 @@ int linenoiseHistorySave(const char* filename) {
fprintf(fp, "%s\n", history[j]);
}
}
fclose(fp);
fclose(fp); // Also causes fd to be closed.
return 0;
}

Expand Down

0 comments on commit 035cf2a

Please sign in to comment.