access(2) shouldn't be used with test(1)

2010-07-20 Thread Garrett Cooper
According to the POSIX spec, using access(2) is implementation
dependent when running as superuser [1]. FreeBSD intentionally returns
true whenever euid/uid = 0 [2]. FreeBSD's /bin/sh doesn't have this
`issue' with test(1). Example:

$ ls -l typescript
-rw-r--r--  1 gcooper  gcooper  37875 Jul 12 22:19 typescript
$ sudo sh -c 'test -x typescript; echo $?'
1
$ sudo bash -c 'test -x typescript; echo $?'
0

Code should be added to detect the mode via stat(2), instead of
access(2) (the FreeBSD manpage also notes security issues with race
conditions when using access(2), so access(2) use is discouraged).
If I can get the details for grabbing bash from cvs/svn/whatever,
I'll whip up a patch for this.
Thanks,
-Garrett

[1] http://www.opengroup.org/onlinepubs/95399/functions/access.html
- see RATIONALE.
[2] http://www.freebsd.org/cgi/man.cgi?query=access



Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Garrett Cooper
On Tue, Jul 20, 2010 at 11:00 AM, Garrett Cooper yaneg...@gmail.com wrote:
    According to the POSIX spec, using access(2) is implementation
 dependent when running as superuser [1]. FreeBSD intentionally returns
 true whenever euid/uid = 0 [2]. FreeBSD's /bin/sh doesn't have this
 `issue' with test(1). Example:

 $ ls -l typescript
 -rw-r--r--  1 gcooper  gcooper  37875 Jul 12 22:19 typescript
 $ sudo sh -c 'test -x typescript; echo $?'
 1
 $ sudo bash -c 'test -x typescript; echo $?'
 0

    Code should be added to detect the mode via stat(2), instead of
 access(2) (the FreeBSD manpage also notes security issues with race
 conditions when using access(2), so access(2) use is discouraged).
    If I can get the details for grabbing bash from cvs/svn/whatever,
 I'll whip up a patch for this.

 [1] http://www.opengroup.org/onlinepubs/95399/functions/access.html
 - see RATIONALE.
 [2] http://www.freebsd.org/cgi/man.cgi?query=access

Oh, and BTW... here's the version of bash I'm using:

$ bash --version
GNU bash, version 4.1.7(0)-release (amd64-portbld-freebsd9.0)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later http://gnu.org/licenses/gpl.html

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Thanks,
-Garrett



Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Eric Blake
On 07/20/2010 12:00 PM, Garrett Cooper wrote:
 According to the POSIX spec, using access(2) is implementation
 dependent when running as superuser [1].

But as long as the answer is correct, then the access(2) family of calls
is the right thing to use.

 FreeBSD intentionally returns
 true whenever euid/uid = 0 [2].

Remember, POSIX allows an OS where the superuser CAN read/write/execute
any file it wants, regardless of whether there are explicit permission
bits set in the stat() results.  If FreeBSD is one of the OS's where the
superuser can execute a file that doesn't have any x bits set in stat(),
then that's one of the privileges of being the superuser, and their
implementation of access(X_OK) always returning true is correct.  On the
other hand, POSIX suggests that a better implementation is that the
superuser should only be able to arbitrarily execute files if the stat()
and ACL bits allow execute permissions to at least one entity (whether
or not that entity is also the superuser), in which case, blindly
returning true for access(X_OK) for uid 0 on a file with no other
execute permissions would be a bug in access().

