Re: bad handling of error conditions in "type -P'
On 10/9/15 8:17 AM, Linda Walsh wrote: > > > There are several problems with how type -P returns errors. `type -P', and `type' in general, reflects what would happen when a name is used as a command. > 1) if a file isn't executable, type returns it anyway in >> ls -l /sbin/scat > -r--r--r-- 1 root root 245663 Nov 19 2013 /sbin/scat >> type -P scat > /sbin/scat Because, in the absence of any other executable with that name, bash will attempt to execute the first file it finds with that name in any directory in $PATH, even if it doesn't have execute permission. Bash has always done this, from the earliest pre-1.0 days. > > 2) if a file is inaccessible, type still returns it an answer for > the path of an executable named 'scat1': >> ls -l /sbin/scat1 > -- 1 root root 245663 Nov 19 2013 /sbin/scat1 >> type -P scat1 > /sbin/scat1 For the same reason. > > 3) bash "knows better" because it doesn't do this in "posix mode" Yeah. When in Posix mode, the behavior of returning a file that doesn't have execute permission is inhibited. I changed this in bash-3.1 for compatibility with other shells claiming Posix conformance. Posix doesn't exactly address this, but other Posix shells behaved differently. It doesn't change the historical bash default behavior. > > 4) if it doesn't find the file it returns a status > code meaning 'EPERM' rather than 'ENOENT'. > (ENOENT No such file or directory (POSIX.1)) > This is true in normal mode or posix mode. This doesn't make any sense. If the file isn't present, type returns 1 (failure). If it's found, but doesn't have the right permissions to execute -- and no other file with that name with appropriate permissions is found -- bash will try and execute it, so `type -P' returns a status that indicates that it will attempt execution. > > 5) if the file is executable for root, it is still return as > an answer for 'type -P': >> ls -l /sbin/scat2 > ---x-- 1 root root 245663 Nov 19 2013 /sbin/scat2 >> type -P scat2 > /sbin/scat2 For the same reason as above. > 6) if bash is in posix mode it will find '/sbin/scat2' > only if the owner is root (good), BUT for a non-root > user, a return code of '1' is return whether it the > file exists or not. NOTE: by 'coincidence' on linux, > 1=EPERM, which would be correct for /sbin/scat2, but > it also returns '1' for the "ENOENT" case. `1' has no relationship to EPERM. And I don't think you meant to say `owner'. As I said above, Posix mode essentially adds a permissions check (using eaccess) to the last-ditch file found by the path search. If the file is found, but eaccess says you can't execute it, `type' returns 1. The exit status has no relationship to the particular errno value. > 7) if the file is NOT owned by root, type -P returns > the alien-owned file (this seems like it would be a security > risk -- but it is also in the kernel, so bash behaving > differently, though correct, would be inconsistent with > the insecure behavior of the kernel: >> ls -l /sbin/ucat2 > ---x--x--- 1 nobody nogroup 245663 Nov 19 2013 /sbin/ucat2 >> type -P ucat2 #(normal user) > # type -P ucat2 #(root user is unprotected) > /sbin/ucat2 Because root can execute any file on which any execute permission bit is set. This is how Unix works. (For simplicity, let's ignore mount options or ACLs.) > > Proposals: > 1) It seems the non-posix mode should parallel the posix mode in > this case. I disagree. The historical bash behavior will not change. > 2) type should return 'EPERM' if it finds an executable owned > by someone else that isn't allowed execution by the caller. > 3) if no file with any executable bits is set it should return > status 'ENOENT'. This is not the historical bash behavior, and I don't think this is sufficient to change it. > 4) Ideally root would not behave differently from the normal > user case, since ownership by a non-priviledged user might > indicate a security problem, HOWEVER, this should be brought > to the attention of the kernel folks for an explanation why > root can execute files owned by suspect users. Perhaps > Bash being different in this case would be a best course, > as it is doing a path seach, while in the kernel case, > it should only be allowed if an absolute path was given > (with no PATH search). What's a `suspect user'? Root can execute any file for which any execute bit is set. If the kernel says a file is executable when using eaccess(2), why does bash need to second-guess that? > I regard this as rather broken, as it gives useless, wrong > and insecure answers depending on the case. I also think > bash, having had it's behavior changed due to posix rules should > be using posix standard errno names, doesn't that make sense? What does errno have to do with it? What does `posix standard errno names' mean? You want an extra permissions check added to the last-ditch return from
bad handling of error conditions in "type -P'
I've run across several problems with how type -P returns errors. 1) if a file isn't executable, type returns it anyway in ls -l /sbin/scat -r--r--r-- 1 root root 245663 Nov 19 2013 /sbin/scat type -P scat /sbin/scat 2) if a file is inaccessible, type still returns it an answer for the path of an executable named 'scat1': ls -l /sbin/scat1 -- 1 root root 245663 Nov 19 2013 /sbin/scat1 type -P scat1 /sbin/scat1 3) bash "knows better" because it doesn't do this in "posix mode" 4) if it doesn't find the file it returns a status code meaning 'EPERM' rather than 'ENOENT'. (ENOENT No such file or directory (POSIX.1)) This is true in normal mode or posix mode. 5) if the file is executable for root, it is still return as an answer for 'type -P': ls -l /sbin/scat2 ---x-- 1 root root 245663 Nov 19 2013 /sbin/scat2 type -P scat2 /sbin/scat2 6) if bash is in posix mode it will find '/sbin/scat2' only if the owner is root (good), BUT for a non-root user, a return code of '1' is return whether it the file exists or not. NOTE: by 'coincidence' on linux, 1=EPERM, which would be correct for /sbin/scat2, but it also returns '1' for the "ENOENT" case. 7) if the file is NOT owned by root, type -P returns the alien-owned file (this seems like it would be a security risk -- but it is also in the kernel, so bash behaving differently, though correct, would be inconsistent with the insecure behavior of the kernel: ls -l /sbin/ucat2 ---x--x--- 1 nobody nogroup 245663 Nov 19 2013 /sbin/ucat2 type -P ucat2 #(normal user) # type -P ucat2 #(root user is unprotected) /sbin/ucat2 Proposals: 1) It seems the non-posix mode should parallel the posix mode in this case. 2) type should return 'EPERM' if it finds an executable owned by someone else that isn't allowed execution by the caller. 3) if no file with any executable bits is set it should return status 'ENOENT'. 4) Ideally root would not behave differently from the normal user case, since ownership by a non-priviledged user might indicate a security problem, HOWEVER, this should be brought to the attention of the kernel folks for an explanation why root can execute files owned by suspect users. Perhaps Bash being different in this case would be a best course, as it is doing a path seach, while in the kernel case, it should only be allowed if an absolute path was given (with no PATH search). I regard this as rather broken, as it gives useless, wrong and insecure answers depending on the case. I also think bash, having had it's behavior changed due to posix rules should be using posix standard errno names, doesn't that make sense? Cheers, L. Walsh
bad handling of error conditions in "type -P'
There are several problems with how type -P returns errors. 1) if a file isn't executable, type returns it anyway in ls -l /sbin/scat -r--r--r-- 1 root root 245663 Nov 19 2013 /sbin/scat type -P scat /sbin/scat 2) if a file is inaccessible, type still returns it an answer for the path of an executable named 'scat1': ls -l /sbin/scat1 -- 1 root root 245663 Nov 19 2013 /sbin/scat1 type -P scat1 /sbin/scat1 3) bash "knows better" because it doesn't do this in "posix mode" 4) if it doesn't find the file it returns a status code meaning 'EPERM' rather than 'ENOENT'. (ENOENT No such file or directory (POSIX.1)) This is true in normal mode or posix mode. 5) if the file is executable for root, it is still return as an answer for 'type -P': ls -l /sbin/scat2 ---x-- 1 root root 245663 Nov 19 2013 /sbin/scat2 type -P scat2 /sbin/scat2 6) if bash is in posix mode it will find '/sbin/scat2' only if the owner is root (good), BUT for a non-root user, a return code of '1' is return whether it the file exists or not. NOTE: by 'coincidence' on linux, 1=EPERM, which would be correct for /sbin/scat2, but it also returns '1' for the "ENOENT" case. 7) if the file is NOT owned by root, type -P returns the alien-owned file (this seems like it would be a security risk -- but it is also in the kernel, so bash behaving differently, though correct, would be inconsistent with the insecure behavior of the kernel: ls -l /sbin/ucat2 ---x--x--- 1 nobody nogroup 245663 Nov 19 2013 /sbin/ucat2 type -P ucat2 #(normal user) # type -P ucat2 #(root user is unprotected) /sbin/ucat2 Proposals: 1) It seems the non-posix mode should parallel the posix mode in this case. 2) type should return 'EPERM' if it finds an executable owned by someone else that isn't allowed execution by the caller. 3) if no file with any executable bits is set it should return status 'ENOENT'. 4) Ideally root would not behave differently from the normal user case, since ownership by a non-priviledged user might indicate a security problem, HOWEVER, this should be brought to the attention of the kernel folks for an explanation why root can execute files owned by suspect users. Perhaps Bash being different in this case would be a best course, as it is doing a path seach, while in the kernel case, it should only be allowed if an absolute path was given (with no PATH search). I regard this as rather broken, as it gives useless, wrong and insecure answers depending on the case. I also think bash, having had it's behavior changed due to posix rules should be using posix standard errno names, doesn't that make sense? Cheers, L. Walsh