Skip to content

Commit

Permalink
permission: v8.writeHeapSnapshot and process.report
Browse files Browse the repository at this point in the history
Co-Authored-By: haxatron <haxatron1@gmail.com>
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
PR-URL: #48564
Reviewed-By: Paolo Insogna <paolo@cowtech.it>
Reviewed-By: Marco Ippolito <marcoippolito54@gmail.com>
  • Loading branch information
2 people authored and juanarbol committed Jul 13, 2023
1 parent a1f4ff7 commit f4333b1
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/internal/process/report.js
Expand Up @@ -2,6 +2,7 @@
const {
ERR_SYNTHETIC,
} = require('internal/errors').codes;
const { getValidatedPath } = require('internal/fs/utils');
const {
validateBoolean,
validateObject,
Expand All @@ -19,6 +20,7 @@ const report = {
file = undefined;
} else if (file !== undefined) {
validateString(file, 'file');
file = getValidatedPath(file);
}

if (err === undefined) {
Expand Down
5 changes: 5 additions & 0 deletions src/heap_utils.cc
Expand Up @@ -2,6 +2,7 @@
#include "env-inl.h"
#include "memory_tracker-inl.h"
#include "node_external_reference.h"
#include "permission/permission.h"
#include "stream_base-inl.h"
#include "util-inl.h"

Expand Down Expand Up @@ -454,6 +455,8 @@ void TriggerHeapSnapshot(const FunctionCallbackInfo<Value>& args) {

if (filename_v->IsUndefined()) {
DiagnosticFilename name(env, "Heap", "heapsnapshot");
THROW_IF_INSUFFICIENT_PERMISSIONS(
env, permission::PermissionScope::kFileSystemWrite, env->GetCwd());
if (WriteSnapshot(env, *name, options).IsNothing()) return;
if (String::NewFromUtf8(isolate, *name).ToLocal(&filename_v)) {
args.GetReturnValue().Set(filename_v);
Expand All @@ -463,6 +466,8 @@ void TriggerHeapSnapshot(const FunctionCallbackInfo<Value>& args) {

BufferValue path(isolate, filename_v);
CHECK_NOT_NULL(*path);
THROW_IF_INSUFFICIENT_PERMISSIONS(
env, permission::PermissionScope::kFileSystemWrite, path.ToStringView());
if (WriteSnapshot(env, *path, options).IsNothing()) return;
return args.GetReturnValue().Set(filename_v);
}
Expand Down
10 changes: 10 additions & 0 deletions src/node_report.cc
Expand Up @@ -7,6 +7,7 @@
#include "node_metadata.h"
#include "node_mutex.h"
#include "node_worker.h"
#include "permission/permission.h"
#include "util.h"

#ifdef _WIN32
Expand Down Expand Up @@ -856,6 +857,8 @@ std::string TriggerNodeReport(Isolate* isolate,
// Determine the required report filename. In order of priority:
// 1) supplied on API 2) configured on startup 3) default generated
if (!name.empty()) {
THROW_IF_INSUFFICIENT_PERMISSIONS(
env, permission::PermissionScope::kFileSystemWrite, name, name);
// Filename was specified as API parameter.
filename = name;
} else {
Expand All @@ -871,6 +874,13 @@ std::string TriggerNodeReport(Isolate* isolate,
filename = *DiagnosticFilename(
env != nullptr ? env->thread_id() : 0, "report", "json");
}
if (env != nullptr) {
THROW_IF_INSUFFICIENT_PERMISSIONS(
env,
permission::PermissionScope::kFileSystemWrite,
std::string_view(env->GetCwd()),
filename);
}
}

// Open the report file stream for writing. Supports stdout/err,
Expand Down
30 changes: 30 additions & 0 deletions test/parallel/test-permission-fs-write-report.js
@@ -0,0 +1,30 @@
// Flags: --experimental-permission --allow-fs-read=*
'use strict';

const common = require('../common');
common.skipIfWorker();
if (!common.hasCrypto)
common.skip('no crypto');

const assert = require('assert');
const path = require('path');

{
assert.throws(() => {
process.report.writeReport('./secret.txt');
}, common.expectsError({
code: 'ERR_ACCESS_DENIED',
permission: 'FileSystemWrite',
resource: path.resolve('./secret.txt'),
}));
}

{
assert.throws(() => {
process.report.writeReport();
}, common.expectsError({
code: 'ERR_ACCESS_DENIED',
permission: 'FileSystemWrite',
resource: process.cwd(),
}));
}
30 changes: 30 additions & 0 deletions test/parallel/test-permission-fs-write-v8.js
@@ -0,0 +1,30 @@
// Flags: --experimental-permission --allow-fs-read=*
'use strict';

const common = require('../common');
common.skipIfWorker();
if (!common.hasCrypto)
common.skip('no crypto');

const assert = require('assert');
const v8 = require('v8');
const path = require('path');

{
assert.throws(() => {
v8.writeHeapSnapshot('./secret.txt');
}, common.expectsError({
code: 'ERR_ACCESS_DENIED',
permission: 'FileSystemWrite',
resource: path.toNamespacedPath(path.resolve('./secret.txt')),
}));
}

{
assert.throws(() => {
v8.writeHeapSnapshot();
}, common.expectsError({
code: 'ERR_ACCESS_DENIED',
permission: 'FileSystemWrite',
}));
}

0 comments on commit f4333b1

Please sign in to comment.