diff options
-rw-r--r-- | share/txr/stdlib/path-test.tl | 27 | ||||
-rw-r--r-- | txr.1 | 36 |
2 files changed, 41 insertions, 22 deletions
diff --git a/share/txr/stdlib/path-test.tl b/share/txr/stdlib/path-test.tl index 77384fa3..3a7146a8 100644 --- a/share/txr/stdlib/path-test.tl +++ b/share/txr/stdlib/path-test.tl @@ -114,25 +114,36 @@ (sys:path-test (s stat path) (let ((m s.mode) (euid (geteuid))) - (mlet ((g (getgrgid s.gid))) - (and (eql euid s.uid) + (mlet ((g (getgrgid s.gid)) + (name (let ((pw (getpwuid euid))) + (if pw pw.name))) + (suname (let ((pw (getpwuid 0))) + (if pw pw.name)))) + (and (or (zerop s.uid) + (eql euid s.uid)) (zerop (logand m s-iwoth)) (or (zerop (logand m s-iwgrp)) (null g.mem) - (and (not (rest g.mem)) - (equal (getpwuid euid).name (first g.mem))))))))) + (and (all g.mem (orf (op equal name) + (op equal suname)))))))))) (defun path-strictly-private-to-me-p (path) (sys:path-test (s stat path) (let ((m s.mode) (euid (geteuid))) - (mlet ((g (getgrgid s.gid))) - (and (eql euid s.uid) + (mlet ((g (getgrgid s.gid)) + (name (let ((pw (getpwuid euid))) + (if pw pw.name))) + (suname (let ((pw (getpwuid 0))) + (if pw pw.name)))) + (and (or (zerop s.uid) + (eql euid s.uid)) (zerop (logand m (logior s-iroth s-iwoth))) (or (zerop (logand m (logior s-iroth s-iwgrp))) (null g.mem) - (and (not (rest g.mem)) - (equal (getpwuid euid).name (first g.mem))))))))) + (and (all g.mem (orf (op equal name) + (op equal suname)))))))))) + (defmacro sys:path-examine ((sym statfun path) . body) ^[sys:do-path-test ,statfun ,path @@ -53870,8 +53870,8 @@ The rules which the function applies are as follows: A file to be examined is initially assumed to be strictly private. -If the file is not owned by the effective user ID of the caller, then -it is not private. +If the file is not owned by the effective user ID of the caller, or +else by the superuser, then it is not private. If the file grants write permission to "others", then it is not private. @@ -53879,12 +53879,12 @@ If the file grants read permission to "others", then it is not strictly private. If the file grants write permission to the group owner, then it is not -private, unless either the group is empty, or else the group has exactly one -member, who is the owner of the file. +private if the group contains names other than that of the file owner or the +superuser. If the file grants read permission to the group owner, then it is not -strictly private, unless either the group is empty, or else the group has -exactly one member, who is the owner of the file. +strictly private if the group contains names other than that of the file owner +or the superuser. Note that this interpretation of "private" and "strictly private" is vulnerable to the following time-of-check to time-of-use race condition with regard to the @@ -53898,15 +53898,23 @@ race if .meta path is a string rather than a .code stat -structure. If the directory which contains the file is writable to others, the -file can pass the check at the time the function is called, but before it is -used, the file can be replaced by another file with different permissions. -To guard against this race, one must open the file, and then use +structure. If any components of the +.meta path +are symbolic links or directories that can be manipulated by other +users, then the object named by +.meta path +file can pass the check, but can later +.meta path +can be subverted to refer to a different object. + +One way to guard against this race is to open the file, then use .code fstat -on the stream, using the structure returned by fstat to perform the check, -with the understanding that it applies only to the open file, and not -necessarily to whatever object may now be retrieved by the original -directory entry. +on the stream to obtain a +.code stat +structure which is then used as an argument to +.code path-private-to-me-p +or +.codn path-strictly-private-to-me-p . .coNP Functions @ path-newer and @ path-older .synb |