retitle 640334 [kfreebsd] dash: faccessat implementation of "test -x" always 
returns true for user root
tags 640334 + upstream patch
quit

Hi Christoph,

Christoph Egger wrote:

>   dash relies, for it's test builtin that faccessat returns useable
> values for X_OK when called from the root user. Unfortunately that's not
> true on kfreebsd (and seemingly not required by POSIX, see
> #640325).

Thanks for reporting it.  The rationale to the description of access()
in POSIX says:

        Historical implementations of access() do not test file access
        correctly when the process real user ID is superuser. In
        particular, they always return zero when testing execute
        permissions with regard to whether the file is executable.
[...]
        New implementations are discouraged from returning X_OK unless
        at least one execution permission bit is set.

In other words, this weird part of POSIX is meant as a historical
exception, not a good behavior.

In glibc-bsd, I think it was just an oversight --- access()
implemented the expected X_OK semantics already, as did faccessat()
when used with a sufficiently old kernel.  Petr fixed faccessat()
in the development repository just now.

All that said, for the sake of smooth upgrades and to support the
aforementioned historical implementations (do they exist for
faccessat?), dash should probably use a workaround.  How about this?

Signed-off-by: Jonathan Nieder <jrnie...@gmail.com>
---
 src/bltin/test.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/src/bltin/test.c b/src/bltin/test.c
index 90135e14..1093b59f 100644
--- a/src/bltin/test.c
+++ b/src/bltin/test.c
@@ -485,8 +485,19 @@ equalf (const char *f1, const char *f2)
 }
 
 #ifdef HAVE_FACCESSAT
+static int has_exec_bit_set(const char *path)
+{
+       struct stat64 st;
+
+       if (stat64(path, &st))
+               return 0;
+       return st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH);
+}
+
 static int test_file_access(const char *path, int mode)
 {
+       if (mode == X_OK && geteuid() == 0 && !has_exec_bit_set(path))
+               return 0;
        return !faccessat(AT_FDCWD, path, mode, AT_EACCESS);
 }
 #else  /* HAVE_FACCESSAT */
-- 
1.7.6




-- 
To UNSUBSCRIBE, email to debian-bugs-rc-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to