|
security
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
SecurityException thrown when serializing custom exception classHowever, when I test my exception class I have a problem with serialization where a SecurityException is thrown. Since I believe I have followed all the rules (including using FxCop on my class) I have tried to simplify my troubleshooting by creating a new custom exception very similar to the System.ArgumentException class. This custom exception class called MyException has code identical to System.ArgumentException (discovered by using Reflector) including attributes. This code passes FxCop inspection (except for some unimportant naming issues: "param" is "misspelled"). I try to serialize it using the following code: MyException x = new MyException("Message", "ParamName"); MemoryStream stream = new MemoryStream(); BinaryFormatter formatter = new BinaryFormatter(); formatter.Serialize(stream, x); stream.Position = 0; x = (MyException) formatter.Deserialize(stream); When this code is executed an exception is thrown in the call to BinaryFormatter.Serialize(). (All the code is executed locally on my computer in a fully trusted environment.) The interesting part of the stack trace is as follows: at System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Assembly asm, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed) at System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Object assemblyOrString, PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission permThatFailed) at System.Security.CodeAccessSecurityEngine.CheckSetHelper(PermissionSet grants, PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Object assemblyOrString, SecurityAction action, Boolean throwException) at System.Security.CodeAccessSecurityEngine.CheckSetHelper(CompressedStack cs, PermissionSet grants, PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Assembly asm, SecurityAction action) at MyException.GetObjectData(SerializationInfo info, StreamingContext context) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) The exception thrown is SecurityException and the FirstPermissionThatFailed property of this exception is: <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="SerializationFormatter"/> Since MyException is an replica of ArgumentException MyException.GetObjectData() is marked with the following attribute: [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)] Removing the attribute doesn't fix the problem, but upsets FxCop. What really puzzles me is that if I replace MyException with ArgumentException no exception is thrown. Why? What should I do to fix my custom exception class? Thanks in advance. -- Martin Liversage Are all your drivers up to date? click for free checkup Remember to mark your own exception class with the Serializable attribute.
and provide the protected contructor taking SerializationInfo as argument. The below works perfectly: -- Show quoteHide quotergds. /Claus Konrad using System; using System.IO; using System.Diagnostics; using System.Collections.Generic; using System.Text; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; namespace ExceptionSerialization { class Program { static void Main(string[] args) { MyException ex = new MyException(); MemoryStream msSerialize= new MemoryStream(); BinaryFormatter form = new BinaryFormatter(); //serialize the exception form.Serialize(msSerialize, ex); //deserialize msSerialize.Position = 0; MyException myEx = (MyException)form.Deserialize(msSerialize); Debug.Assert(myEx != null); Console.ReadKey(); } } [Serializable] class MyException : System.ApplicationException { public MyException() {} public MyException(string message) : base(message) { } protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { } } } -- rgds. /Claus Konrad "Martin Liversage" wrote: > I want to create a custom exception class that contains an additional field. > However, when I test my exception class I have a problem with serialization > where a SecurityException is thrown. Since I believe I have followed all the > rules (including using FxCop on my class) I have tried to simplify my > troubleshooting by creating a new custom exception very similar to the > System.ArgumentException class. This custom exception class called > MyException has code identical to System.ArgumentException (discovered by > using Reflector) including attributes. This code passes FxCop inspection > (except for some unimportant naming issues: "param" is "misspelled"). I try > to serialize it using the following code: > > MyException x = new MyException("Message", "ParamName"); > MemoryStream stream = new MemoryStream(); > BinaryFormatter formatter = new BinaryFormatter(); > formatter.Serialize(stream, x); > stream.Position = 0; > x = (MyException) formatter.Deserialize(stream); > > When this code is executed an exception is thrown in the call to > BinaryFormatter.Serialize(). (All the code is executed locally on my computer > in a fully trusted environment.) > > The interesting part of the stack trace is as follows: > > at > System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Assembly asm, > PermissionSet granted, PermissionSet refused, RuntimeMethodHandle rmh, > SecurityAction action, Object demand, IPermission permThatFailed) > at > System.Security.CodeAccessSecurityEngine.ThrowSecurityException(Object > assemblyOrString, PermissionSet granted, PermissionSet refused, > RuntimeMethodHandle rmh, SecurityAction action, Object demand, IPermission > permThatFailed) > at > System.Security.CodeAccessSecurityEngine.CheckSetHelper(PermissionSet grants, > PermissionSet refused, PermissionSet demands, RuntimeMethodHandle rmh, Object > assemblyOrString, SecurityAction action, Boolean throwException) > at > System.Security.CodeAccessSecurityEngine.CheckSetHelper(CompressedStack cs, > PermissionSet grants, PermissionSet refused, PermissionSet demands, > RuntimeMethodHandle rmh, Assembly asm, SecurityAction action) > at MyException.GetObjectData(SerializationInfo info, StreamingContext > context) > at > System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object > obj, ISurrogateSelector surrogateSelector, StreamingContext context, > SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, > ObjectWriter objectWriter) > at > System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object > obj, ISurrogateSelector surrogateSelector, StreamingContext context, > SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, > ObjectWriter objectWriter) > at > System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object > graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck) > at > System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck) > at > System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) > > The exception thrown is SecurityException and the FirstPermissionThatFailed > property of this exception is: > > <IPermission class="System.Security.Permissions.SecurityPermission, > mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > version="1" Flags="SerializationFormatter"/> > > Since MyException is an replica of ArgumentException > MyException.GetObjectData() is marked with the following attribute: > > [SecurityPermission(SecurityAction.LinkDemand, > Flags=SecurityPermissionFlag.SerializationFormatter)] > > Removing the attribute doesn't fix the problem, but upsets FxCop. > > What really puzzles me is that if I replace MyException with > ArgumentException no exception is thrown. Why? What should I do to fix my > custom exception class? > > Thanks in advance. > > -- > Martin Liversage > "Claus Konrad" wrote: Thanks for you input.> Remember to mark your own exception class with the Serializable attribute. > and provide the protected contructor taking SerializationInfo as argument. My custom exception is marked Serializable and contains the protected constructor you are refering to. I have used Reflector to "reverse engineer" ArgumentException, and my problem is that for some reason my exception throws a SecurityException during serialization, but ArgumentException does not. You example does not include a private field, and the SecurityException is thrown in the ISerializable.GetObjectData() method where the private field is supposed to be serialized. Your example works for me too by the way. In case you are interested I include the code for MyException below: using System; using System.Runtime.Serialization; using System.Security.Permissions; using System.Runtime.InteropServices; namespace MyNamespace { [Serializable, ComVisible(true)] public class MyException : SystemException, ISerializable { public MyException() : base("MyException") { } public MyException(String message) : base(message) { } protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { if (info == null)throw new ArgumentNullException("info"); this.m_paramName = info.GetString("ParamName"); } public MyException(String message, Exception innerException) : base(message, innerException) { } public MyException(String message, String paramName) : base(message) { this.m_paramName = paramName;} public MyException(String message, String paramName, Exception innerException) : base(message, innerException) { this.m_paramName = paramName;} [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) throw new ArgumentNullException("info"); base.GetObjectData(info, context); info.AddValue("ParamName", this.m_paramName, typeof(String)); } public override String Message { get { return base.Message; } } public virtual String ParamName { get { return this.m_paramName; } } String m_paramName; } } -- Martin Liversage Right.
In case you are dealing with custom parameters, you need to cater for that by adding these to the serialization info object (to be allowed to be descerialised). using System; using System.IO; using System.Diagnostics; using System.Collections.Generic; using System.Text; using System.Security.Permissions; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Serialization.Formatters.Binary; namespace ExceptionSerialization { class Program { static void Main(string[] args) { string myMsg = "message"; int par = 22; MyException ex = new MyException(myMsg, par); using (MemoryStream ms = new MemoryStream()) { BinaryFormatter binForm = new BinaryFormatter(); //serialize the exception binForm.Serialize(ms, ex); //deserialize ms.Position = 0; MyException myEx = (MyException)binForm.Deserialize(ms); Debug.Assert(myEx != null); Debug.Assert(myEx.SomeParameter.Equals(par)); Debug.Assert(myEx.Message.Equals(myMsg)); } Console.ReadKey(); } } [Serializable] class MyException : System.ApplicationException { public MyException(string message, int someParamenter) : base(message) { this.m_somePar = someParamenter; } private int m_somePar; public int SomeParameter { get { return m_somePar; } set { m_somePar = value; } } protected MyException(SerializationInfo info, StreamingContext context) : base(info, context) { m_somePar = info.GetInt32("myparameter"); } [SecurityPermission(SecurityAction.LinkDemand, Flags=SecurityPermissionFlag.SerializationFormatter)] public override void GetObjectData(SerializationInfo info, StreamingContext context) { base.GetObjectData(info, context); info.AddValue("myparameter", m_somePar); } } } -- Show quoteHide quotergds. /Claus Konrad "Martin Liversage" wrote: > "Claus Konrad" wrote: > > > Remember to mark your own exception class with the Serializable attribute. > > and provide the protected contructor taking SerializationInfo as argument. > > Thanks for you input. > > My custom exception is marked Serializable and contains the protected > constructor you are refering to. I have used Reflector to "reverse engineer" > ArgumentException, and my problem is that for some reason my exception throws > a SecurityException during serialization, but ArgumentException does not. > > You example does not include a private field, and the SecurityException is > thrown in the ISerializable.GetObjectData() method where the private field is > supposed to be serialized. Your example works for me too by the way. > > In case you are interested I include the code for MyException below: > > using System; > using System.Runtime.Serialization; > using System.Security.Permissions; > using System.Runtime.InteropServices; > > namespace MyNamespace { > > [Serializable, ComVisible(true)] > public class MyException : SystemException, ISerializable { > > public MyException() : base("MyException") { } > > public MyException(String message) : base(message) { } > > protected MyException(SerializationInfo info, StreamingContext context) > : base(info, context) { > if (info == null) > throw new ArgumentNullException("info"); > this.m_paramName = info.GetString("ParamName"); > } > > public MyException(String message, Exception innerException) : > base(message, innerException) { } > > public MyException(String message, String paramName) > : base(message) { > this.m_paramName = paramName; > } > > public MyException(String message, String paramName, Exception > innerException) > : base(message, innerException) { > this.m_paramName = paramName; > } > > [SecurityPermission(SecurityAction.LinkDemand, > Flags=SecurityPermissionFlag.SerializationFormatter)] > public override void GetObjectData(SerializationInfo info, > StreamingContext context) { > if (info == null) > throw new ArgumentNullException("info"); > base.GetObjectData(info, context); > info.AddValue("ParamName", this.m_paramName, typeof(String)); > } > > public override String Message { get { return base.Message; } } > > public virtual String ParamName { get { return this.m_paramName; } } > > String m_paramName; > > } > > } > > -- > Martin Liversage > "Claus Konrad" wrote: Again, thanks a lot for you input.> Right. > In case you are dealing with custom parameters, you need to cater for that > by adding these to the serialization info object (to be allowed to be > descerialised). Your code works (off course). In my setup I had a test application that did the serialization and an assembly containing the custom exception class. When I moved your exception class to my assembly the SecurityException was thrown again indicating that the problem was with my assembly containing the exception class. After some investigation I found that the culprit was these two attributes in the assembly: // Minimum permissions required for this assembly. [assembly: FileIOPermission(SecurityAction.RequestOptional, Unrestricted=true)] [assembly: SecurityPermission(SecurityAction.RequestOptional, UnmanagedCode=true)] Removing them fixed the problem. -- Martin Liversage
Creating MSI for installing .NET security policies
ActiveDirectory group membership in offline profile How to deploy a VS2005 VB app without signing the clickonce manifest and assy Effective FileSystemRights for a WindowsIdentity??? The remote server returned an error: (403) Forbidden in webrequest Which encryption type ???? Why am I not trusted? Seeking Advice on RSA IL code fails with VerificationException .NET 2.0/ VB 2005 application-Security Policy issue |
|||||||||||||||||||||||