To be clear, the current implementation of using stat(), reading the
permissions, then later exec()ing is subject to the same race conditions
described in the access() man page. Just because stat() doesn't include
these warnings in the man page shouldn't be interpreted that the current
usage is race condition free.

In fact, if the code wants to be race condition free, the appropriate
thing to do is to skip the access(X_OK) check *and* the stat() check,
and just do the exec(). This is the solution I proposed in comment #10
bullet #5. Since you're raising security concerns, I assume you want to
be race condition free?

As an alternative solution to deal with buggy or incomplete access()
implementations, we could also consider making the "stat()" call
conditional on the operating system. For Linux, in particular,
access(X_OK) is known to be robust, so we can omit the stat() check on
that operating system. I proposed a similar solution in
https://bugs.launchpad.net/mksh/+bug/1817959 comment #6.

-- 
You received this bug notification because you are a member of mksh
Mailing List, which is subscribed to mksh.
Matching subscriptions: mkshlist-to-mksh-bugmail
https://bugs.launchpad.net/bugs/1817789

Title:
  misleading error message for SELinux denials

Status in mksh:
  Opinion

Bug description:
  Given a stat(2) failure caused by an SELinux denial (rather than a
  stat(2) success and an access(2) failure, as with a regular `chmod
  a-x` failure), mksh reports "not found" rather than the more correct
  "Permission denied".

  Expected:
  * Permission Denied error message

  Actual:

    $ sh -c /system/bin/vold
    sh: /system/bin/vold: not found

    "not found" error message.

  
  here's the behind-the-scenes SELinux denial:

  02-25 22:37:11.023  4571  4571 W sh      : type=1400 audit(0.0:347):
  avc: denied { getattr } for path="/system/bin/vold" dev="dm-0" ino=717
  scontext=u:r:shell:s0 tcontext=u:object_r:vold_exec:s0 tclass=file
  permissive=0

  
  here's what strace says happened:

  newfstatat(AT_FDCWD, "/system/bin/vold", 0x7ffcc3ef20, 0) = -1 EACCES 
(Permission denied)
  write(2, "/system/bin/sh: /system/bin/vold"..., 44/system/bin/sh: 
/system/bin/vold: not found
  ) = 44

  versus the normal `chmod a-x` case where stat succeeds but access
  fails:

  newfstatat(AT_FDCWD, "/data/local/tmp/date2", {st_mode=S_IFREG|0644, 
st_size=482560, ...}, 0) = 0
  faccessat(AT_FDCWD, "/data/local/tmp/date2", X_OK) = -1 EACCES (Permission 
denied)
  write(2, "sh: /data/local/tmp/date2: can't"..., 60sh: /data/local/tmp/date2: 
can't execute: Permission denied
  ) = 60

  
  this patch fixes the issue:

  ```
  diff --git a/src/exec.c b/src/exec.c
  index 8330174..3f6d876 100644
  --- a/src/exec.c
  +++ b/src/exec.c
  @@ -1279,8 +1279,8 @@ search_access(const char *fn, int mode)
          struct stat sb;
   
          if (stat(fn, &sb) < 0)
  -               /* file does not exist */
  -               return (ENOENT);
  +               /* file may or may not exist: check errno */
  +               return errno;
          /* LINTED use of access */
          if (access(fn, mode) < 0) {
                  /* file exists, but we can't access it */
  ```

  i don't know if you want to elaborate further in the comment along the
  lines of "...for example, an SELinux denial may mean that we get
  EACCES here, or if the file doesn't exist and we're allowed to know
  that, we'll get ENOENT".

  
  result with patch:

  $ sh -c /system/bin/vold
  sh: /system/bin/vold: can't execute: Permission denied

To manage notifications about this bug go to:
https://bugs.launchpad.net/mksh/+bug/1817789/+subscriptions

Reply via email to