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

.Net Core FSI causes security exception when attempting to executing a PInvoke call from fsx scripts #6544

Closed
patrickallensimpson opened this issue Apr 15, 2019 · 3 comments
Milestone

Comments

@patrickallensimpson
Copy link

Don Syme asked me to move this bug from fsharp/fsharp issue 886 to here. I describe a failure mode where F# interactive running under .Net Core won't generate correct PInvoke calls in your scripts. It was determined by @jkotas here and @KevinRansom here that the issue was related to originally missing functionality in .Net Core's Reflection.Emit.TypeBuilder that is now present in .Net Core 3.0.

Considering that we now have F# 4.6 FSI as a preview dotnet command dotnet fsi inside the .Net Core 3.0 preview 3 this needs to get fixed otherwise any existing scripts using PInvoke will not work reporting a rather esoteric error message. This is still an issue under 3.0.100-preview3-010431 running Microsoft (R) F# Interactive version 10.4.0 for F# 4.6

Here is the original issue:

When running the .Net Core version of the F# Interactive Service we get a security exception on any invocation of a PInvoke call that was generated in the script itself.

  1. Start .Net Core version of fsi.exe
dotnet 'C:\Program Files\dotnet\sdk\3.0.100-preview-009812\FSharp\fsi.exe'
  1. Enter the following script:
open System.Runtime.InteropServices
[<DllImport("kernel32")>]
extern int GetLastError()

GetLastError()

  1. You'll see the following exception:
System.Security.SecurityException: ECall methods must be packaged into a system module.
   at <StartupCode$FSI_0012>.$FSI_0012.main@()
Stopped due to error

On .Net Framework fsi this will execute and return the last error this is just the simplest test case I could think of.

I investigated and this is due to a check in ecall.cpp:346 inside the coreclr project.


    if (!pMD->GetModule()->IsSystem())
        COMPlusThrow(kSecurityException, BFA_ECALLS_MUST_BE_IN_SYS_MOD);


They perform a check on the incoming module to see if it is a system module (My guess is this means it's loaded from disk?) In any case if it is not then they throw this error. This means any scripts that were using PInvoke to call win32 services or other C api's CAN NOT work on the CoreCLR fsi version.

I've confirmed this is the case with .Net Core 2.0, 2.1, 2.2 and 3.0 preview at the exact same line number.

It there something that can be done to let the CoreCLR system know that the dynamically generated FSI assemblies are ok as far as this check is concerned?

Thanks,
-Patrick Simpson

DotNetFSISecurityFailureTest.zip

@patrickallensimpson
Copy link
Author

I'd fix this myself but I need guidance on the appropriate way we should special case this for .Net Core 3 builds in the project. My understanding of the issue is that when compiling under .Net Core 3 we simply need to remove the #if and keep the containing code that surrounds lines here:
https://github.com/Microsoft/visualfsharp/blob/5cf2d974241efb1bfa525cb636d392960ce1f0b7/src/absil/ilreflect.fs#L1515-L1541

Thanks,
-Patrick

@matthid
Copy link
Contributor

matthid commented Apr 15, 2019

@patrickallensimpson It looks like @KevinRansom is already working on it in #6542

@patrickallensimpson
Copy link
Author

I just commented on that pull request, I'm very happy about this new fix!

-Patrick

@cartermp cartermp added this to the Core 3.0 milestone Apr 15, 2019
@cartermp cartermp modified the milestones: Core 3.0, 16.1 Apr 16, 2019
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

3 participants