Question

I am not able to understand how to fix CA2123 for a C++/CLI project. Here is a sample project to demonstrate the issue:

1) Create a C# (.NET 4) Class Library

ManagedClass.cs

namespace CSharpLibrary {

public interface IManagedClass
{
    void WriteSomething();
}

public class ManagedClass : IManagedClass
{
    public void WriteSomething()
    {
    }
}

}

2) Create a C++/CLI Console App (VS 2010):

AssemblyInfo.cpp

#include "stdafx.h"

using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security;

[assembly:AssemblyTitleAttribute("CPlusPlusCLIConsoleApp")];
[assembly:AssemblyDescriptionAttribute("")];

[assembly:AssemblyVersionAttribute("1.0.*")];

[assembly:ComVisible(false)];

[assembly:CLSCompliantAttribute(false)];

[assembly:SecurityCritical];

CPlusPlusCLIConsoleApp.h

#pragma once

using namespace CSharpLibrary;
using namespace System::Security;

typedef void* (__cdecl FACTORY_PROC)();

namespace CPlusPlusCLIConsoleApp
{
    public ref class MainClass : public IManagedClass
    {
    public:
        [SecurityCritical]
        virtual void WriteSomething();
    };

};

CPlusPlusCLIConsoleApp.cpp

#include "stdafx.h"
#include "CPlusPlusCLIConsoleApp.h"

using namespace System;

int main(){};

namespace CPlusPlusCLIConsoleApp
{
    [SecurityCritical]
    void MainClass::WriteSomething()
    {
    }
};

After enabling all Microsoft Security Rules, I get this warning:

CA2123 Override link demands should be identical to base

Add the following security attribute to 'MainClass::WriteSomething(void)' in order to match a LinkDemand on base method 'IManagedClass::WriteSomething(void)': 'SecurityCriticalAttribute'.

CPlusPlusCLIConsoleApp cpluspluscliconsoleapp.cpp 13

I tried to follow what this StackOverflow answer suggested but it did not fix the error.

I understand that the managed dll is by default SecurityCritical (I do not want to change this in my original project) since I don't specify any SecurityAttribute. Why isn't the C++ CLI dll follow the same default?

What steps should I follow to fix this error? (Basically how can I make WriteSomething method SecurityCritical in C++ CLI)

EDIT 1: I have asked the same question on MSDN.

EDIT 2: Contacted Microsoft and it is an as designed behaviour. The C++\CLI team just did not have time to implement Level2 Security for C++\CLI. Hence C++\CLI is always stuck at Level1 Security. One can safely suppress the code analysis warning for the same.

Was it helpful?

Solution

The root problem here is that your C# and C++ assemblies are using two different transparency models (see http://blogs.msdn.com/b/shawnfa/archive/2009/11/11/transparency-models-a-tale-of-two-levels.aspx and http://blogs.msdn.com/b/shawnfa/archive/2009/11/12/differences-between-the-security-rule-sets.aspx for details of the two levels). This is because the C# assembly compiles to level 2 by default, but the C++ assembly is automatically forced down to level 1 by the compiler for some apparently undocumented reason. Unfortunately, it seems that the latter behaviour isn't overridable. To make things worse, it doesn't appear to have changed in VS2012, and it doesn't look like the product team is considering changing it any time soon.

Given that you can't move the C++ assembly to level 2, you have a couple of potentially viable choices if you want to keep the executable in C++ and it must contain the interface implementation:

  1. Move the C# assembly to level 1 via use of the SecurityRulesAttribute. This would presumably only be acceptable if the C++ console app is the only consumer of the C# library.
  2. Reproduce the level 2 "escalation" of security criticality to a full trust link/inheritance demand via the use of PermissionSetAttribute. e.g.:

    [SecurityCritical]
    [PermissionSet(SecurityAction::LinkDemand, Unrestricted = true)]
    [PermissionSet(SecurityAction::InheritanceDemand, Unrestricted = true)]
    virtual void WriteSomething();
    

It might also be worthwhile to submit another bug report on Connect (voting for closed ones doesn't seem to be very useful) or a feature request on UserVoice to request that the compiler behaviour be changed. (Locking into level 1 is pretty darn odd given that level 2 is supposed to be the default for .NET 4.0 and higher.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top