Explicit Serialization API and Security
Peter Firmstone
peter.firmstone at zeus.net.au
Wed Jan 14 20:41:32 UTC 2015
It's only top down if there are intra class invariants, in this case invariants are checked more than once.
This done simply because we can't move up the constructor call chain untill all child class invariants have been satisfied.
For simpler class relationships, invariant check order is bottom up. The child class cannot allow a super class constructor to be called until its own invariants have been satisfied, in order to prevent an illegal instance of itself being created.
If we check invariants after the object has been created, unless we introduce a check initialized method into every method, we loose. Unfortunately we can't share this check with child classes, so the class really should be declared final, or all its methods should be, including any superclass methods, including Object equals and hashcode.
Unfortunately enforcing security by enforcing invariants after calling a superclass constructor, is far more complicated.
Using a serial constructor, is less evil.
Regards,
Peter.
----- Original message -----
> On 14/01/15 12:58, Peter Firmstone wrote:
> > Hi Chris,
> >
> > Sorry, no.
> >
> > Currently when an ObjectStreamClass is read in from the stream, the
> > framework searches for the first zero arg constructor of a non
> > serializable class and creates and instance of the class read and
> > resolved from the stream, however it does so using a super class
> > constructor.
> >
> > Then from the super class down, fields are read in and set in order for
> > each class in the object's inheritance hierarchy.
>
> This is my understanding also.
>
> > The alternative I propose, doesn't create the instance, instead it
> > reads the fields from the stream, one by one and without instantiating
> > them, if they are newly read objects, stores them temporarily into
> > byte [] arrays in a Map with reference handle keys, otherwise it just
> > holds the reference handle.
>
> GetField.get(...), or ReadSerial, will create an object before returning
> it. So the invariant checker methods will turn the stream field values
> into objects at some point.
>
> Also, from your previous examples, I though I seen the invariant checker
> method explicitly create superclass instance, so that it could be used
> in the validation, right?
>
> What I was trying to do was to reduce your examples, and description,
> into a sequence of steps, to try to better understand how this would
> work.
>
> What I came up with, I believe, is equivalent to what was done in this
> example [1]. If you intend to chain the "serial constructors" up with
> static check methods that create superclass instances, then I think is
> equates to top-down checking as I have described it.
>
>
> > What it does next is wrap this information into a caller sensitive api,
> > GetFields or ReadSerial instance, that is passed as a constructor
> > parameter to the child class serial constructor.
> >
> > The child class checks invariants and reads each field it needs using a
> > static method prior to calling a superclass constructor, each class in
> > the inheritance hierarchy for the object then checks its invariants
> > until it gets to the first non serializable superclass.
> >
> > The benefit of this order is that each class is present in the thread
> > security context, so protection domain security and invariants are
> > enforced before instantiating an object.
> >
> > Hope this helps illuminate it a little better, regards,
>
>
> -Chris.
>
> [1]
> http://mail.openjdk.java.net/pipermail/core-libs-dev/2015-January/030550.html
>
> >
> > Peter.
> >
> > ----- Original message -----
> > Peter F,
> >
> > I am still struggling with the basic concept of you proposal. Let me
> > see if I understand it correctly. Does the following describe a similar
> > scenario as you envisage:
> >
> > 1) For each Serializable type, T, in the deserialized types
> > hierarchy, starting with the top most ( closest to
> > j.l.Object ),
> >
> > 1a) Read T's fields from the stream, fields
> >
> > 1b) validate(t, fields) // t will be null first time
> >
> > 1c) allocate a new instance of T, and assign to t
> >
> > 1d) set fields in t
> >
> > 2) Return t;
> >
> > So for each level in the hierarchy, an instance of a type is created
> > only after its invariants have been checked. This instance is then
> > passed to the next level so it can participate in that levels
> > invariants validation.
> >
> > If this scenario is along the same lines as yours, then I just don't
> > see how 1c above will always be possible.
> >
> > If we could somehow make the object caller sensitive until after
> > deserialization completes, then could avoid having to try to allocate
> > multiple instance down the hierarchy.
> >
> > -Chris.
> >
> > On 13/01/15 10:24, Peter Firmstone wrote:
> > Could we use a static validator method and generate bytecode for
> > constructors dynamically?
> >
> > The developer can optionally implement the constructors.
> >
> > static GetField invariantCheck(GetField f);
> >
> > Create a caller sensitive GetField implementation and add a two new
> > methods to GetField:
> >
> > abstract Object createSuper(); // to access superclass object methods
> > for inavariant checking.
> >
> > abstract Class getType(String name);
> >
> > Set fields from within constructors.
> >
> > The generated constructors are straight forward:
> >
> > 1. Call static method.
> > 2. Call super class constructor with result from static method.
> > 3. Set final fields
> > 4. How to set transient fields, implement a private method called from
> > within the constructor?
> >
> > Require a permission to extend GetField?
> >
> >
More information about the core-libs-dev
mailing list