The Shared Source CLI (SSCLI) runtime is not intended for use as a secure environment, although its source code does provide a good example of how a secure execution environment can be implemented. By default, strong name verification is turned off for several important public keys.
The implementation of the global assembly cache and strong name verification system in the SSCLI is completely separate from the implementation used by the commercial Microsoft® .NET Framework, and because of this, there should be no interaction between the two. Turning off strong name verification in the SSCLI will not impact the .NET Framework on Microsoft® Windows® in any way.
Strong name verification is a mechanism that requires a developer or publisher of an assembly to have access to both the public and private elements of a cryptographic key pair at build time. The public key becomes part of the assembly name and a cryptographic hash of the metadata of the assembly is calculated using the private key and inserted into the assembly. At load time, strong name verification uses the public key to derive the metadata checksum that can be checked against the actual metadata thus proving that the producer of the assembly had access to the private key. More information on this process can be obtained from msdn.microsoft.com. The implementation of strong name verification can be seen in the SSCLI source tree in sscli\clr\src\dlls\mscorsn\strongname.cpp.
There is an additional distinction among strong names. All assemblies released in the .NET Framework that include classes specified in the ECMA-335 CLI standard are name with a special public key. This public key is cryptographically invalid and is treated as a special case by both the SSCLI and the .NET Framework strong name verification code.
In Microsoft's commercial .NET Framework implementation, when an assembly using this special public key is loaded, the strong name verification code assumes that the assembly is signed using the private Microsoft key. If it is not signed with the Microsoft key then the assembly will not load unless strong name verification for the public key in that assembly is turned off.
In the SSCLI, when an assembly contains the special public key designated by ECMA, the strong name verification code assumes that the assembly is signed with the SSCLI private key, which can be found in sscli\clr\bin\bin\finalpublickey.snk. If it is not signed with the SSCLI private key, the assembly will not load unless strong name verification for the public key of that assembly is turned off. By default, the build process delay-signs all assemblies.
Note that the SSCLI private key is not in any sense a "private" key because it is published in the source distribution. Anyone can use it to sign any assembly and it signifies nothing with respect to security and ownership of the resulting binary.
Because the SSCLI distribution is a source distribution with a build process and because the private key used to sign the .NET Framework implementation of system assemblies can be used only for signing binary files published by Microsoft, assemblies built during the SSCLI build process on your computer are delay-signed.
Delay signing (also called "partial signing") means that the public key is stored in the assembly metadata but the assembly file is not signed using the private key. In order for a delay-signed assembly to load, strong name verification must be turned off. This is done using the Strong Name tool during the SSCLI build process (see sn.html). The default configuration for the SSCLI build environment is that verification is turned off for both the ECMA public key and the Microsoft public key.
All assemblies that can be found in both the SSCLI and in Microsoft's commercial .NET Framework use identical public keys: some contain the ECMA key and some contain the Microsoft public key. Note that no assembly built with the SSCLI key can be trusted with respect to origin, including assemblies built during the SSCLI build process. (Of course, you have control of the SSCLI source code on your computer, so you understand the level of trust to impart to your own build output.)
When an assembly B references an assembly A, compilers store the full assembly identity, including the public key, in the assembly reference in assembly B. When either the SSCLI or the commercial .NET Framework load assembly B and attempt to resolve the types that reside in assembly A, the assembly-loading infrastructure will only look for assemblies with the same public key as assembly A. Note that no information with respect to the cryptographic signature of assembly A is stored in assembly B - only the public key (usually a size-reduced hash of the public key). Cryptographic verification occurs when an assembly is loaded into the CLI execution environment. Thus, assemblies built against delay-signed assemblies are no different than assemblies built against fully signed assemblies, only the public key is transferred to the new assembly.
The SSCLI implementation is designed to facilitate sharing code and experimentation. Code built against one SSCLI installation should run against another SSCLI installation. It should also run against other ECMA 335-compliant CLI implementations, assuming only classes in the ECMA standard are used. No assumptions should be made, however, about the security of the SSCLI installation or of assembly code signed with the SSCLI key pair.
Some tools in the SSCLI are managed applications that must be run inside the SSCLI execution environment. This means they must be executed using the clix application launching utility. Managed applications are assemblies and in the SSCLI these assemblies are delay signed. Failure to use the clix launcher to execute an SSCLI managed tool on Windows will cause the tool to be executed under the .NET Framework. This will cause an error dialog box that states that the utility might have been tampered with or was partially signed. This error is correct: the SSCLI utilities are partially signed and will not execute under the .NET Framework.
For example, if you forget to run clix caspol on Windows and instead just
run caspol you could see the resulting error dialog box content:
caspol.exe - Strong name validation failed.
Strong name validation failed for assembly 'C:\sscli\build\v1.x86fstchk.rotor\caspol.exe'. The file may have been tampered with or it was partially signed but not fully signed with the correct private key.
If you see a similar error, make sure to use the clix launcher when executing that tool.
You can use the sample tool, keyconfig, to change the key used by the SSCLI when it builds. See keyconfig.html for more information on using this tool.
When you use this tool, you will be providing a custom assembly key pair or just a custom assembly public key. If you provide the key pair, then all SSCLI assemblies will be signed with this full key pair. This can be convenient if you wish to attempt to load the assembly under the .NET Framework for debugging. For example, jsc.exe will be fully signed so it will load under the .NET Framework with no errors.
What will happen when you use the keyconfig tool is the new custom key values you provide will be used as a replacement for all keys for building assemblies.
Assemblies such as mscorlib.dll and System.dll will be built with the ECMA public key (see description above) but will be signed with the private key that you provided. This will continue to work because the SSCLI assembly verification code will now treat the new custom public key as a special case when loading these assemblies.
However, assemblies that do not normally have the ECMA public key (for example, Microsoft.JScript.dll) will now be built with a new public key and signed with a new private key. Any code that you develop that references these assemblies will not run under the .NET Framework because the public key stored in the assembly reference will not match any installed assemblies.
If you choose the delaysign option with the keyconfig tool, then all SSCLI assemblies will be built as delay-signed. The assemblies that would normally be signed with the ECMA public key will continue to be signed with that public key and other assemblies contain the new custom public key.
To build the SSCLI implementation on Microsoft® Windows® XP requires Visual Studio .NET, as stated in the readfirst.html.
The minimum installation of Visual Studio .NET required to support the SSCLI is to install Visual C++® .NET. Within the options for installing Visual C++ .NET, the C runtime libraries must be selected because the runtime header files are required by the SSCLI build process.
A Perl distribution must be installed on Windows XP in order to build the SSCLI source tree. You can go to www.activestate.com and install the free download of Perl (preferably version 5.6.1, builds 630 and later).
The Perl installation must correctly modify your environment variables so that Perl is in your path. The env.bat file will search your path and will set the PERLLIB environment variable assuming there is a LIB directory that is a peer of the location where perl.exe is installed.
You must install Perl with administrator-level privileges. If you install the ActiveState Perl distribution while you are logged in with only user-level privileges, the installer will not be able to modify your environment variables and the SSCLI build process will not work correctly.
The SSCLI requires 256MB of memory to build without slowing down considerably. Users building the SSCLI on FreeBSD on systems with 128MB of memory report that they must increase the available swap space to twice the default size (default is 2x memory) or at least 512MB. The build will proceed very slowly under this configuration but it will usually complete.
The first source release of the SSCLI used makefiles that required the use of BSD make on FreeBSD 4.5. These makefiles were incompatible with other variants of the make utility. The makefiles in the current release have been modified to remove the dependency on BSD make.
Due to portability modifications to the security implementation, support for mapping URLs to security zones is limited in the SSCLI security implementation. All file URLs will map to the zone of the local computer (LocalMachine) and all other URLs will map to the Internet zone. Ensure that you understand this limitation if you run code that relies on security zones generated from URLs.
In the first source release of the SSCLI, the directory where user-configuration information was stored was %userprofile%\rotor on Microsoft® Windows® or ~/.rotor on UNIX system-based platforms. This caused problems when trying to run checked, free, or fastchecked suites simultaneously because they all shared the same user configuration location. Modifications have been made to allow more complete side-by-side isolation of SSCLI builds.
The new user configuration directory name is created by generating a unique name based on a hash of the path to the platform adaptation layer (PAL) library (rotor_pal.dll on Windows, librotor_pal.so on FreeBSD, and librotor_pal.dylib on Mac® OS X). The new user configuration directory location is: %userprofile%\rotor\<hash>\ on Windows or ~/.rotor<hash> on UNIX system-based platforms, where <hash> is a 40-character hash of the path to the PAL dynamic library.
For example, if your user name on Windows is jsmith then the per-user configuration settings directory would be something like:
C:\Documents and Settings\jsmith\rotor\clejgcjcdhmbcjpgllccjfagplehoohojacjmnho
Note: Named shared memory objects also use this naming convention which should prevent contention for named objects during execution of code in other running instances of the SSCLI.
To review the implementation of this naming convention, search for the
MangleObjectNameW() function and the associated global
variable NameManglerW in the source code in the PAL subdirectories.
All assemblies created by using either the SSCLI or .NET Framework compilers contain a entry in the metadata root (see ECMA-335 specification, Partition II, section 23.2.1) that specifies which version of the .NET Framework should be loaded to run the assembly. This is a different version value than the assembly version and is utilized by the .NET Framework on Windows but it ignored by the SSCLI. The .NET Framework relies on the Windows loader to first load an executable assembly and because there can be multiple, side-by-side versions of the .NET Framework installed, the runtime version value is needed to indicate which version of the .NET Framework should be given the assembly to load and execute. Although the runtime version value is included in all assemblies, it is only normally relevant to executable assemblies.
The SSCLI does not utilize platform loaders to run assemblies, instead it relies on the clix launcher application. The clix launcher loads SSCLI core files based on the directory from which it was loaded so the SSCLI has no need to use the runtime version value and the value is ignored.
When an assembly is built using the .NET Framework compilers, the default behavior is to store the current version of the .NET Framework as the runtime version value. For example, with version 1.0 of the .NET Framework the runtime version value would be "v1.0.3705". This allows the .NET Framework pre-loader to find and load the version v1.0.3705 core implementation files.
If you intend to develop assemblies using the SSCLI and run them on the .NET Frameworks you might need to modify the runtime version value in order for them to load. By default the compilers in the SSCLI will generate assemblies with the value of "v1.0.0". This value does allow executable assemblies to load in version 1.0 of the .NET Framework and was chosen because it represents a generic version number that still works with version 1.0. However, future versions of the .NET Framework might not recognize this version value. Instead the value that should be used by an assembly that does not have a strict version requirement is the string: "Standard CLI 2002". This value, however, will not work with version 1.0 of the .NET Framework.
To summarize, the following are a set of runtime version values and the version of the .NET Framework on Windows into which the executable assembly containing the value will be loaded:
| Version value | Loaded version of .NET Framework |
|---|---|
| 1.0.0 | Version 1.0 of the .NET Framework. |
| v1.0.3705 | Version 1.0 of the .NET Framework. |
| v1.n.nnnn | Version 1.n.nnnn of the .NET Framework, where n is any digit. |
| Standard CLI 2002 | Future ECMA version 1.0 compliant versions of the .NET Framework. |
To change the runtime version value that will be built into assemblies created by SSCLI compilers, open the sscli\clr\src\dlls\mscoree\mscoree.cpp file. Search for the string: ROTOR_VERSION_NUMBER. You will see the following code:
#ifndef ROTOR_VERSION_NUMBER // By using (L"v1.0.0"), this should allow the us to run on the desktop version as well #define ROTOR_VERSION_NUMBER (L"v1.0.0") #endif
Changing the value of the #define ROTOR_VERSION_NUMBER will change the runtime version value in assemblies that are subsequently built with SSCLI compilers. You will need to rebuild the SSCLI after changing this value in order to have the change applied.
See the GetCliVersion sample for more information on how to inspect and modify the runtime version value in an existing assembly.
The SSCLI requires specific functionality in the POSIX threads (Pthreads) implementation on any platform to which it might be ported. Specifically, exception handling in the SSCLI is dependent on several extra parameters sent to SA_SIGINFO signal handlers which provide details about the signal and the context in which it occurred.
An example of a UNIX system-based platform which does not currently provide this required functionality is OpenBSD 3.1. It would be very difficult to port the SSCLI to such a platform and maintain exception handling functionality. Future versions of OpenBSD might provide this functionality and would then be available as a porting target for the SSCLI.
Due to problems with the default implementation of the tar archive utility on Mac OS X, the gnutar archive utility should instead be used to extract the SSCLI distribution archive. You can also use version 7.0 of the Stuffit™ Expander application to expand the SSCLI archive on Mac OS X. You must use version 7.0 or newer because older versions do not have full long file name support and some files in the archive have names with more than thirty-one characters.
Finding a file named @LongLink in the directory where you expanded the SSCLI archive is one indication that you used the tar utility and file name truncation occurred. The extracted distribution might not build or run correctly due to file name truncation. The exact behavior varies depending on the length of the path into which the archive was extracted.
There are no known issues using the default tar utility to extract the archive on other UNIX system-based platforms.
The Managed Code Debugger (cordbg) might not work correctly on FreeBSD installations that use a multi-processor kernel. This problem has been reproduced using FreeBSD 4.5.
This problem is fixed on FreeBSD 4.7.
There are no known problems building or running the SSCLI and CorDBG on Windows or Mac OS X multi-processor systems.
Several known problems might occur when the just-in-time (JIT) compiler implementation pitches code as it attempts to minimize the code heap size.
In some cases, when an exception is thrown the code for methods on the stack has been pitched. This causes the original starting address in StartOfTheMethod to be lost. For safety in this release of the SSCLI implementation, the offset is set to 0 to avoid pointing into unallocated memory. This means that the stack trace will always show the first line of the function for functions that have been pitched.
When the SSCLI runs out of code heap space, several different errors can occur:
There are a variety of options that modify the behavior of code pitching which can be set using environment variables. Two useful options are:
set COMPlusCodePitchEnable=false
set ComPlusMaxCodeCacheSize=10000
See the information in eeconfig.cpp for more information about further code pitching options and other implementation details. See logging.html for general information about the SSCLI logging infrastructure.
The SSCLI implementation cannot be installed to a location with spaces in the path name. Please extract the .tgz file into a directory location with no spaces in the name.
If you use the WinZip utility (http://www.winzip.com) to extract the SSCLI archive on Windows you must turn off the smart CR/LF conversion option. Some files in the SSCLI archive might not extract correctly if this option is turned on. To turn off the option in WinZip go to the Options item on the Configuration menu. On the Miscellaneous tab make sure the item labeled "TAR file smart CR/LF conversion" is not selected.
When you run one of the SSCLI implementations of a tool or utility on Windows you must make sure that the SSCLI build output directory is in your path before the .NET Framework or Visual Studio bin directories or errors will occur. For example, if you change into the .NET Framework directory which contains files like mscorwks.dll and mscorlib.dll, and then attempt to run the SSCLI version of metainfo.exe you will see an error like the following:
metainfo.exe - Entry Point Not Found The procedure entry point SetFusionShutdownCallback could not be located in the dynamic link library fusion.dll.
It has been reported that compiling the FreeBSD kernel with some modified configuration options might cause the SSCLI build process to fail. The symptom of the problem in the reported case was that the C# compiler would core dump when building the FX tree. Here is a snippet from the builddf.log file:
/out:/usr/local/src/sscli/build/v1.x86fstchk.rotor/private/lib/System.dll @objdf/rotor_x86/csc.rsp.lib Fatal error 'Can't create gc thread' at line ? in file /usr/src/lib/libc_r/uthread/uthread_create.c
The problem was solved by removing the following settings from the kernel configuration file and then recompiling the kernel:
# To use more memory per process options MAXDSIZ="(2048*1024*1024)" options MAXSSIZ="(256*1024*1024)" options DFLDSIZ="(1024*1024*1024)"
All the samples under the sscli\samples\pigui directory require Tcl and Tk to be installed on the system in order to execute. On Windows, one option is to install the ActiveTcl 8.4.0 distribution from www.ActiveState.com. Versions of Tcl and Tk older than 8.4.0 might not work correctly with the SSCLI Tk sample applications. On FreeBSD 4.5 and Mac OS X, the Tcl and Tk 8.4.0 packages will have to be downloaded and installed.
Platform-independent UI (PIGUI) samples built under one platform will not run on other platforms. For example, PIGUI samples built on Windows will not run on FreeBSD or Mac OS X. Also, these samples built on Mac OS X will not run on Windows or FreeBSD.
The samples rely on platform invoke wrappers in sscli\samples\pigui\tk\tknative.cs which use a constant value that contains either tk84.dll on Windows, libtk84.so on FreeBSD, and libtk84.dylib on Mac OS X under an #ifdef switch. Built sample applications will have the name of the Tk support DLL built into them but the file name changes across platforms.
The version of the gdb debugger that installs by default on FreeBSD 4.5 has problems using the SOS debugger extension. You can obtain more information on using gdb and SOS in sos.html.
Problem reports indicate that the version of gdb that ships with FreeBSD 4.5 might crash and core dump when used with the SOS debugger extension library. However, later versions of gdb do not seem to have this problem.
SOS is implemented as a dynamically loaded library, sos.dll on Windows, libsos.so on FreeBSD, and libsos.dylib on Mac OS X. It can be loaded from the Windows SDK platform debuggers NTSD or WinDBG on Windows, or from gdb on UNIX system-based platforms. However the manner in which it is loaded differs between the Windows debuggers and gdb.
On Windows under NTSD or WinDBG, the SOS dll is loaded into the debugger process and it communicates across-process to obtain data from the process being debugged. Under gdb, extension libraries are loaded into the process being debugged and function calls into SOS are made to the external process from the debugger. The SSCLI supports this loading procedure by means of a function in the core runtime library libsscoree.so (libsscoree.dylib on Mac OS X), which uses the PAL and the LoadLibrary() API to load the SOS library into the CLI process being debugged.
The SSCLI implementation requires the released version of the Visual Studio .NET development system as the build environment. The build process does not work with the Visual Studio .NET version 7.0 beta2 release.
Symptoms of the problem are log file errors like the following:
Studio.NET\Vc7\PlatformSDK\Include\WinNT.h(4323) : error C2220: warning treated as error -
no object file generated C:\Program Files\Microsoft Visual
Studio.NET\Vc7\PlatformSDK\Include\WinNT.h(4323) : warning C4005: 'THREAD_BASE_PRIORITY_MIN' : macro redefinition
..\rotor_pal.h(1776) : see previous definition of 'THREAD_BASE_PRIORITY_MIN' C:\Program Files\Microsoft Visual
Studio.NET\Vc7\PlatformSDK\Include\WinNT.h(4324) : warning C4005: 'THREAD_BASE_PRIORITY_IDLE' : macro redefinition
..\rotor_pal.h(1777) : see previous definition of 'THREAD_BASE_PRIORITY_IDLE' C:\Program Files\Microsoft Visual
Studio.NET\Vc7\PlatformSDK\Include\WinBase.h(3797) : warning C4005: 'TLS_OUT_OF_INDEXES' : macro redefinition
..\rotor_pal.h(1802) : see previous definition of 'TLS_OUT_OF_INDEXES'
NMAKE : fatal error U1077: 'cl' : return code '0x2' Stop.
These particular errors are caused by changes to the macro definitions between the beta and release versions of Visual Studio .NET. Since the SSCLI was developed using the released version, these macro definitions do not match.
If your user account on FreeBSD is not a member of group wheel, you may see a sequence of errors during an SSCLI build that look like:
config.status: creating makefile mv: makefile: set owner/group (was: 1000/0): Operation not permitted config.status: creating makefile.common mv: makefile.common: set owner/group (was: 1000/0): Operation not permitted
These errors specifically occur if you run ./configure in the SSCLI directory.
These errors are not significant and do not indicate a build problem. The errors are due to the way the mv command works with permissions on FreeBSD. The mv command is attempting to preserve user and group information when it moves the file but because the file has a group of wheel but the user does not, the mv command cannot preserve this information. The file is successfully copied and simply ends up as a member of the user's group so the error messages can be ignored.
Copyright (c) 2002 Microsoft Corporation. All rights reserved.