Also, remember that access(2) takes into account ACLs, but stat() does
not.  POSIX requires that 'test -x file' succeed for a non-superuser uid
that does not own a file with 700 stat() bits, but where the file also
has an ACL granting execute rights to that uid.

 FreeBSD's /bin/sh doesn't have this
 `issue' with test(1). Example:

I argue that either FreeBSD's /bin/sh or their access(2) is buggy; the
question now is which one.

 
 $ ls -l typescript
 -rw-r--r--  1 gcooper  gcooper  37875 Jul 12 22:19 typescript
 $ sudo sh -c 'test -x typescript; echo $?'
 1
 $ sudo bash -c 'test -x typescript; echo $?'
 0

Try:

echo echo hi  foo
chmod 644 foo
sudo sh -c './foo'

If it prints hi, then bash is correct as-is, because FreeBSD falls into
the category of OSs that allow arbitrary superuser execution regardless
of whether any other entity has execute rights, which is allowed but not
recommended by POSIX.  On the other hand, if the superuser fails to
execute ./foo but access(2) says it can, then FreeBSD's access(2) is
broken, at which point bash should be working around the broken
access().  But I still argue that bash is correct for using the
access(2) family (actually, bash should be using faccessat(,AT_EACCESS)
[required by POSIX 2008] or the non-portable alternatives eaccess() or
euidaccess() in preference to access(2), because you want to know if the
file is executable for the effective id).

(I don't have root access to a FreeBSD machine at the moment, or I would
try this myself).

 Code should be added to detect the mode via stat(2), instead of
 access(2) (the FreeBSD manpage also notes security issues with race
 conditions when using access(2), so access(2) use is discouraged).
 If I can get the details for grabbing bash from cvs/svn/whatever,

Bash (unfortunately) is not available in a public repository.  Provide
any patch against the 4.1 sources instead; that's the latest publicly
available source.  But be aware that bash already has fallback code to
use stat() on systems with known-buggy access(2), and that your solution
must NOT interfere with correct test behavior on systems with ACLs (that
is, relying _solely_ on stat() is almost guaranteed to be wrong on any
platform with alternate access controls).

Meanwhile, if bash ever uses access() instead of faccessat(,AT_EACCESS)
on a POSIX 2008 platform, then that would be a bug worth fixing.

-- 
Eric Blake   ebl...@redhat.com+1-801-349-2682
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Garrett Cooper
On Tue, Jul 20, 2010 at 11:28 AM, Eric Blake ebl...@redhat.com wrote:
 On 07/20/2010 12:00 PM, Garrett Cooper wrote:
     According to the POSIX spec, using access(2) is implementation
 dependent when running as superuser [1].

 But as long as the answer is correct, then the access(2) family of calls
 is the right thing to use.

 FreeBSD intentionally returns
 true whenever euid/uid = 0 [2].

 Remember, POSIX allows an OS where the superuser CAN read/write/execute
 any file it wants, regardless of whether there are explicit permission
 bits set in the stat() results.  If FreeBSD is one of the OS's where the
 superuser can execute a file that doesn't have any x bits set in stat(),
 then that's one of the privileges of being the superuser, and their
 implementation of access(X_OK) always returning true is correct.  On the
 other hand, POSIX suggests that a better implementation is that the
 superuser should only be able to arbitrarily execute files if the stat()
 and ACL bits allow execute permissions to at least one entity (whether
 or not that entity is also the superuser), in which case, blindly
 returning true for access(X_OK) for uid 0 on a file with no other
 execute permissions would be a bug in access().

Yeah, the manpage gives access(2) the `license to lie':

 Even if a process's real or effective user has appropriate privileges and
 indicates success for X_OK, the file may not actually have execute per-
 mission bits set.  Likewise for R_OK and W_OK.

 Also, remember that access(2) takes into account ACLs, but stat() does
 not.  POSIX requires that 'test -x file' succeed for a non-superuser uid
 that does not own a file with 700 stat() bits, but where the file also
 has an ACL granting execute rights to that uid.

