Bug (?) report for secilc and CIL semantics: some unexpected behaviours

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

 



To Whom it may concern,

I am performing some tests to fully understand the semantics of CIL, and I have noticed some strange behaviours that may be erroneous. Please note that I am currently using the version available on Ubuntu 18.04.5 LTS via packet manager, hence some of the problems (if they are problems) may be already solved. Moreover, I am focusing on policies that only use types, and the procedure I have used for testing is simply to compile the .cil file with secilc and check which allow rules are found by "sesearch --allow".

I decided to send this email instead of opening issues on github, please let me know if I was wrong.

The strange behaviours that I have observed follows:

############ Report ############

1) The manual says "Note that when resolving macros the callers namespace is not checked, only the following places:

    •Items defined inside the macro
    •Items passed into the macro as arguments
    •Items defined in the same namespace of the macro
    •Items defined in the global namespace"

like in the following

(type a)

(block B
     (type a)
     (macro m ()
                (allow a a perms)))

(block A
      (type a)
      (call B.m))

Where you get "allow B.a B.a perms" instead of "allow A.a A.a perms"

BUT, according to my experiments this seems to work only if types are locally defined in the macro namespace, whereas the caller namespace is checked if they are defined in the global namespace or undefined. Two examples follows:

Ex 1.1

(block A
     (macro m1 ()
               (allow a a perms))
)

(block B
     (type a)
     (call A.m1)
)

Ideally this should not compile (because type a is not defined in A namespace nor in the global namespace), instead we get allow B.a B.a

Ex 1.2

(type a)

(macro m ()
    (allow a a perms))

(block A
      (type a)
      (call m))

Ideally the "a" inside the macro should refer to the "a" type in the global namespace, and we should get "allow .a .a", instead we get "allow A.a A.a"

Question:

Is this the intended behaviour?

For this point I see that there is already a report (in the mailing list) for asking to modify the manual, writing

"When resolving macros the following places are checked in this order:
    •Items defined inside the macro
    •Items passed into the macro as arguments
    •Items defined in the same namespace of the macro
    •Items defined in the callers namespace
    •Items defined in the global namespace"

As far as I can see, the CIL Reference Guide has not been updated. Have you decided to change the semantics of CIL (i.e. the behaviour of secilc) instead of the documentation?


2) The CIL Wiki says, regarding inheritance of multiple macros with the same name "Inheritance causes all of the macros to be merged into a single macro with the union of the access". I think this is not the case, like in the following example:

Ex 2.1

(type c)

(block A
        (type a)
        (macro m1 ()
                (allow a c perms)))

(block B
        (type b)
        (macro m1 ()
                (allow b c perms)))

(block C
        (blockinherit A)
        (blockinherit B)
        (call m1))

In theory I should get both "allow C.a .c perms" and "C.b .c perms", but I only get the first one.

According to my tests I get the one that is declared first (it is also inherited first, but this does not seem to be relevant).

Question:

Is this a bug?
If not (I see that CIL Wiki is not maintained since CIL is merged into SELinux repository), which is the criterion for choosing which macro to take (is it really "first defined wins")?



3) Types resulting from a macro call may be used inside a macro definition, like in the following

(type a)

(block A
     (macro m ()
          (allow a a perms))

     (call m1))

(macro m1()
     (type a))

(block B
     (call A.m))

Here the "a" in macro "m" is resolved to the local type "a" that is introduced because of a call to macro "m1", hence you get "allow A.a A.a Perms" instead of "allow .a .a Perms", as it would have been if names in "m" were resolved before calling "m1".

BUT, this lead to a strange behaviour when circular definitions are considered, as in the following example

Ex 3.1

(type a)
(type b)

(block A
     (macro m ()
         (type b)
         (allow a a perms))

     (call B.m1)
)

(block B
     (macro m1()
          (type a)
          (allow b b perms))

     (call A.m)
)

where you get "allow A.a A.a Perms" and "allow B.b B.b Perms" even if there is no evaluation order of the macros that transforms the code in such way (given that the names inside the macros are evaluated before copying the code, as stated in (1)) Depending on the evaluation order, the result should be one of the following:

a) if you evaluate "m" before "m1"


(type a)
(type b)

(block A
     (type a)
     (allow B.b B.b perms))
)
(block B
    (type b)
     (allow .a .a perms)
)

b) if you evaluate "m1" before "m"

(type a)
(type b)

(block A
     (type a)
     (allow .b .b perms))
)
(block B
    (type b)
     (allow A.a A.a perms)
)

Question:

I am not sure this is not exactly the behaviour you want, but in case I would like to have a confirmation.

4) I see that something like late binding is used for names in block inheritance, like in the following

(type a)
    (block A
           (type b)
       (allow a b perms))

    (block B
          (blockinherit A)
      (type a))

in which we get “allow B.a B.b perms” instead of “allow .a B.b perms”.

Question:

Given the static resolution of names in macros I wonder if this is intentional.

############ End of the report ############


Thank you for your time,
I am available for any questions.

Cheers,
    Lorenzo Ceragioli



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

  Powered by Linux