Skip to content
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

.dll files in path are surfacing as executable Linux-side #2515

Closed
mqudsi opened this issue Sep 23, 2017 · 12 comments
Closed

.dll files in path are surfacing as executable Linux-side #2515

mqudsi opened this issue Sep 23, 2017 · 12 comments
Labels

Comments

@mqudsi
Copy link

mqudsi commented Sep 23, 2017

Microsoft Windows [Version 10.0.16278.1000]

WSL's importing of the PATH environment variable from Windows is awesome because it lets one execute Windows commands by name and extension without needing to also specify the path, so +1 for that.

However, it seems that .dll dynamic library files are also being surfaced as executable to the Linux environment, which isn't ideal for a number of reasons. First and foremost, they're not. You can't execute them without a specific verb, and attempting to execute them is an error. Second, the fact that they're marked as executable means that command completion under Linux is broken, since the PATH namespace is now polluted with thousands of non-executable entries that make it impossible to autocomplete the name of a Windows or Linux executable.

Here's what happens when you try to execute a random DLL (it doesn't work, as is proper):

mqudsi@ZBook ~/r/f/tests> filemgmt.dll
/mnt/c/Windows/System32/filemgmt.dll: Invalid argument

However, this shouldn't be possible:

mqudsi@ZBook ~/r/f/tests> which filemgmt.dll
/mnt/c/Windows/System32/filemgmt.dll

since filemgmt.dll is not really an executable!

Here's the executable bit set on DLLs:

mqudsi@ZBook ~/r/f/tests> ls -ahl (which filemgmt.dll)
Permissions Size User Date Modified Name
.r-xr-xr-x  562k root 26 Aug  2:05  /mnt/c/Windows/System32/filemgmt.dll

Just like it is on EXEs:

mqudsi@ZBook ~/r/f/tests> ls -ahl (which bcdedit.exe)
Permissions Size User Date Modified Name
.r-xr-xr-x  457k root 26 Aug  2:05  /mnt/c/Windows/System32/bcdedit.exe

Obviously chmod is useless on Windows files, so it's not even possible to manually mark these as non-executable (even if permissions weren't an issue):

mqudsi@ZBook ~/r/f/tests> sudo chmod -x (which filemgmt.dll)
chmod: changing permissions of '/mnt/c/Windows/System32/filemgmt.dll': Permission denied

Was this an intentional feature or an oversight that can hopefully be fixed?

EDIT: .cpl files are also included. I think a whitelist comprising of .{exe,com,bat} is needed (am I missing any extensions?)

@therealkenc
Copy link
Collaborator

#2461

@mqudsi
Copy link
Author

mqudsi commented Sep 23, 2017

Thanks. My search terms were too technical (executable bit dll) to turn that up 🤣

@mqudsi
Copy link
Author

mqudsi commented Sep 23, 2017

Upon reviewing #2461, I don't think this is the same. That one is more of a general complaint about the side effects of the Windows PATH being merged with the Linux PATH environment variable, and includes the DLL issue as a side effect.

I have no qualms with the PATH merging, but this is a bug that I don't believe was present in Creators Update (where the PATH merging was first introduced). DLL files are not executable and shouldn't appear to be.

@therealkenc
Copy link
Collaborator

therealkenc commented Sep 23, 2017

First and foremost, they're not. You can't execute them without a specific verb, and attempting to execute them is an error.

No, dlls are executable. Check out /lib/x86_64-linux-gnu/ld-2.24.so and the rest on Real Linux™. That bit isn't there to make ls --color pretty or make tab completion function. It is there to indicate permission to map the x64 instructions in that file into memory and execute them.

Second, the fact that they're marked as executable means that command completion under Linux is broken

That's #2461. What's academically "broken" is that MSFT used /Windows/system32 as a dumping ground for 30 years, but there is no turning back the clock on that. Exclude them from the search:

export FIGNORE=".dll:.DLL"

If you had /lib/x86_64-linux-gnu/ in your $PATH you'd need to ignore *.so files just the same.