Hmmm...

 FreeBSD's /bin/sh doesn't have this
 `issue' with test(1). Example:

 I argue that either FreeBSD's /bin/sh or their access(2) is buggy; the
 question now is which one.

Technically it's test(1) that's reporting the mode info, and what they
do is use eaccess(2) instead of access(2).

 $ ls -l typescript
 -rw-r--r--  1 gcooper  gcooper  37875 Jul 12 22:19 typescript
 $ sudo sh -c 'test -x typescript; echo $?'
 1
 $ sudo bash -c 'test -x typescript; echo $?'
 0

 Try:

 echo echo hi  foo
 chmod 644 foo
 sudo sh -c './foo'

 If it prints hi, then bash is correct as-is, because FreeBSD falls into
 the category of OSs that allow arbitrary superuser execution regardless
 of whether any other entity has execute rights, which is allowed but not
 recommended by POSIX.  On the other hand, if the superuser fails to
 execute ./foo but access(2) says it can, then FreeBSD's access(2) is
 broken, at which point bash should be working around the broken
 access().  But I still argue that bash is correct for using the
 access(2) family (actually, bash should be using faccessat(,AT_EACCESS)
 [required by POSIX 2008] or the non-portable alternatives eaccess() or
 euidaccess() in preference to access(2), because you want to know if the
 file is executable for the effective id).

Yeah, it fails:

$ echo echo hi  foo
$ chmod 644 foo
$ sudo sh -c './foo'
./foo: Permission denied

     Code should be added to detect the mode via stat(2), instead of
 access(2) (the FreeBSD manpage also notes security issues with race
 conditions when using access(2), so access(2) use is discouraged).
     If I can get the details for grabbing bash from cvs/svn/whatever,

 Bash (unfortunately) is not available in a public repository.  Provide
 any patch against the 4.1 sources instead; that's the latest publicly
 available source.  But be aware that bash already has fallback code to
 use stat() on systems with known-buggy access(2), and that your solution
 must NOT interfere with correct test behavior on systems with ACLs (that
 is, relying _solely_ on stat() is almost guaranteed to be wrong on any
 platform with alternate access controls).

 Meanwhile, if bash ever uses access() instead of faccessat(,AT_EACCESS)
 on a POSIX 2008 platform, then that would be a bug worth fixing.

I see the quandary now (thanks for the clarification). FreeBSD
supports POSIX ACLs and MAC, so yes, it does appear that access(2) (or
rather the underlying callers for it) should be fixed. I'll have to
check faccessat(2) to see whether or not it's buggy by writing
unittests for it (*sigh*). At least I'll integrate them into the
open_posix_testsuite in ltp, which means they'll be available for
Linux as well...

Thanks,
-Garrett



Re: function grammar

2010-07-20 Thread Linda Walsh



Ken Irving wrote:

So maybe the declaration could be fixed to show that, e.g., as either of:

name () compound-command [redirection]
function name [()] compound-command [redirection]

I can't see how to put that in one construct...

BNF would use:

 'function' NAME  |  NAME '()'  compound-command [redirection]

(ignoring that it would probably also specify SPACE where needed

maybe using bash syntax:

+(function _name_ | _name_ () ) compound-command [redirection]




BUG: grammar handler needs to be fixed to recognize Bash syntax.... (was Re: function grammar)

2010-07-20 Thread Linda Walsh

The following function is legal syntax, but yields an error:

function good_dir [[ -n $1  -d $1  -r $1   -x $1 ]]

bash: syntax error near unexpected token `[['


To which Andreas comments that it's a grammar bug:


Andreas Schwab wrote:

Bernd Eggink mono...@sudrala.de writes:


If the function reserved word is supplied,  the  parentheses  are
optional.


While the grammer has the right rules for this the handling inside of
special_case_tokens isn't right up to it, it only recognizes '{'
following 'function WORD'.

Andreas.





Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Linda Walsh

What are you saying it should return, because I get correct results
on linux:

sudo sh -c 'test -x start_trans; echo $?'
1
sudo bash -c 'test -x start_trans; echo $?'  
1


Are you saying that access on BSD, when
passed (filename X_OK) returns true for superuser even
when the file isn't executable?

Sounds like a bug to me   if a file isn't executable, I don't care
how super you are -- permission won't make a text file executable!
;-)

Or isn't that what BSD is sorta saying?




Garrett Cooper wrote:

According to the POSIX spec, using access(2) is implementation
dependent when running as superuser [1]. FreeBSD intentionally returns
true whenever euid/uid = 0 [2]. FreeBSD's /bin/sh doesn't have this
`issue' with test(1). Example:

$ ls -l typescript
-rw-r--r--  1 gcooper  gcooper  37875 Jul 12 22:19 typescript
$ sudo sh -c 'test -x typescript; echo $?'
1
$ sudo bash -c 'test -x typescript; echo $?'
0

Code should be added to detect the mode via stat(2), instead of
access(2) (the FreeBSD manpage also notes security issues with race
conditions when using access(2), so access(2) use is discouraged).
If I can get the details for grabbing bash from cvs/svn/whatever,
I'll whip up a patch for this.
Thanks,
-Garrett

[1] http://www.opengroup.org/onlinepubs/95399/functions/access.html
- see RATIONALE.
[2] http://www.freebsd.org/cgi/man.cgi?query=access





Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Garrett Cooper
On Tue, Jul 20, 2010 at 2:18 PM, Linda Walsh b...@tlinx.org wrote:
 What are you saying it should return, because I get correct results
 on linux:

 sudo sh -c 'test -x start_trans; echo $?'
 1
 sudo bash -c 'test -x start_trans; echo $?'  1

 Are you saying that access on BSD, when
 passed (filename X_OK) returns true for superuser even
 when the file isn't executable?

Correct.

 Sounds like a bug to me   if a file isn't executable, I don't care
 how super you are -- permission won't make a text file executable!
 ;-)

Yes, but POSIX says that it's allowed to be broken based on past
behavior, and FreeBSD just says don't use access, act on the file,
which means that access on FreeBSD is only really useful for F_OK, but
I can get that from open/fstat/whatever.

Not having correct data via test(1) renders the utility useless in
many scenarios, which isn't desirable... I've found other issues with
other implementations of access that need to be resolved as well. This
is just one of the problem applications / languages that I'm
addressing that I care about.

Thanks,
-Garrett

 Garrett Cooper wrote:

    According to the POSIX spec, using access(2) is implementation
 dependent when running as superuser [1]. FreeBSD intentionally returns
 true whenever euid/uid = 0 [2]. FreeBSD's /bin/sh doesn't have this
 `issue' with test(1). Example:

 $ ls -l typescript
 -rw-r--r--  1 gcooper  gcooper  37875 Jul 12 22:19 typescript
 $ sudo sh -c 'test -x typescript; echo $?'
 1
 $ sudo bash -c 'test -x typescript; echo $?'
 0

    Code should be added to detect the mode via stat(2), instead of
 access(2) (the FreeBSD manpage also notes security issues with race
 conditions when using access(2), so access(2) use is discouraged).
    If I can get the details for grabbing bash from cvs/svn/whatever,
 I'll whip up a patch for this.
 Thanks,
 -Garrett

 [1] http://www.opengroup.org/onlinepubs/95399/functions/access.html
 - see RATIONALE.
 [2] http://www.freebsd.org/cgi/man.cgi?query=access





Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Eric Blake
On 07/20/2010 03:22 PM, Garrett Cooper wrote:
 Correct.
 
 Sounds like a bug to me   if a file isn't executable, I don't care
 how super you are -- permission won't make a text file executable!
 ;-)
 
 Yes, but POSIX says that it's allowed to be broken based on past
 behavior, and FreeBSD just says don't use access, act on the file,
 which means that access on FreeBSD is only really useful for F_OK, but
 I can get that from open/fstat/whatever.

POSIX says:
http://www.opengroup.org/onlinepubs/9699919799/functions/access.html

Normative:
If any access permissions are checked, each shall be checked
individually, as described in XBD File Access Permissions , except that
where that description refers to execute permission for a process with
appropriate privileges, an implementation may indicate success for X_OK
even if execute permission is not granted to any user.

Descriptive:
In early proposals, some inadequacies in the access() function led to
the creation of an eaccess() function because:

   1.

  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 without regard
to whether the file is executable.
   2.

  The superuser has complete access to all files on a system. As a
consequence, programs started by the superuser and switched to the
effective user ID with lesser privileges cannot use access() to test
their file access permissions.

However, the historical model of eaccess() does not resolve problem (1),
so this volume of POSIX.1-2008 now allows access() to behave in the
desired way because several implementations have corrected the problem.
It was also argued that problem (2) is more easily solved by using
open(), chdir(), or one of the exec functions as appropriate and
responding to the error, rather than creating a new function that would
not be as reliable. Therefore, eaccess() is not included in this volume
of POSIX.1-2008.

The sentence concerning appropriate privileges and execute permission
bits reflects the two possibilities implemented by historical
implementations when checking superuser access for X_OK.

New implementations are discouraged from returning X_OK unless at least
one execution permission bit is set.


Thus, access(2) _may_ say X_OK for the superuser, regardless of whether
stat()/ACL say anyone can execute, based on historical behavior,
although this historical behavior is frowned upon.  However, nowhere
does POSIX allow R_OK or W_OK to return true if stat()/ACL don't grant
read/write privileges to someone, and as long as access() is doing the
permission check for rw, it shouldn't be too hard to patch it to also do
the permission check for x.

So, if FreeBSD is poor QoI because of POSIX, it had better only be for
'test -x' and not for 'test -r' or 'test -w'.

Meanwhile, POSIX says that access(a,b) and faccessat(AT_FDCWD,a,b,0)
must be identical in behavior.

-- 
Eric Blake   ebl...@redhat.com+1-801-349-2682
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Chet Ramey
On 7/20/10 2:00 PM, Garrett Cooper wrote:
 According to the POSIX spec, using access(2) is implementation
 dependent when running as superuser [1]. FreeBSD intentionally returns
 true whenever euid/uid = 0 [2]. FreeBSD's /bin/sh doesn't have this
 `issue' with test(1). Example:

Bash-4.1 doesn't use access for `test -x' (or -e, -r, or -w, for that
matter) on FreeBSD.  If eaccess is available and configure detects its
presence, bash uses that, otherwise it either uses access or checks the
permissions returned by stat.

