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

dotnet exec current folder issue #28315

Open
bucurb opened this issue Oct 4, 2022 · 6 comments
Open

dotnet exec current folder issue #28315

bucurb opened this issue Oct 4, 2022 · 6 comments
Assignees
Milestone

Comments

@bucurb
Copy link

bucurb commented Oct 4, 2022

I'm building a .net 6 console application that needs to p/Invoke into a native library. The native library lives in the same folder as my console application and so I have marked-up my native dll APIs with [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)].

The output of my .net application has two files: MyConsoleApp.exe, as well as MyConsoleApp.dll. My expectation is that I can run either of those and get an identical behaviour in terms of how my native dll is loaded. However, that is not the case.

If I run MyConsoleApp.exe from a command prompt with the current directory set to where the executable is, everything works as expected. If I instead run dotnet exec MyConsoleApp.dll, from the same command prompt as above, I get a DllNotFound exception for my native dll. Using procmon it seems that the current directory for the case where I'm running through dotnet is the one where dotnet lives, and the folder where my app lives is not among the searched locations.

Is there a way to tell dotnet exec what the current folder should be? I don't want to change my DefaultDllImportSearchPaths to Assembly because that seems to be considered a vulnerability, and I'd also like to continue running my app through dotnet.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-NetSDK untriaged Request triage from a team member labels Oct 4, 2022
@KalleOlaviNiemitalo
Copy link

When your Platform Invoke method has [DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)], the current directory does not affect the DLL search anyway.

In principle, you could use NativeLibrary.SetDllImportResolver to set a resolver that recognizes the DLL name, constructs the correct path, and calls NativeLibrary.Load. However, I doubt this would be any more secure than e.g. [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.ApplicationDirectory)], as both approaches trust the native library if it has the correct name and is in the same directory as MyConsoleApp.dll. (In contrast, [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] without other flags means the same as [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory | DllImportSearchPath.LegacyBehavior)] and searches many more directories.)

Related reading: 2019 year-end link clearance: The different kinds of DLL planting - The Old New Thing

@bucurb
Copy link
Author

bucurb commented Oct 4, 2022

Looking at the docs for SafeDirectories it says: Include the application directory, the %WinDir%\System32 directory, and user directories in the DLL search path. My understanding of the application directory is it's where MyConsoleApp.exe lives, and that is consistent with the fact that MyConsoleApp.exe can find the native dll in the same folder with no additional code. My issue is when running through dotnet the application directory becomes dotnet's directory, which seems weird, as I invoked dotnet to exec something. Additionally dotnet test seems to correctly find that same native dll with no additional changes needed, which is somewhat inconsistent.

@marcpopMSFT marcpopMSFT self-assigned this Oct 11, 2022
@dfields-msft
Copy link

dfields-msft commented Nov 16, 2022

Similar to dotnet/runtime#11540 I observe the same problem but with dotnet test on Linux. @marcpopMSFT are you looking into addressing both cases, or only the dotnet exec on Windows case?

@marcpopMSFT
Copy link
Member

To clarify, I only self-assigned for triage. SDK gets a lot of incoming so we assign out to team members and leave them labeled untriaged.

@marcpopMSFT
Copy link
Member

@elinor-fung @vitek-karas as this seems to be a question about the working directory of the host when launching an application.

@marcpopMSFT marcpopMSFT added this to the Discussion milestone Nov 21, 2022
@marcpopMSFT marcpopMSFT removed the untriaged Request triage from a team member label Nov 21, 2022
@elinor-fung
Copy link
Member

DllImportSearchPath (with the exception of AssemblyDirectory) is a direct mapping to the Windows LOAD_LIBRARY_* flags. The 'application directory' is in reference to the application from the OS perspective - so the actual process executable dotnet when running dotnet MyConsoleApp.dll.

Additionally dotnet test seems to correctly find that same native dll with no additional changes needed, which is somewhat inconsistent.

This is likely because dotnet test involves a couple levels of indirection. On Windows, what ends up running your test is a testhost.exe, which is copied next to your managed assembly, so the application directory (the testhost.exe directory) has your native library.

Anything done to change what is considered the application directory (such that it doesn't match the OS platform definition) would be the same, from a security perspective, as if you were to take the options @KalleOlaviNiemitalo mentioned.

cc @AaronRobinsonMSFT @jkoritzinsky

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

No branches or pull requests

5 participants