.NET Type Safety and .NET Configuration Tool

  • Thread starter Thread starter Peter Andersen
  • Start date Start date
P

Peter Andersen

I posted this on a mailing list, but I wanted to hear peoples reaction
to this here on the official discussion forum:
Hi folks. I've got a problem with a bit of IL I'm using to try and teach
about types. My understanding is that execution of managed code is
inherently type safe at all levels. I've bodged a bit of IL to do a division
between floating point and string:

IL_000b: ldstr "rob"
IL_0010: stloc.2
IL_0011: ldloc.2
IL_0012: ldc.r4 1.
IL_0017: div

I was hoping that this would throw an appropriate exception. When I run it
under .NET I get a divide by zero error which takes me to the Pentium DIV
instruction when I debug. I get really strange behaviour if I try to catch
the exception that should be thrown.
....

As a compiler writer for .net and java I have a few times stumpled
across this too: it seems that .net code is not verified before
attempted run by the runtime.

I decided to try to get to the bottom of it.
I tried to make a complete program (test.il) that has your problem:

// Compilation:
// ilasm -nologo -exe test.il
.assembly extern mscorlib {}
.assembly test { .ver 0:0:0:0 }
.class public Test extends [mscorlib]System.Object
{
.method public static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init ([0] class [mscorlib]System.String)
ldstr "rob"
stloc.0
ldloc.0
ldc.r4 1.
div
ret
}
}

When running "test.exe" I could partly confirm your observation: No
verification errors are reported (on the other hand, I did not get
into a native error situation, the program just runs with no output,
but exit code 1 - maybe you have a slightly different program? I have
the .NET framework version 1.1 - same as you?).

If I run the stand alone verifier, indeed it reports errors:

$ peverify -nologo test.exe
[IL]: Error: [c:...\test.exe : Test::Main]
[offset 0x0000000C]
[opcode div]
objref 'System.String'
Double Non-compatible types on the stack.
[IL]: Error: [c:...\test.exe : Test::Main]
[offset 0x0000000D]
[opcode ret]
Stack must be empty on return from a void function.
2 Errors Verifying test.exe

So how come the runtime does not report this, when I run the
executable?

After a long time digging in the documentation, I think I found the
answer: When running code from the locale machine, this code is "Fully
Trusted" meaning that even the bytecode verification is skipped!

I did not look into detail of this before, but a good starting point
is
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconnetframeworksecurity.asp
Look especially on the "Code Access Security" stuff.

I then tried to see if it would be possible to adjust the security
policy for a given application (at least to strengthen is by requiring
bytecode validation). A good guess (I thought :-) would be some flag
in
a configuration file (test.exe.config in this case).

I looked at

http://msdn.microsoft.com/library/en-us/cpgenref/html/gngrfnetframeworkconfi
gurationfileschema.asp

but it seems that you should instead look at

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconsecurityconfigurationfiles.asp

As this describes, you can only change a given zone's security policy
by using one of two tools (as administrator):

Mscorcfg.msc or caspol.exe

Well, I tried using the command line tool caspol, but was overwhelmed
by the complexity (:-)

Instead I tried using Mscorcfg directly from the Control Panels.

*** NOTICE: READ THE REST OF THIS BEFORE TRYING IT YOURSELF! ***

To be specific:

1. Open Control Panel
-> Administrative Tools
-> Microsoft .NET Framework 1.1 Configuration
2. In the treeview, unfold
My Computer
-> Runtime Security Policy
-> User
-> Code Groups
-> All_Code
3. Right-click All_Code and select Properties
4. Click Permission Sets tab
5. From the documentation on Named Permission Sets,

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconNamedPermissionSets.asp
I judged, that instead of the default "FullTrust" I should probably
use "Everything", which grants
"All standard (built-in) permissions, except permission to skip
verification."
So thats what I did!

The configuration tool the came with a surprising warning:
"The changes you just made to security policy might prevent
the .NET Framework Configuration Tool from running the next time you
need it. Please check your changes before closing the .NET Framework
Configuration tool."
OK, but since I knew what I was doing (:-), I went ahead.

Back to my test program:

Oh great!!! When I now run the program I actually get some runtime
verification failure:

Unhandled Exception: System.Security.VerificationException:
Operation could destabilize the runtime.
at Test.Main(String[] args)

So thats much better (although a little strange message).
The .NET executables now behaves like Java and complains about
verification errors at run time!

After having learned that, I figured, I had better put the
security policy back to normal again before proceeding.
But oh-oh-oh: Now the .NET Framework Configuration Tool in the
Administrative Tools actually failed to load!!! Just like it had
warned me about!
[does this mean that this is a managed *unverified* program?!]

To make a long story short, I had plenty of problems getting this to
run
again: I tried changing the three security.config files explained in
the documentation and reboot. I tried (again) to use caspol.exe. But
finally I deinstalled the .NET Framework 1.1 and reinstalled it before
I was again able to load the .NET Framework Configuration Tool!!!

So now I an back to normal. Well, sort of: My program no longer
complains about "Operation could destabilize the runtime", but
actually gives a nicer

Unhandled Exception: System.InvalidProgramException:
Common Language Runtime detected an invalid program.
at Test.Main(String[] args)

Strange - I would have expected to be back to the original situation,
where the program just ran without reporting problems.

To finish this long story, I am left with a few questions:

1. What did I do wrong above? Did I misunderstand something?
2. Is it correct that the runtime does not require local code
to be verifiable by default (unlike java)?
3. Is it, then, possible on a program-by-program basis (via
configuration files?) to strengthen this default behavior
be requiring SkipVerification=false?
4. Why does my program behave differently now that I should be back to
normal security policy?
5. Is the .NET Framework Configuration Tool indeed a non-verifiable
managed executable?

Sincerely,

Peter Andersen
Institute of Computer Science
Aarhus University
Aabogade 34A, Hopper-335
DK-8200 Aarhus N
Denmark.
 
2. Is it correct that the runtime does not require local code
to be verifiable by default (unlike java)?

Just a quick note: I seem to recall that most JVMs don't do full
bytecode verification on locally loaded code either. They may do more
than .NET does by default, but not the strictest verification. Sun's
JRE 1.4.2 for instance has the "-Xfuture" option to enable stricter
checking than the default.
 
Back
Top