Skip to content

Commit 2fdbe15

Browse files
committed
permission: keep explicit fs grants when dropping a covering directory
Signed-off-by: RafaelGSS <rafael.nunu@hotmail.com>
1 parent fcfb7ec commit 2fdbe15

2 files changed

Lines changed: 53 additions & 8 deletions

File tree

‎src/permission/fs_permission.cc‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,15 +218,26 @@ void FSPermission::RebuildTree(PermissionScope scope) {
218218

219219
void FSPermission::GrantAccess(PermissionScope perm, const std::string& res) {
220220
const std::string path = WildcardIfDir(res);
221-
if (perm == PermissionScope::kFileSystemRead &&
222-
!granted_in_fs_.Lookup(path)) {
223-
granted_in_fs_.Insert(path);
224-
granted_paths_in_.push_back(path);
221+
// Track every explicit grant, even when already covered by another one,
222+
// so that it still applies if the covering grant is dropped later.
223+
if (perm == PermissionScope::kFileSystemRead) {
224+
if (std::find(granted_paths_in_.begin(), granted_paths_in_.end(), path) ==
225+
granted_paths_in_.end()) {
226+
granted_paths_in_.push_back(path);
227+
}
228+
if (!granted_in_fs_.Lookup(path)) {
229+
granted_in_fs_.Insert(path);
230+
}
225231
deny_all_in_ = false;
226-
} else if (perm == PermissionScope::kFileSystemWrite &&
227-
!granted_out_fs_.Lookup(path)) {
228-
granted_out_fs_.Insert(path);
229-
granted_paths_out_.push_back(path);
232+
} else if (perm == PermissionScope::kFileSystemWrite) {
233+
if (std::find(granted_paths_out_.begin(),
234+
granted_paths_out_.end(),
235+
path) == granted_paths_out_.end()) {
236+
granted_paths_out_.push_back(path);
237+
}
238+
if (!granted_out_fs_.Lookup(path)) {
239+
granted_out_fs_.Insert(path);
240+
}
230241
deny_all_out_ = false;
231242
}
232243
}

‎test/parallel/test-permission-drop-fs-granted-path.js‎

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,40 @@ fs.writeFileSync(path.join(dir, 'item2.txt'), 'bbb');
133133
assert.strictEqual(child.status, 0);
134134
}
135135

136+
// Grant a directory and a file inside it separately, drop the directory
137+
// the explicit file grant still applies regardless of the flag order
138+
for (const files of [
139+
[dir, path.join(dir, 'item1.txt')],
140+
[path.join(dir, 'item1.txt'), dir],
141+
]) {
142+
const child = spawnSync(process.execPath, [
143+
'--permission',
144+
...files.map((file) => `--allow-fs-read=${file}`),
145+
...files.map((file) => `--allow-fs-write=${file}`),
146+
'-e',
147+
`
148+
const assert = require('assert');
149+
const fs = require('fs');
150+
const dir = ${JSON.stringify(dir)};
151+
152+
for (const scope of ['fs.read', 'fs.write']) {
153+
assert.ok(process.permission.has(scope, dir + '/item1.txt'));
154+
assert.ok(process.permission.has(scope, dir + '/item2.txt'));
155+
156+
process.permission.drop(scope, dir);
157+
158+
assert.ok(process.permission.has(scope, dir + '/item1.txt'));
159+
assert.ok(!process.permission.has(scope, dir + '/item2.txt'));
160+
}
161+
assert.strictEqual(fs.readFileSync(dir + '/item1.txt', 'utf8'), 'aaa');
162+
`,
163+
]);
164+
if (child.status !== 0) {
165+
console.error('Case 5 stderr:', child.stderr?.toString());
166+
}
167+
assert.strictEqual(child.status, 0);
168+
}
169+
136170
// Drop entire scope without reference - revokes everything
137171
{
138172
const child = spawnSync(process.execPath, [

0 commit comments

Comments
 (0)