1

I noticed that displaying a FolderBrowserDialog resulted in assemblies from any shell extensions loaded on my computer to be loaded into my application's AppDomain. This was causing problems for my application as an old version of a library my application uses was being loaded. I thought that a potential fix for this would be to open the FolderBrowserDialog in a different AppDomain and then unload the AppDomain to unload all of the shell extension assemblies loaded. For example:

public class Form1 : Form
{
    public Form1()
    {
        var setup = new AppDomainSetup()
        {
            ApplicationBase = System.Environment.CurrentDirectory,
            DisallowBindingRedirects = false,
            DisallowCodeDownload = true,
            ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile
        };

        var ad = AppDomain.CreateDomain("FolderBrowser", null, setup);
        var type = typeof(MyFolderBrowserDialog);
        var diag = (MyFolderBrowserDialog)ad.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
        diag.ShowDialog();
        AppDomain.Unload(ad);
    }
}

public class MyFolderBrowserDialog : MarshalByRefObject
{
    public DialogResult ShowDialog()
    {
        using (var diag = new FolderBrowserDialog())
        {
            return diag.ShowDialog();
        }
    }
}

This didn't work though. The shell extension assemblies are still loaded into the application's normal AppDomain and weren't loaded into the new AppDomain as I'd expected would happen. As a test I created my own class which calls the native SHBrowseForFolder function in Shell32.dll and found that making that call was what was causing the assemblies to be loaded.

So if sandboxing with AppDomains only works with managed code, how do you sandbox unmanaged code called with P/Invoke? I could see this as being a potential security issue if you are running untrusted code or at the very least a reliability issue as there is no way for you to know what assemblies might be loaded on a customer's computer just by opening a save or browse dialog.

Community
  • 1
  • 1
kjbartel
  • 10,381
  • 7
  • 45
  • 66
  • 2
    Poorly written shell extensions are a problem for everyone, not just managed code applications. Unfortunately, short of finding a time machine and fundamentally changing this extension point so that it doesn't let shell extensions run in-process at all, there's no real fix for this. – Damien_The_Unbeliever May 13 '14 at 06:53
  • Well, if something is *untrusted*, it means you don't have security reliability part of managed code. AppDomain is a managed sandbox. – Matías Fidemraizer May 13 '14 at 06:53
  • 1
    @MatíasFidemraizer I never would have thought that opening a `FolderBrowserDialog` should be considered "untrusted". Potentially this is absolutely any unmanaged code not just shell extensions. If you call managed code inside an AppDomain which in-turn pinvokes a native method which in-turn loads a managed assembly... that assembly has been loaded into your default AppDomain. Sandbox by-passed. – kjbartel May 13 '14 at 07:10
  • You don't typically give code running inside a sandbox the `UnmanagedCode` permission. – Damien_The_Unbeliever May 13 '14 at 07:40
  • @Damien_The_Unbeliever That is true yes. But a lot of the normal .Net libraries call unmanaged code. As is the case with the commondialogs. – kjbartel May 13 '14 at 07:59
  • 1
    Yes, but for example, with the shell extensions - someone has already taken the decision to install these *as* shell extensions - they're running in the explorer shell. They're running in *every* process that uses the shell dialogs, whether that process is managed or not. They're capable of all kinds of evil, even when we ignore anything that they might do inside of your process. – Damien_The_Unbeliever May 13 '14 at 08:03
  • @Damien_The_Unbeliever That's all fine and good and yes people have chosen to install the said shell extensions. But now as a software developer I need to make sure that my application will run on a customer's computer reliably. I'll note that the actual shell extension causing the problem is "Dell Backup and Recovery" i.e. a program installed on a lot of computers. – kjbartel May 13 '14 at 08:11
  • AppDomains are a .net construct. Shell extensions are unmanaged and load into the process. There's no isolation of unmanaged code within a process. So it actually makes no sense to say that the unmanaged code loads into one AppDomain or another. That's just meaningless. – David Heffernan May 13 '14 at 12:22
  • @DavidHeffernan That's funny. I have three managed shell extensions installed on my machine. And when I open a FolderBrowserDialog those assemblies and their dependencies are loaded into the default AppDomain of my application. – kjbartel May 13 '14 at 12:59
  • AppDomains provide isolation between different .net applications running inside the same process. However, that isolation does not isolate unmanaged code. – David Heffernan May 13 '14 at 13:09
  • @DavidHeffernan You might want to re-read the title and last paragraph. I want to stop assemblies being loaded as it is causing conflicts with an assembly I reference. I really don't care if I use an AppDomain or some other sandboxing technique but I do not want those assemblies loaded into the default AppDomain (all managed code runs in an AppDomain the default being the name of the executing executable). – kjbartel May 13 '14 at 14:29
  • 1
    Within a process, you cannot sandbox unmanaged code. – David Heffernan May 13 '14 at 14:42

0 Answers0