Verifiable Code is Safe?
Tuesday 13 September 2005
Its always disconcerting when something you believe in turns out to be not quite what you thought. For a long time I've thought that as long as you build .NET assemblies that are verifiable then you have 100% type-safe code and when running you are guaranteed not to experience any memory corruption. Then a week ago Matthias Kestenholz posted to the Mono list about a problem running XML-RPC.NET on Mono.
$ ./rpctest2.exe *** glibc detected *** free(): invalid next size (fast): 0x084818d8 ***
I replied:
The error you're then seeing looks like a Mono problem, on the basis that the XML-RPC.NET assembly is verifiable and so type safe.
But I had some nagging doubts as to whether this is true. In fact code can be verifiable yet still make calls to unmanaged code using P/Invoke. For example peverify determines that this program is verifiable even though a call to unmanaged code is made (the choice of AddAtom here is arbitrary and could be a call to any unmanaged dll):
using System;
using System.Security;
using System.Security.Permissions;
using System.Runtime.InteropServices;
class AtomSetter
{
[DllImport("kernel32.dll")]
static extern ushort AddAtom(string lpString);
public static void SetAtom(string atom)
{
AddAtom(atom);
}
}
class Program
{
static void Main(string[] args)
{
AtomSetter.SetAtom("foo");
}
}
To ensure that unmanaged code is not called from an assembly you have to use Code Access Security. In this case if we add a SecurityPermission attribute to the AtomSetter class we get a SecurityException at runtime.
[SecurityPermission(SecurityAction.Deny, UnmanagedCode = true)]
class AtomSetter
{
// ...
}
By default assemblies running from a local drive have full trust and can call unmanaged code via P/Invoke. Maybe this particular permission should be denied by default. Obviously there have to be calls into unmanaged code at some point but I would prefer this to be allowed by default only in the Framework libraries and not in any of my own code.