Ensure proper file permissions on startup

Co-authored-by: Scott Nonnenberg <scott@signal.org>
This commit is contained in:
Ken Powers 2020-02-21 18:40:04 -05:00 committed by GitHub
parent 6b56dd4ce0
commit 8d9ccd3c0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 289 additions and 24 deletions

59
main.js
View file

@ -3,9 +3,12 @@
const path = require('path');
const url = require('url');
const os = require('os');
const fs = require('fs');
const fs = require('fs-extra');
const crypto = require('crypto');
const qs = require('qs');
const normalizePath = require('normalize-path');
const fg = require('fast-glob');
const PQueue = require('p-queue').default;
const _ = require('lodash');
const pify = require('pify');
@ -16,6 +19,10 @@ const GlobalErrors = require('./app/global_errors');
GlobalErrors.addHandler();
// Set umask early on in the process lifecycle to ensure file permissions are
// set such that only we have read access to our files
process.umask(0o077);
const getRealPath = pify(fs.realpath);
const {
app,
@ -863,6 +870,8 @@ app.on('ready', async () => {
}
setupMenu();
ensureFilePermissions(['config.json', 'sql/db.sqlite']);
});
function setupMenu(options) {
@ -1195,3 +1204,51 @@ ipc.on('install-sticker-pack', (_event, packId, packKeyHex) => {
const packKey = Buffer.from(packKeyHex, 'hex').toString('base64');
mainWindow.webContents.send('install-sticker-pack', { packId, packKey });
});
ipc.on('ensure-file-permissions', async event => {
await ensureFilePermissions();
event.reply('ensure-file-permissions-done');
});
/**
* Ensure files in the user's data directory have the proper permissions.
* Optionally takes an array of file paths to exclusively affect.
*
* @param {string[]} [onlyFiles] - Only ensure permissions on these given files
*/
async function ensureFilePermissions(onlyFiles) {
console.log('Begin ensuring permissions');
const start = Date.now();
const userDataPath = await getRealPath(app.getPath('userData'));
// fast-glob uses `/` for all platforms
const userDataGlob = normalizePath(path.join(userDataPath, '**', '*'));
// Determine files to touch
const files = onlyFiles
? onlyFiles.map(f => path.join(userDataPath, f))
: await fg(userDataGlob, {
markDirectories: true,
onlyFiles: false,
ignore: ['**/Singleton*'],
});
console.log(`Ensuring file permissions for ${files.length} files`);
// Touch each file in a queue
const q = new PQueue({ concurrency: 5 });
q.addAll(
files.map(f => async () => {
const isDir = f.endsWith('/');
try {
await fs.chmod(path.normalize(f), isDir ? 0o700 : 0o600);
} catch (error) {
console.error('ensureFilePermissions: Error from chmod', error.message);
}
})
);
await q.onEmpty();
console.log(`Finish ensuring permissions in ${Date.now() - start}ms`);
}