New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fish Running as Root Fails to Suggest All Executable Commands in PATH #9699
Comments
Thank you for the detailed reproduction steps. I was able to reproduce this on Linux. This bisects to 0b55f08. The issue is replacing the call to |
Upon reflection I think 0b55f08 cannot be saved; for example it doesn't consider ACLs, plus the "Cache a list of our group memberships" is suspect as this may change during a shell session. We should not be second-guessing the kernel in this way. Reverted in c67d77f. Thank you for the outstanding bug report. cc @mqudsi ; I don't think 0b55f08 can be saved but maybe you have other ideas. |
Thanks for cc'ing me, @ridiculousfish
Yes, fair point. To be fair, no one has complained showing just how little real-world ACLs (continue to) get.
I remember considering that but in practice I believe group membership is always cached anyway until you log out and log back in. You can try it yourself by creating a group and giving it permissions to access a file/directory and then add yourself to the group. You won't have permissions until you log back in after being made a member of the group (or start a new session over ssh or on another tty, but those scenarios necessarily involve a new shell instance). I'll think over this and see if I can come up with any alternatives. The speed gain was very tangible, iirc. |
On our large, shared web environments we use ACLs extensively on the development tier, but almost exclusively for developer team file permissions within sites/hosted applications. I've honestly never run into an issue with fish not checking them during completions. |
There are two options that I can see. The first step in both cases is to just add an euid == 0 check to Given that code in question sonly suggests completions and doesn't affect any core functionality of the shell, I think that's the way to go. Just add the euid check and call it a day. Making 4 extra syscalls per potential file completion is expensive, especially with all the various security mitigations enabled that make the syscall boundary so much more expensive than it was. The second option is to add the the code back as-is, add the euid check as above, but additionally fall back to an actual Given that the |
I'm uncomfortable second-guessing the kernel here but I may be convinced. Still it's true that ACLs can also deny privileges, plus there may be other mechanisms in play such as sandboxing. But why is it four extra syscalls per file, and not just one? |
Best I can see is that we check waccess for the executables_only flag, and then again for the description. We can of course skip the latter by passing on the information that it's definitely executable. |
We have already run waccess with X_OK. We already *know* the file is executable. There is no reason to check again. Restores some of the speedup from the fast_waccess hack that was removed to fix fish-shell#9699.
We have already run waccess with X_OK. We already *know* the file is executable. There is no reason to check again. Restores some of the speedup from the fast_waccess hack that was removed to fix fish-shell#9699.
We have already run waccess with X_OK. We already *know* the file is executable. There is no reason to check again. Restores some of the speedup from the fast_waccess hack that was removed to fix #9699.
This checks the st_mode, which we need for other reasons. If it has the user, group *and* other exec bits set, i.e. a mode of 777 or 755 or similar, we assume it is executable and skip the waccess. This can have false-positives in some cases: 1. Capabilities 2. noexec filesystems 3. MAC like SELinux? Of these, capabilities also aren't reflected in access. On a debian system: ``` sudo capsh --drop=CAP_NET_RAW --shell=/usr/bin/fish -- -c 'test -x /usr/bin/ping && echo is executable; ping 8.8.8.8' ``` prints > is executable > exec: Failed to execute process '/usr/bin/ping': No permission. Either suid/sgid is forbidden or you lack capabilities. and strace confirms: > faccessat(AT_FDCWD, "/usr/bin/ping", X_OK) = 0 Bash fails similarly, except the error is a more generic "Operation not permitted" This leaves noexec filesystems and MAC. Since this is for completions, it's probably okay to possibly be wrong in those cases - if it is, the user can just try to execute and will get an error. Especially noexec filesystems shouldn't really be in completions because they'd have to be in $PATH. I have been unable to test MAC, and from a cursory googling those would mostly fail the `stat` already. This speeds up the common case by removing *most* access calls here - of the 2869 binaries in my $PATH, *1* (one) does not have a mode of 777, 555 or 755. It has 750. That means completing an empty command will have 2868 fewer access() calls. This regains all of the speed loss of fish-shell#9699.
In fish 3.6.1 as well as 3.3.1 at least, when running as root, commands (scripts or binaries) that are in $PATH, not owned by user root and/or group root, and are not world-executable will not be offered as completions, even though they are executable by root. This appears to affect Enterprise Linux (RHEL, CentOS, and Oracle Linux) 7 and 8, but does not affect macOS (any version). This happens whether ssh-ing to the Linux system via Apple Terminal or connecting directly to the machine's console. Running without third-party customizations does not affect the behavior.
How to reproduce:
testprog
(without typing it fully) and notice that fish will happilytestprog
(without typing it fully) and notice that fish will nottestprog
(notice that fish will color the command as valid once it's typed fully)testprog
(without typing it fully) and notice that fish will now suggest it, since it's in your command history, but will not tab-complete it.testprog
(without typing it fully) and notice that bash will happilytestprog
again. Note that fish will happily tab-complete it now.What should happen:
What does happen:
The text was updated successfully, but these errors were encountered: