Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: fix OOB reads in process.title getter #31633

Closed
wants to merge 4 commits into from

Conversation

bnoordhuis
Copy link
Member

The getter passed a stack-allocated, fixed-size buffer to
uv_get_process_title() but neglected to check the return value.

When the total length of the command line arguments exceeds the size of
the buffer, libuv returns UV_ENOBUFS and doesn't modify the contents of
the buffer. The getter then proceeded to return whatever garbage was on
the stack at the time of the call, quite possibly reading beyond the
end of the buffer.

Add a GetProcessTitle() helper that reads the process title into a
dynamically allocated buffer that is resized when necessary.

Fixes: #31631

  • this is technically a security vulnerability although probably impossible to exploit practically
  • the second commit I'm happy to leave out
  • there's also a minor libuv bug but this PR is still necessary

The getter passed a stack-allocated, fixed-size buffer to
uv_get_process_title() but neglected to check the return value.

When the total length of the command line arguments exceeds the size of
the buffer, libuv returns UV_ENOBUFS and doesn't modify the contents of
the buffer. The getter then proceeded to return whatever garbage was on
the stack at the time of the call, quite possibly reading beyond the
end of the buffer.

Add a GetProcessTitle() helper that reads the process title into a
dynamically allocated buffer that is resized when necessary.

Fixes: nodejs#31631
Remove the version of GetHumanReadableProcessName() that operates on a
fixed-size buffer.

The only remaining caller is Assert() which might get called in contexts
where dynamically allocating memory isn't possible but as Assert() calls
printf(), which also allocates memory when necessary, this commit is
unlikely to make matters much worse.
@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels Feb 4, 2020
@nodejs-github-bot
Copy link
Collaborator

std::string buf(16, '\0');

