Thread (3 messages) flat view 3 messages, 2 authors, 2016-06-15

Re: [PATCH 1/2] run-command: Add checks after execvp fails with EACCES

From: Frans Klaver <hidden>
Date: 2016-06-15 22:52:38

On Tue, Dec 13, 2011 at 8:01 PM, Junio C Hamano [off-list ref] wrote:
 - That "have_..._ions()" is too long and ugly.
I half expected that one and I agree. I vaguely remember typing it,
deleting it and typing it again when I started on that one.

 - The only thing you care about this callsite is if you have enough
  permission to execute the "cmd".

In fact, you should not unconditionally require read permissions here.

   $ chmod a-r $(type --path git) && /bin/ls -l $(type --path git)
   --wx--x--x 109 junio junio 5126580 Dec 13 09:47 /home/junio/git-active/bin/git
   $ /home/junio/git-active/bin/git --version
   git version 1.7.8.249.gb1b73

You may need read permission when the file is a script (i.e. not binary
executable).
[...]
When checking if you can run "foo/bar/baz", directories "foo/" and "foo/bar/"
do not have to be readable.  They only have to have executable bit to allow
descending into them, and typically this is called "searchable" (see man chmod).

   $ mkdir -p /var/tmp/a/b && cp $(type --path git) /var/tmp/a/b/git
   $ chmod 111 /var/tmp/a /var/tmp/a/b
   $ /var/tmp/a/b/git --version
   git version 1.7.8.249.gb1b73

I'd suggest having two helper functions, instead of the single one with
overlong "have...ions" name.

 - can_search_directory() checks with access(X_OK);

 - can_execute_file() checks with access(X_OK|R_OK), even though R_OK is
  not always needed.
On the whole I like the suggestion. We should probably take it a bit
further. Since the x and r bits basically have nothing to do with each
other, and we need +rx only on scripts, I could just rely on fopen()
for the +r check. I will still add the can_execute_file() and
can_search_dir() helpers to support readability, as access(path, X_OK)
means different things in the different contexts. I would then
probably go for is_searchable() and is_executable() as function names.
is_executable then means "is file and has executable flag set",
is_searchable means "is directory and has executable flag set".
Basically files won't be searchable and directories won't be
executable. If execvp fails on a command that is executable, but not
readable, it is definitely a script and we can generate an error in
that case. 1/2 would then probably use access(path, R_OK), while 2/2
would start using fopen.

Since fopen() uses the effective uid/gid, it then makes sense to use
eaccess(3) instead of access(2) if available. It would be stupid to
have bugs arise just because of a mismatch between the [ug]ids used by
the two access checks. I'm aware of the fact that eaccess isn't a
standard function, so a #define HAVE... fallback to at least access()
would probably be required.

Use the former here where you check the directory that contains the
command, and use the latter up above where you check the command that is
supposed to be executable, and also down below after you checked sb.buf is
a path to a file that may be the command that is supposed to be
executable.

Then patch 2/2 can extend can_execute() to enhance its support for scripts
by reading the hash-bang line and validating it, etc.
I'd rather keep the hash-bang check outside of that function and use
can_execute/is_executable for checking the interpreter as well, if
only for keeping the possibility of easily promoting them into an API.

I'd rather move check_interpreter into where it's called now, but pull
out the logic to find the interpreter. This will keep the error text
generation in diagnose_execvp_eacces. I think the code will make more
sense this way. There's tons of more errors that can be caused by a
faulty interpreter, and it'll be easier to cover more cases this way
in the future.

Thanks for the insightful reviews so far.

Let me know what you think,
Frans
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help