Bash-4.2 will prefer the use of faccessat if available, falling back to
eaccess and then access/stat.  On FreeBSD, bash-4.2 will use stat to
verify X_OK when euid == 0 even if eaccess returns true, since eaccess
lies also (the FreeBSD test does the same thing).

The relevant code is in lib/sh/eaccess.c:sh_eaccess().  This was
discussed extensively back in March.

Chet
-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: access(2) shouldn't be used with test(1)

2010-07-20 Thread Garrett Cooper
On Tue, Jul 20, 2010 at 5:16 PM, Chet Ramey chet.ra...@case.edu wrote:
 On 7/20/10 2:00 PM, Garrett Cooper wrote:
     According to the POSIX spec, using access(2) is implementation
 dependent when running as superuser [1]. FreeBSD intentionally returns
 true whenever euid/uid = 0 [2]. FreeBSD's /bin/sh doesn't have this
 `issue' with test(1). Example:

 Bash-4.1 doesn't use access for `test -x' (or -e, -r, or -w, for that
 matter) on FreeBSD.  If eaccess is available and configure detects its
 presence, bash uses that, otherwise it either uses access or checks the
 permissions returned by stat.

 Bash-4.2 will prefer the use of faccessat if available, falling back to
 eaccess and then access/stat.  On FreeBSD, bash-4.2 will use stat to
 verify X_OK when euid == 0 even if eaccess returns true, since eaccess
 lies also (the FreeBSD test does the same thing).

 The relevant code is in lib/sh/eaccess.c:sh_eaccess().  This was
 discussed extensively back in March.

