Skip to content

Commit 36a93e3

Browse files
committed
use lchown to address part 1 of TOCTOU issue
1 parent a631d84 commit 36a93e3

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

chownr.js

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,24 @@
22
const fs = require('fs')
33
const path = require('path')
44

5+
/* istanbul ignore next */
6+
const LCHOWN = fs.lchown ? 'lchown' : 'chown'
7+
/* istanbul ignore next */
8+
const LCHOWNSYNC = fs.lchownSync ? 'lchownSync' : 'chownSync'
9+
510
const chownr = (p, uid, gid, cb) => {
611
fs.readdir(p, (er, children) => {
712
// any error other than ENOTDIR means it's not readable, or
813
// doesn't exist. give up.
914
if (er && er.code !== 'ENOTDIR') return cb(er)
10-
if (er || !children.length) return fs.lchown(p, uid, gid, cb)
15+
if (er || !children.length) return fs[LCHOWN](p, uid, gid, cb)
1116

1217
let len = children.length
1318
let errState = null
1419
const then = er => {
1520
if (errState) return
1621
if (er) return cb(errState = er)
17-
if (-- len === 0) return fs.lchown(p, uid, gid, cb)
22+
if (-- len === 0) return fs[LCHOWN](p, uid, gid, cb)
1823
}
1924

2025
children.forEach(child => {
@@ -36,10 +41,10 @@ const chownrSync = (p, uid, gid) => {
3641
try {
3742
children = fs.readdirSync(p)
3843
} catch (er) {
39-
if (er && er.code === 'ENOTDIR') return fs.lchownSync(p, uid, gid)
44+
if (er && er.code === 'ENOTDIR') return fs[LCHOWNSYNC](p, uid, gid)
4045
throw er
4146
}
42-
if (!children.length) return fs.lchownSync(p, uid, gid)
47+
if (!children.length) return fs[LCHOWNSYNC](p, uid, gid)
4348

4449
children.forEach(child => {
4550
const pathChild = path.resolve(p, child)
@@ -48,7 +53,7 @@ const chownrSync = (p, uid, gid) => {
4853
chownrSync(pathChild, uid, gid)
4954
})
5055

51-
return fs.lchownSync(p, uid, gid)
56+
return fs[LCHOWNSYNC](p, uid, gid)
5257
}
5358

5459
module.exports = chownr

0 commit comments

Comments
 (0)