Tcl Source Code

View Ticket
Login
Ticket UUID: 391bc0fd2cdd59209201660b95a2d886d24c1825
Title: glob, -nocomplain, -types, and insufficient privileges
Type: Bug Version: 8.6.6
Submitter: pooryorick Created on: 2016-11-16 06:27:46
Subsystem: 16. Commands A-H Assigned To: nobody
Priority: 5 Medium Severity: Minor
Status: Open Last Modified: 2017-04-30 06:25:26
Resolution: None Closed By: nobody
    Closed on:
Description:

When glob is denied permission to get a directory listing, the result is an error. This is true even with -nocomplain. However, there is a circumstance under which inability to return the requested result due to insufficient permissions does not result in an error. On *nix platforms, a user may have read permissions but not execute permissions on a directory, which means that they may list the contents of the directory, but not the attributes of those contents. In this situation, glob -nocomplain -dir /path/to/dir -types d returns the empty string, since it lacks the ability to get the attributes of the file and thus determine its type. Back before glob had a -nocomplain option, this scenario was covered by the "empty list result is an error" behaviour of glob. The introduction of -nocomplain may have inadvertently lead to this current behaviour, where inability to complete the operation due to insufficient permissions ended up not being an error.

Another facet of this issue is that -types hidden also returns an empty string, even though on *nix, that information is contained in the "." character prefixing the name.

Because of this behaviour, the simple task of walking a hierarchy of files, modifying them as needed in order to continue the walk, becomes rather complex: -types can't be used at all, hidden files have to be explicitly matched on *nix systems, and something like file type, which *does* raise an error, must be used instead in order to raise the alert that there is a potential permissions problem.

User Comments: aspect added on 2017-04-30 06:25:26:

Pushed a fix for {-types hidden} relying on stat() to branch of core-8-5-branch: [e83297c2af]. That includes the error mentioned in the previous comment.

Now I'm not convinced about the second (larger) part of the patch. The code that needs adjusting is populated with this comment:

https://core.tcl.tk/tcl/artifact/92268746c547b361?ln=437-449

.. IMHO passing EACCES back to the caller isn't clearly more useful: a mode 0444 directory may have contents, but we can't do anything with them. It also means [glob] will return EACCES under other conditions (eg, concurrent changes to the parent hierarchy) and raises questions of whether it should handle other error codes, which is a minefield when trying to retain portability. It's a visible change to public routines without clear benefit.

The committed change doesn't raise any new exceptions, so I think it should be fine for the next minor releases.


aspect added on 2017-04-29 13:43:46:
another oddity:

% exec ln -s nonesuch .foo
% exec ln -s nonesuch foo
% glob -types l foo
foo
% glob -types {l hidden} .foo
no files matched glob pattern ".bar"

This is clearly wrong, the two stat calls in NativeMatchType disagree about what to do when stat(symlink) fails.

I have patches resolving this and the issues above - but they need tidying, tests and back-porting from trunk before being push-worthy.  If anyone's waiting, ping me.

aspect added on 2017-04-29 05:03:21:
To summarise:

% file mkdir a/b a/c
% file attributes a -permissions 0600
% file type a/b                             ;# expected error
could not read "a/b": permission denied
% set errorCode
POSIX EACCES {permission denied}

% glob a/*                                  ;# expected
a/b a/c
% glob -types hidden a/*                    ;# 1: should be: {a/. a/..}
no files matched glob pattern "a/*"
% glob -types d a/*                         ;# 2: should raise {POSIX EACCES}
no files matched glob pattern "a/*"
% glob -nocomplain -types d a/*             ;# 3: ??
%


Not quite sure what #3 should do - probably {POSIX EACCES} is best.

Is there a comparable scenario on Windows?

aspect added on 2016-11-16 12:00:30:
This surprised me so I had to dig a bit further.  The manual for <code>stat(2)</code> on Linux and FreeBSD agrees:

<quote>No permissions are required on the file itself, but execute (search) permission is required on all of the directories in pathname that lead to the file.</quote>

So <code>stat()</code> will return -1 with errno <code>EACCES</code> in this case.

An oddity below this:  <code>TclOSStat</code> and friends populate statBuf with junk if the syscall returns non-zero.  I don't think this has any effect, but it doesn't seem wise.