access(2) shouldn't be used with test(1)
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)
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)
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)
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
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)
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)
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)
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)
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)
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)
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
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
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
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/