process: allow reading from stdout/stderr sockets · nodejs/node@ea5628e · GitHub
Skip to content

Commit ea5628e

Browse files
addaleaxBethGriggs
authored andcommitted
process: allow reading from stdout/stderr sockets
Allow reading from stdio streams that are conventionally associated with process output, since this is only convention. This involves disabling the oddness around closing stdio streams. Its purpose is to prevent the file descriptors 0 through 2 from being closed, since doing so can lead to information leaks when new file descriptors are being opened; instead, not doing anything seems like a more reasonable choice. Fixes: #21203 Backport-PR-URL: #25351 PR-URL: #23053 Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 1a9582b commit ea5628e

8 files changed

Lines changed: 35 additions & 20 deletions

File tree

doc/api/errors.md

Lines changed: 20 additions & 0 deletions

doc/api/process.md

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,9 +1703,7 @@ important ways:
17031703

17041704
1. They are used internally by [`console.log()`][] and [`console.error()`][],
17051705
respectively.
1706-
2. They cannot be closed ([`end()`][] will throw).
1707-
3. They will never emit the [`'finish'`][] event.
1708-
4. Writes may be synchronous depending on what the stream is connected to
1706+
2. Writes may be synchronous depending on what the stream is connected to
17091707
and whether the system is Windows or POSIX:
17101708
- Files: *synchronous* on Windows and POSIX
17111709
- TTYs (Terminals): *asynchronous* on Windows, *synchronous* on POSIX
@@ -1925,7 +1923,6 @@ cases:
19251923

19261924

19271925
[`'exit'`]: #process_event_exit
1928-
[`'finish'`]: stream.html#stream_event_finish
19291926
[`'message'`]: child_process.html#child_process_event_message
19301927
[`'rejectionHandled'`]: #process_event_rejectionhandled
19311928
[`'uncaughtException'`]: #process_event_uncaughtexception
@@ -1936,7 +1933,6 @@ cases:
19361933
[`EventEmitter`]: events.html#events_class_eventemitter
19371934
[`console.error()`]: console.html#console_console_error_data_args
19381935
[`console.log()`]: console.html#console_console_log_data_args
1939-
[`end()`]: stream.html#stream_writable_end_chunk_encoding_callback
19401936
[`net.Server`]: net.html#net_class_net_server
19411937
[`net.Socket`]: net.html#net_class_net_socket
19421938
[`process.argv`]: #process_process_argv

lib/internal/errors.js

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,6 @@ E('ERR_SOCKET_BUFFER_SIZE',
427427
(reason) => `Could not get or set buffer size: ${reason}`);
428428
E('ERR_SOCKET_CANNOT_SEND', 'Unable to send data');
429429
E('ERR_SOCKET_DGRAM_NOT_RUNNING', 'Not running');
430-
E('ERR_STDERR_CLOSE', 'process.stderr cannot be closed');
431-
E('ERR_STDOUT_CLOSE', 'process.stdout cannot be closed');
432430
E('ERR_UNKNOWN_BUILTIN_MODULE', (id) => `No such built-in module: ${id}`);
433431
E('ERR_UNKNOWN_FILE_EXTENSION', 'Unknown file extension: %s');
434432
E('ERR_UNKNOWN_MODULE_FORMAT', 'Unknown module format: %s');

lib/internal/process/stdio.js

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
'use strict';
22

3-
const errors = require('internal/errors');
3+
const errors = require('internal/errors').codes;
44

55
exports.setup = setupStdio;
66

7+
function dummyDestroy(err, cb) { cb(err); }
8+
79
function setupStdio() {
810
var stdin;
911
var stdout;
@@ -13,11 +15,8 @@ function setupStdio() {
1315
if (stdout) return stdout;
1416
stdout = createWritableStdioStream(1);
1517
stdout.destroySoon = stdout.destroy;
16-
stdout._destroy = function(er, cb) {
17-
// Avoid errors if we already emitted
18-
er = er || new errors.Error('ERR_STDOUT_CLOSE');
19-
cb(er);
20-
};
18+
// Override _destroy so that the fd is never actually closed.
19+
stdout._destroy = dummyDestroy;
2120
if (stdout.isTTY) {
2221
process.on('SIGWINCH', () => stdout._refreshSize());
2322
}
@@ -28,11 +27,8 @@ function setupStdio() {
2827
if (stderr) return stderr;
2928
stderr = createWritableStdioStream(2);
3029
stderr.destroySoon = stderr.destroy;
31-
stderr._destroy = function(er, cb) {
32-
// Avoid errors if we already emitted
33-
er = er || new errors.Error('ERR_STDERR_CLOSE');
34-
cb(er);
35-
};
30+
// Override _destroy so that the fd is never actually closed.
31+
stdout._destroy = dummyDestroy;
3632
if (stderr.isTTY) {
3733
process.on('SIGWINCH', () => stderr._refreshSize());
3834
}

test/parallel/test-stdout-cannot-be-closed-child-process-pipe.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ function parent() {
2424
});
2525

2626
child.on('close', function(code, signal) {
27-
assert(code);
27+
assert.strictEqual(code, 0);
28+
assert.strictEqual(err, '');
2829
assert.strictEqual(out, 'foo');
29-
assert(/process\.stdout cannot be closed/.test(err));
3030
console.log('ok');
3131
});
3232
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Hello!
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
const common = require('../common');
3+
process.stderr.on('data', common.mustCall(console.log));
Lines changed: 1 addition & 0 deletions

0 commit comments

Comments
 (0)