Re: [PATCH] libsepol/cil: Give an error when constraint expressions exceed max depth

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Sep 8, 2020 at 4:32 PM James Carter <jwcart2@xxxxxxxxx> wrote:
>
> On Tue, Sep 8, 2020 at 11:27 AM Stephen Smalley
> <stephen.smalley.work@xxxxxxxxx> wrote:
> >
> > On Tue, Sep 8, 2020 at 9:50 AM Stephen Smalley
> > <stephen.smalley.work@xxxxxxxxx> wrote:
> > >
> > > On Tue, Sep 8, 2020 at 9:46 AM Stephen Smalley
> > > <stephen.smalley.work@xxxxxxxxx> wrote:
> > > >
> > > > On Fri, Sep 4, 2020 at 8:49 AM Stephen Smalley
> > > > <stephen.smalley.work@xxxxxxxxx> wrote:
> > > > >
> > > > > On Thu, Sep 3, 2020 at 2:19 PM James Carter <jwcart2@xxxxxxxxx> wrote:
> > > > > >
> > > > > > CIL was not correctly determining the depth of constraint expressions
> > > > > > which prevented it from giving an error when the max depth was exceeded.
> > > > > > This allowed invalid policy binaries with constraint expressions exceeding
> > > > > > the max depth to be created.
> > > > > >
> > > > > > Correctly calculate the depth of constraint expressions when building
> > > > > > the AST and give an error when the max depth is exceeded.
> > > > > >
> > > > > > Reported-by: Jonathan Hettwer <j2468h@xxxxxxxxx>
> > > > > > Signed-off-by: James Carter <jwcart2@xxxxxxxxx>
> > > > >
> > > > > The fix for conditional boolean expression depth checking can be a
> > > > > separate patch.  For this one,
> > > > >
> > > > > Acked-by: Stephen Smalley <stephen.smalley.work@xxxxxxxxx>
> > > >
> > > > Actually, this breaks selinux-testsuite. Will have to look into why.
> > > > /usr/sbin/semodule -i test_policy/test_policy.pp test_mlsconstrain.cil
> > > > test_overlay_defaultrange.cil test_add_levels.cil test_glblub.cil
> > > > Max depth of 4 exceeded for constraint expression
> > > > Bad expression tree for constraint
> > > > Bad constrain declaration at
> > > > /var/lib/selinux/targeted/tmp/modules/100/base/cil:919
> > >
> > > Here is the failing cil module:
> > > $ cat policy/test_mlsconstrain.cil
> > > (mlsconstrain (peer (recv)) (or (dom l1 l2) (and (neq t1
> > > mcs_constrained_type) (neq t2 mcs_constrained_type))))
> > > (mlsconstrain (packet (recv)) (or (dom l1 l2) (and (neq t1
> > > mcs_constrained_type) (neq t2 mcs_constrained_type))))
> > >
> > > Maybe an off-by-one in your depth checking?
> >
> > Actually, the depth computation logic doesn't seem consistent with
> > checkpolicy's define_constraint().
>
> I don't really understand what checkpolicy is doing. I guess keeping
> track of the postfix stack size?

Yes, the whole point is to prevent overflowing the fixed-size stack
used by the kernel (and by libsepol) in evaluating constraints.
Originally I think it was to bound recursion in the function since the
original implementation was recursive and only later converted.  The
important thing is to match the kernel.

> The one difference that would be easy to fix is that checkpolicy ignores "not".
>
> CIL has a max depth = 4, but checkpolicy has a max depth = 0 for these:
> (constrain (C5 (P5)) (not (not (not (not (eq t1 T5a))))))
> constrain C5 { P5 } not (not (not (not (t1 == T5a))));
>
> Here is one pair of examples that would be hard for me to make CIL
> agree with checkpolicy. These are essentially the same constraint:
>
> Both see max depth = 2 for this one
> (constrain (C6 (P6)) (or (eq t1 T6g) (and (neq t1 A6a) (neq t2 T6f))))
> constrain C6 { P6 } (t1 == T6g or (t1 != A6a and t2 != T6f));
>
> CIL sees max depth = 2 for this one, but checkpolicy has max depth = 1
> (constrain (C7 (P7)) (or (and (neq t1 A7a) (neq t2 T7f)) (eq t1 T7g)))
> constrain C7 { P7 } ((t1 != A7a and t2 != T7f) or t1 == T7g);
>
> In most other examples that I have created, they had the same max depth.
>
> Both have max depth = 2 for these:
> (constrain (C1 (P1)) (or (eq t1 T1a) (and (eq t1 T1b) (eq t1 T1c))))
> constrain C1 { P1 } (t1 == T1a or (t1 == T1b and t1 == T1c));
>
> Both have max depth = 4 for these:
> (constrain (C2 (P2)) (or (eq t1 T2a) (or (eq t1 T2b) (or (eq t1 T2c)
> (and (eq t1 T2d) (eq t1 T2e))))))
> constrain C2 { P2 } (t1 == T2a or (t1 == T2b or (t1 == T2c or (t1 ==
> T2d and t1 == T2e))));
>
> Both have max depth = 3 for these:
> (constrain (C4 (P4)) (or (or (eq t1 T4a) (or (eq t1 T4b) (eq t1 T4c)))
> (or (eq t1 T4d) (and (eq t1 T4e) (eq t1 T4f)))))
> constrain C4 { P4 } ((t1 == T4a or (t1 == T4b or t1 == T4c)) or (t1 ==
> T4d or (t1 == T4e and t1 == T4f)));
>
> Both have max depth = 4 for these:
> (constrain (C8 (P8)) (or (or (or (and (neq t1 T8a) (neq t1 T8b)) (and
> (neq t1 T8c) (neq t1 T8d))) (or (and (neq t1 T8e) (neq t1 T8f)) (and
> (neq t1 T8g) (neq t1 T8h)))) (or (or (and (neq t1 T8i) (neq t1 T8j))
> (and (neq t1 T8k) (neq t1 T8l))) (or (and (neq t1 T8m) (neq t1 T8n))
> (and (neq t1 T8o) (neq t1 T8p))))))
> constrain C8 { P8 } ((((t1 != T8a and t1 != T8b) or (t1 != T8c and t1
> != T8d)) or ((t1 != T8e and t1 != T8f) or (t1 != T8g and t1 != T8h)))
> or (((t1 != T8i and t1 != T8j) or (t1 != T8k and t1 != T8l)) or ((t1
> != T8m and t1 != T8n) or (t1 != T8o and t1 != T8p))));
>
> I guess I can convert the expressions to postfix and then follow the
> logic of checkpolicy, but that seems to be a lot of work. Instead, I
> could add a second check when the binary is being created and the
> constraint expression has been turned into postfix already.



[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux