From c50954dc62c45e09b65a2ba99c6a2d3f107ed989 Mon Sep 17 00:00:00 2001 From: Daniel Katz Date: Thu, 27 Oct 2022 15:32:50 +0300 Subject: [PATCH] fix: fix EACCES error on access by root user --- lib/binding.js | 21 ++++++++------------- test/lib/binding.spec.js | 20 +++++++++++++++++++- test/lib/item.spec.js | 32 ++++++++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 16 deletions(-) diff --git a/lib/binding.js b/lib/binding.js index cea5405..a4a3e6c 100644 --- a/lib/binding.js +++ b/lib/binding.js @@ -1325,19 +1325,14 @@ Binding.prototype.access = function (filepath, mode, callback, ctx) { throw new FSError('ENOENT', filepath); } if (mode && process.getuid && process.getgid) { - const itemMode = item.getMode(); - if (item.getUid() === process.getuid()) { - if ((itemMode & (mode * 64)) !== mode * 64) { - throw new FSError('EACCES', filepath); - } - } else if (item.getGid() === process.getgid()) { - if ((itemMode & (mode * 8)) !== mode * 8) { - throw new FSError('EACCES', filepath); - } - } else { - if ((itemMode & mode) !== mode) { - throw new FSError('EACCES', filepath); - } + if (mode & constants.R_OK && !item.canRead()) { + throw new FSError('EACCES', filepath); + } + if (mode & constants.W_OK && !item.canWrite()) { + throw new FSError('EACCES', filepath); + } + if (mode & constants.X_OK && !item.canExecute()) { + throw new FSError('EACCES', filepath); } } }); diff --git a/test/lib/binding.spec.js b/test/lib/binding.spec.js index f2b55fa..d00b5f3 100644 --- a/test/lib/binding.spec.js +++ b/test/lib/binding.spec.js @@ -1625,6 +1625,14 @@ describe('Binding', function () { }); describe('#access()', function () { + const originalGetuid = process.getuid; + const originalGetgid = process.getgid; + + beforeEach(function () { + process.getuid = originalGetuid; + process.getgid = originalGetgid; + }); + it('works if file exists', function () { const binding = new Binding(system); const pathname = path.join('mock-dir', 'one-link.txt'); @@ -1639,7 +1647,7 @@ describe('Binding', function () { }, /ENOENT/); }); - if (process.getuid && process.getgid) { + if (originalGetuid && originalGetgid) { it('fails in case of insufficient user permissions', function () { const binding = new Binding(system); const item = system.getItem(path.join('mock-dir', 'one.txt')); @@ -1669,6 +1677,16 @@ describe('Binding', function () { binding.access(path.join('mock-dir', 'one.txt'), 5); }, /EACCES/); }); + + it('sould not throw if process runs as root', function () { + const binding = new Binding(system); + const item = system.getItem(path.join('mock-dir', 'one.txt')); + item.setUid(42); + item.setGid(42); + item.setMode(parseInt('0000', 8)); + process.getuid = () => 0; + binding.access(path.join('mock-dir', 'one.txt'), 5); + }); } it('fails for bogus paths', function () { diff --git a/test/lib/item.spec.js b/test/lib/item.spec.js index 80dd5a7..b1d4204 100644 --- a/test/lib/item.spec.js +++ b/test/lib/item.spec.js @@ -139,11 +139,15 @@ describe('Item', function () { }); if (process.getgid && process.getuid) { - const uid = process.getuid(); - const gid = process.getgid(); + const originalGetuid = process.getuid; + const originalGetgid = process.getgid; + const uid = originalGetuid(); + const gid = originalGetgid(); let item; beforeEach(function () { + process.getuid = originalGetuid; + process.getgid = originalGetgid; item = new Item(); }); @@ -220,6 +224,14 @@ describe('Item', function () { item.setMode(parseInt('0777', 8)); assert.isTrue(item.canRead()); }); + + it('always returns true if process runs as root', function () { + process.getuid = () => 0; + item.setUid(42); + item.setGid(42); + item.setMode(parseInt('0000', 8)); + assert.isTrue(item.canRead()); + }); }); describe('#canWrite()', function () { @@ -295,6 +307,14 @@ describe('Item', function () { item.setMode(parseInt('0777', 8)); assert.isTrue(item.canWrite()); }); + + it('always returns true if process runs as root', function () { + process.getuid = () => 0; + item.setUid(42); + item.setGid(42); + item.setMode(parseInt('0000', 8)); + assert.isTrue(item.canWrite()); + }); }); describe('#canExecute()', function () { @@ -370,6 +390,14 @@ describe('Item', function () { item.setMode(parseInt('0777', 8)); assert.isTrue(item.canExecute()); }); + + it('always returns true if process runs as root', function () { + process.getuid = () => 0; + item.setUid(42); + item.setGid(42); + item.setMode(parseInt('0000', 8)); + assert.isTrue(item.canExecute()); + }); }); } });