for (;;) {
const int rc = uv_get_process_title(&buf[0], buf.size());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not blocking for this PR, but... in the future, might it be possible to introduce a variant of uv_get_process_title that can optionally report the size of the buffer required? something along the lines of...

  size_t actual = buf.size();
  const int rc = uv_get_process_title2(&buf[0], &actual);
  if (rc == UV_ENOBUFS) {
    buf.resize(actual);
    // then try again
  }
  // ....

Definitely minor but a bit nicer to avoid the multiple resize operations

@nodejs-github-bot
Copy link
Collaborator

// is necessary otherwise *its* process.title is whatever the last
// SetConsoleTitle() call in our process tree set it to.
if (common.isWindows)
process.title = process.execPath;
Copy link
Member

@jasnell jasnell Feb 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using // Flags: --title=test to explicitly set the title with a flag would work here also, right? Might be better than having a special case here for Windows

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See libuv/libuv#2667 - I believe this is a Windows-only libuv bug. Until it's fixed, it's best to call it out explicitly.

@addaleax addaleax added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Feb 7, 2020
@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented Feb 7, 2020

CI: https://ci.nodejs.org/job/node-test-pull-request/28985/ (:heavy_check_mark:)

addaleax pushed a commit that referenced this pull request Feb 7, 2020
The getter passed a stack-allocated, fixed-size buffer to
uv_get_process_title() but neglected to check the return value.

When the total length of the command line arguments exceeds the size of
the buffer, libuv returns UV_ENOBUFS and doesn't modify the contents of
the buffer. The getter then proceeded to return whatever garbage was on
the stack at the time of the call, quite possibly reading beyond the
end of the buffer.

Add a GetProcessTitle() helper that reads the process title into a
dynamically allocated buffer that is resized when necessary.

Fixes: #31631

PR-URL: #31633
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
addaleax pushed a commit that referenced this pull request Feb 7, 2020
Remove the version of GetHumanReadableProcessName() that operates on a
fixed-size buffer.

The only remaining caller is Assert() which might get called in contexts
where dynamically allocating memory isn't possible but as Assert() calls
printf(), which also allocates memory when necessary, this commit is
unlikely to make matters much worse.

PR-URL: #31633
Fixes: #31631
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@addaleax
Copy link
Member

addaleax commented Feb 7, 2020

Landed in d394dd7 3271c40

@addaleax addaleax closed this Feb 7, 2020
codebytere pushed a commit that referenced this pull request Feb 17, 2020
The getter passed a stack-allocated, fixed-size buffer to
uv_get_process_title() but neglected to check the return value.

When the total length of the command line arguments exceeds the size of
the buffer, libuv returns UV_ENOBUFS and doesn't modify the contents of
the buffer. The getter then proceeded to return whatever garbage was on
the stack at the time of the call, quite possibly reading beyond the
end of the buffer.

Add a GetProcessTitle() helper that reads the process title into a
dynamically allocated buffer that is resized when necessary.

Fixes: #31631

PR-URL: #31633
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
codebytere pushed a commit that referenced this pull request Feb 17, 2020
Remove the version of GetHumanReadableProcessName() that operates on a
fixed-size buffer.

The only remaining caller is Assert() which might get called in contexts
where dynamically allocating memory isn't possible but as Assert() calls
printf(), which also allocates memory when necessary, this commit is
unlikely to make matters much worse.

PR-URL: #31633
Fixes: #31631
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@codebytere codebytere mentioned this pull request Feb 17, 2020
codebytere pushed a commit that referenced this pull request Mar 15, 2020
The getter passed a stack-allocated, fixed-size buffer to
uv_get_process_title() but neglected to check the return value.

When the total length of the command line arguments exceeds the size of
the buffer, libuv returns UV_ENOBUFS and doesn't modify the contents of
the buffer. The getter then proceeded to return whatever garbage was on
the stack at the time of the call, quite possibly reading beyond the
end of the buffer.

Add a GetProcessTitle() helper that reads the process title into a
dynamically allocated buffer that is resized when necessary.

Fixes: #31631

PR-URL: #31633
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
codebytere pushed a commit that referenced this pull request Mar 15, 2020
Remove the version of GetHumanReadableProcessName() that operates on a
fixed-size buffer.

The only remaining caller is Assert() which might get called in contexts
where dynamically allocating memory isn't possible but as Assert() calls
printf(), which also allocates memory when necessary, this commit is
unlikely to make matters much worse.

PR-URL: #31633
Fixes: #31631
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
codebytere pushed a commit that referenced this pull request Mar 17, 2020
The getter passed a stack-allocated, fixed-size buffer to
uv_get_process_title() but neglected to check the return value.

When the total length of the command line arguments exceeds the size of
the buffer, libuv returns UV_ENOBUFS and doesn't modify the contents of
the buffer. The getter then proceeded to return whatever garbage was on
the stack at the time of the call, quite possibly reading beyond the
end of the buffer.

Add a GetProcessTitle() helper that reads the process title into a
dynamically allocated buffer that is resized when necessary.

Fixes: #31631

PR-URL: #31633
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
codebytere pushed a commit that referenced this pull request Mar 17, 2020
Remove the version of GetHumanReadableProcessName() that operates on a
fixed-size buffer.

The only remaining caller is Assert() which might get called in contexts
where dynamically allocating memory isn't possible but as Assert() calls
printf(), which also allocates memory when necessary, this commit is
unlikely to make matters much worse.

PR-URL: #31633
Fixes: #31631
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
@codebytere codebytere mentioned this pull request Mar 17, 2020
codebytere pushed a commit that referenced this pull request Mar 30, 2020
The getter passed a stack-allocated, fixed-size buffer to
uv_get_process_title() but neglected to check the return value.

When the total length of the command line arguments exceeds the size of
the buffer, libuv returns UV_ENOBUFS and doesn't modify the contents of
the buffer. The getter then proceeded to return whatever garbage was on
the stack at the time of the call, quite possibly reading beyond the
end of the buffer.

Add a GetProcessTitle() helper that reads the process title into a
dynamically allocated buffer that is resized when necessary.

Fixes: #31631

PR-URL: #31633
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
codebytere pushed a commit that referenced this pull request Mar 30, 2020
Remove the version of GetHumanReadableProcessName() that operates on a
fixed-size buffer.

The only remaining caller is Assert() which might get called in contexts
where dynamically allocating memory isn't possible but as Assert() calls
printf(), which also allocates memory when necessary, this commit is
unlikely to make matters much worse.

PR-URL: #31633
Fixes: #31631
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: David Carlier <devnexen@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
codebytere added a commit to electron/electron that referenced this pull request Nov 21, 2022
codebytere added a commit to electron/electron that referenced this pull request Nov 21, 2022
jkleinsc added a commit to electron/electron that referenced this pull request Nov 21, 2022
* chore: bump node in DEPS to v18.12.1

* chore: update patches

* chore: add missing <algorithm> include

* src: add detailed embedder process initialization AP

nodejs/node#44121

* chore: update gn build files

* dns: support dns module in the snapshot

nodejs/node#44633

#36118

* src: fix OOB reads in process.title getter

nodejs/node#31633

* chore: fix incorrectly removed patch bit

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
khalwa pushed a commit to solarwindscloud/electron that referenced this pull request Feb 22, 2023
* chore: bump node in DEPS to v18.12.1

* chore: update patches

* chore: add missing <algorithm> include

* src: add detailed embedder process initialization AP

nodejs/node#44121

* chore: update gn build files

* dns: support dns module in the snapshot

nodejs/node#44633

electron#36118

* src: fix OOB reads in process.title getter

nodejs/node#31633

* chore: fix incorrectly removed patch bit

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Process.title gets corrupted in case process.argv[2] is too long
8 participants