mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 00:20:08 +01:00
src: tolerate EPERM returned from tcsetattr
macOS app sandbox makes tcsetattr return EPERM. The CHECK_EQ(0, err) here would fail when a sandboxed Node.js process is exiting. This commit fixes this issue. * test: add test for running in macOS app sandbox Bare-bone command-line executables cannot run directly in the app sandbox. To test that Node.js is able to run in the sandbox (and to test the fix in 317621b4a12562eb75055a67bb2c5556f53fe017), this commit creates a typical Cocoa app bundle, puts the node executable in it and calles Apple's codesign command to enable sandbox. * test: use process.execPath to get path of testing node PR-URL: https://github.com/nodejs/node/pull/33944 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
56124e92e8
commit
cb2c8106a7
|
|
@ -730,7 +730,10 @@ void ResetStdio() {
|
|||
err = tcsetattr(fd, TCSANOW, &s.termios);
|
||||
while (err == -1 && errno == EINTR); // NOLINT
|
||||
CHECK_EQ(0, pthread_sigmask(SIG_UNBLOCK, &sa, nullptr));
|
||||
CHECK_EQ(0, err);
|
||||
|
||||
// Normally we expect err == 0. But if macOS App Sandbox is enabled,
|
||||
// tcsetattr will fail with err == -1 and errno == EPERM.
|
||||
CHECK_IMPLIES(err != 0, err == -1 && errno == EPERM);
|
||||
}
|
||||
}
|
||||
#endif // __POSIX__
|
||||
|
|
|
|||
24
test/fixtures/macos-app-sandbox/Info.plist
vendored
Normal file
24
test/fixtures/macos-app-sandbox/Info.plist
vendored
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>node</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.nodejs.test.node_sandboxed</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>node_sandboxed</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSupportedPlatforms</key>
|
||||
<array>
|
||||
<string>MacOSX</string>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
8
test/fixtures/macos-app-sandbox/node_sandboxed.entitlements
vendored
Normal file
8
test/fixtures/macos-app-sandbox/node_sandboxed.entitlements
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.app-sandbox</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
65
test/parallel/test-macos-app-sandbox.js
Normal file
65
test/parallel/test-macos-app-sandbox.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
'use strict';
|
||||
const common = require('../common');
|
||||
if (process.platform !== 'darwin')
|
||||
common.skip('App Sandbox is only avaliable on Darwin');
|
||||
|
||||
const fixtures = require('../common/fixtures');
|
||||
const tmpdir = require('../common/tmpdir');
|
||||
const assert = require('assert');
|
||||
const child_process = require('child_process');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const os = require('os');
|
||||
|
||||
const nodeBinary = process.execPath;
|
||||
|
||||
tmpdir.refresh();
|
||||
|
||||
const appBundlePath = path.join(tmpdir.path, 'node_sandboxed.app');
|
||||
const appBundleContentPath = path.join(appBundlePath, 'Contents');
|
||||
const appExecutablePath = path.join(
|
||||
appBundleContentPath, 'MacOS', 'node');
|
||||
|
||||
// Construct the app bundle and put the node executable in it:
|
||||
// node_sandboxed.app/
|
||||
// └── Contents
|
||||
// ├── Info.plist
|
||||
// ├── MacOS
|
||||
// │ └── node
|
||||
fs.mkdirSync(appBundlePath);
|
||||
fs.mkdirSync(appBundleContentPath);
|
||||
fs.mkdirSync(path.join(appBundleContentPath, 'MacOS'));
|
||||
fs.copyFileSync(
|
||||
fixtures.path('macos-app-sandbox', 'Info.plist'),
|
||||
path.join(appBundleContentPath, 'Info.plist'));
|
||||
fs.copyFileSync(
|
||||
nodeBinary,
|
||||
appExecutablePath);
|
||||
|
||||
|
||||
// Sign the app bundle with sandbox entitlements:
|
||||
assert.strictEqual(
|
||||
child_process.spawnSync('/usr/bin/codesign', [
|
||||
'--entitlements', fixtures.path(
|
||||
'macos-app-sandbox', 'node_sandboxed.entitlements'),
|
||||
'-s', '-',
|
||||
appBundlePath
|
||||
]).status,
|
||||
0);
|
||||
|
||||
// Sandboxed app shouldn't be able to read the home dir
|
||||
assert.notStrictEqual(
|
||||
child_process.spawnSync(appExecutablePath, [
|
||||
'-e', 'fs.readdirSync(process.argv[1])', os.homedir()
|
||||
]).status,
|
||||
0);
|
||||
|
||||
if (process.stdin.isTTY) {
|
||||
// Run the sandboxed node instance with inherited tty stdin
|
||||
const spawnResult = child_process.spawnSync(
|
||||
appExecutablePath, ['-e', ''],
|
||||
{ stdio: 'inherit' }
|
||||
);
|
||||
|
||||
assert.strictEqual(spawnResult.signal, null);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user