@mqudsi
Copy link
Author

mqudsi commented Sep 23, 2017

No dlls are executable. Check out /lib/x86_64-linux-gnu/ld-2.24.so and the rest on Real Linux™.

On real Linux:

mqudsi@debianvm:~$ uname -a
Linux debianvm 4.9.0-3-amd64 #1 SMP Debian 4.9.30-2+deb9u5 (2017-09-19) x86_64 GNU/Linux
mqudsi@debianvm:~$ ls -ahl /lib/x86_64-linux-gnu/libdl-2.24.so
-rw-r--r-- 1 root root 15K Jun 15 14:17 /lib/x86_64-linux-gnu/libdl-2.24.so
mqudsi@debianvm:~$ ls -ahl /lib/x86_64-linux-gnu/ld-2.24.so
-rwxr-xr-x 1 root root 150K Jun 15 14:17 /lib/x86_64-linux-gnu/ld-2.24.so
mqudsi@debianvm:~$ /lib/x86_64-linux-gnu/ld-2.24.so
Usage: ld.so [OPTION]... EXECUTABLE-FILE [ARGS-FOR-PROGRAM...]
You have invoked `ld.so', the helper program for shared library executables.
This program usually lives in the file `/lib/ld.so', and special directives
in executable files using ELF shared libraries tell the system's program
loader to load the helper program from this file.  This helper program loads
the shared libraries needed by the program executable, prepares the program
to run, and runs it.  You may invoke this helper program directly from the
command line to load and run an ELF executable file; this is like executing
that file itself, but always uses this helper program from the file you
specified, instead of the helper program file specified in the executable
file you run.  This is mostly of use for maintainers to test new versions
of this helper program; chances are you did not intend to run this program.

  --list                list all dependencies and how they are resolved
  --verify              verify that given object really is a dynamically linked
                        object we can handle
  --inhibit-cache       Do not use /etc/ld.so.cache
  --library-path PATH   use given PATH instead of content of the environment
                        variable LD_LIBRARY_PATH
  --inhibit-rpath LIST  ignore RUNPATH and RPATH information in object names
                        in LIST
  --audit LIST          use objects named in LIST as auditors
mqudsi@debianvm:~$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Debian GLIBC 2.24-11+deb9u1) stable release version 2.24, by Roland McGrath et al.
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 6.3.0 20170516.
Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.

Linux doesn't have a concept of extensions, and so there is no "dll file" vs "executable file" extension. Linux has plain old files that can have any name and any extension. And files can have their executable bit set (like ld-2.24.so above) or cleared (like libdl-2.24.so).

When attempting to complete a command, files with that executable bit are autocompleted:

mqudsi@debianvm:~$ /lib/x86_64-linux-gnu/<TAB>
ld-2.24.so            ld-linux-x86-64.so.2  libc-2.24.so          libc.so.6             libpthread-2.24.so    libpthread.so.0

And files without it are not. Attempting to execute a file that does not have an executable bit set is not possible, and therefore they do not show up in the list of completions.

#2461 says tab completion shouldn't include DLLs. I don't have a problem with tab completion including DLLs, just like I don't have a problem with tab completion include .so files when they're executable because that's what tab completion should do: list executable files. The bug here is that DLL files are marked as executable in the first place.

Basically, there's absolutely nothing wrong with the completions behavior. And there's nothing wrong with merging the Windows and Linux PATH environment variables. And there's even nothing wrong with having executable binaries and system dlls in the same folder (system32 and its ilk). The bug is that these DLL files are marked as executable when they're not.

@therealkenc
Copy link
Collaborator

therealkenc commented Sep 23, 2017

The bug is that these DLL files are marked as executable when they're not.

Sure they are...

dll-read-execute

If the beef here is really #81 #2421, well, yeah. That. But no behaviour has changed in this respect since Creator's Update, or for Samba users mounting Windows shares who have wanted it addressed for the last two and a half decades.

@mqudsi
Copy link
Author

mqudsi commented Sep 24, 2017