I see what you mean.. I need to do more digging because according to
the config logs, eaccess(2) is used, and when I put an #error in the
relevant block, it pops up with:

findcmd.c:98:2: error: #error !eaccess!
*** Error code 1

Stop in /usr/ports/shells/bash/work/bash-4.1.
*** Error code 1

:(...

Thanks,
-Garrett



Re: function grammar

2010-07-20 Thread Chet Ramey
 from man bash, to define a function use;
 
 function name compound-command
   OR
 name () compound-command
 
 right?
 
 And Compound Commands are:
 
   ( list)
{ list; )
   (( expression ))
   [[ expression ]]
 ...et al
 
 so why do I get a syntax error for
 
 function good_dir [[ -n $1  -d $1  -r $1   -x $1 ]]
 
 bash: syntax error near unexpected token `[['

Good catch.  This will be fixed in bash-4.2.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: function grammar

2010-07-20 Thread Chet Ramey
 I see this in bash(1):
 
 SHELL GRAMMAR
 ...
 Shell Function Definitions
 ...
 [ function ] name () compound-command [redirection]
 
 and do not see the version you show without the parens.

Read the text following the definition.  It says, in part:

If  the  function reserved word is supplied, the
parentheses are optional.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: function grammar

2010-07-20 Thread Chet Ramey
 So maybe the declaration could be fixed to show that, e.g., as either of:
 
 name () compound-command [redirection]
 function name [()] compound-command [redirection]

I think this is a great suggestion.

Chet

-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/