That would almost nullify my argument about WSL being wrong in setting the +x bit, good point.

However, I think it's quite clear that the executable ACL rule under Win32 has a very different meaning from the executable bit under Linux - the only similarity they share is that they both have the same name.

While +x/-x can be used to deny a user or group permission from executing a certain executable binary on Linux, it does not have that effect on library files (.so). On Windows, code from a DLL cannot be executed if the executable bit is not set and the DLL is set as the handler for an action (see IIS problems with DLLs missing the executable bit). On Linux, the executable bit is not needed for a .so to be used - only to be invoked directly as an executable.

So it would be a mistake to translate the win32 execute ACL to a Linux executable bit literally for DLL files (although it is correct for .exe files).

@therealkenc
Copy link
Collaborator

Linux doesn't have a concept of extensions, and so there is no "dll file" vs "executable file" extension.

Neither the Linux Kernel nor the NT Kernel have a concept of file extensions. It is a function of the shell (graphical or CLI), on both operating systems, equivalently.

What the shell does with a given string followed by a tab or enter (or mouse click) is entirely up to the shell. A shell like cmd.exe might look up the extension in the registry and decide what to do (as with .bat, .jpg, or .zip files). Or, in the case of the Cygwin bash shell on Windows, try to launch the file as a PE executable or shebang script, regardless of extension.

The dll extension is likewise not special. It could be .ocx, or .foo, or no extension at all.

On Windows, code from a DLL cannot be executed if the executable bit is not set and the DLL is set as the handler for an action (see IIS problems with DLLs missing the executable bit)

True (well, since around 1995 anyway; a.out shared libs required +x iirc. It's a function of the loader). But this difference is not related to the file's extension, on either kernel.

the executable ACL rule under Win32 has a very different meaning from the executable bit under Linux

No, it means the same thing. It means that the file possesses permission to allocate a new virtual address space and execute x86 code in that space. Nearly all files on Windows possess this permission, including .xml files in the system32 folder. Which is most unfortunate. But you can create a Windows PE binary with an .xml extension and run it just fine if your shell behaves that way, as is the case with Cygwin bash.

What you want is for WSL bash to behave more like cmd.exe, in that it should treat files with different extensions differently; acting on files with some extensions and not on others. Thankfully there is just such a feature in bash: the FINGNORE environment variable.

Fun fact: You can also go the other way with zsh and make your shell behave much like cmd.exe treats .zip extensions, with a suffix alias. Not all Windows shells are cmd.exe, just like not all WSL shells are bash.

@mqudsi
Copy link
Author

mqudsi commented Oct 2, 2017

I looked into adding FIGNORE and have opened an isssue for fish-shell (of which I am a core committer) to add some functionality to address this, but I have to point out that FIGNORE is not the solution to the problem described here. FIGNORE is a global "completions blocklist" for both head and tail autocompletions, whereas the issue here is head autocompletions only.

I've described the complications in greater detail there: fish-shell/fish-shell#4440

@therealkenc
Copy link
Collaborator

therealkenc commented Dec 3, 2017

At base the OP ask here was basically for a kernel layer heuristic to guess the executable disposition of files on DrvFs based on the file extension. Marking this issue as by-design because the current behaviour is intended and the thread ran its course a couple of months ago. 🌟 for the fish feature addition which is awesome.

@mqudsi
Copy link
Author

mqudsi commented Sep 21, 2018

fwiw, fish now has a basic heuristic to ignore treating *.dll files as executable under WSL, without needing to set FIGNORE.

Ref fish-shell/fish-shell@a9b582d from April 2018.

@michkot
Copy link

michkot commented Apr 9, 2020

This is closed, but for BASH you can use
EXECIGNORE=\*.dll
https://unix.stackexchange.com/questions/314631/hide-some-commands-from-bash-completion
https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html#:~:text=EXECIGNORE

(I am myself using MSYS2/MINGW64 and it for some reasons also treats .dlls as executables even though using some other heuristics for shebangs in scripts to be treated as executables)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants