On Wed, Apr 28, 2021 at 8:42 AM lorenzo ceragioli <lorenzo.ceragioli@xxxxxxxxxxxx> wrote: > > Hello, > > > I am still performing tests to fully understand the semantics of CIL, > here are three strange behaviours I have noticed, I would really > appreciate it if you can say if I am wrong and, in case I am not, if > they are coherent with the intended meaning of CIL constructs. > > Please note again that I am currently using the version available on > Ubuntu 18.04.5 LTS via packet manager. > > > ########################## Report ########################## > > > 1) > > > Names defined inside the body of a macro are not checked before names > defined in the namespace in which the macro is defined. For example, in > the following > > (block A > > (type a) > > (macro m () > > (type a) > > (allow a a (file (read))))) > > > (block B > > (call A.m)) > > > I would expect "a" to be resolved as the type "a" in the body of the > macro, hence to "B.a" as the allow statement and type definition are > copied into block "B". Instead it is resolved as "A.a" (I get “allow A.a > A.a”). > > Basically, it behaves like > > > (block A > > (type a) > > (macro m () > > (allow a a (file (read))))) > > (block B > > (call A.m)) > > and not like > > (block A(macro m ()(type a) > > (allow a a (file (read))))) > > (block B > > (call A.m)) > > as I expected. > > I know that the documentation saying: > > “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” > > is outdated, and that it has been proposed to change it with: > > "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" > > > But the observed behaviour is not coherent with none of these descriptions. > > Maybe this could work: > > "When resolving macros the following places are checked in this order: > > - Items passed into the macro as arguments > > - Items defined in the same namespace of the macro > > - Items defined inside the macro - Items defined in the callers namespace > > - Items defined in the global namespace" > You are correct, the observed behavior is not consistent with the documentation. I might have an idea on how to make it work as documented, but, otherwise, the documentation should be changed to reflect what actually happens. > But I think it is not an intuitive way of resolving names. > I will admit that it is somewhat arbitrary. I think that what was in mind was policy like: (block service1 (type t) (macro run ((type x)) (allow t x (CLASS1 (PERM1))) ) ) (block service2 (type t) (allow t self (CLASS2 (PERM2))) (call service1.run(t)) ) With the resulting policy being: (allow service2.t self (CLASS2 (PERM2))) (allow service1.t service2.t (CLASS1 (PERM1))) > > 2) > > Usually, names inside a macro are resolved using the definitions in the > namespace in which the macro is defined before the ones in the caller > namespace. > > I noticed that, in the following > > > (type a) > > > (macro m () > > (allow a a (file (read)))) > > > (block A > > (type a) > > (call m)) > > > the name "a" is resolved in "A", not as ".a" in the global namespace, > which is the namespace where "m" is defined. > > Hence I assumed that the rule does not apply to macros defined in the > global namespace, can you confirm? > That is as intended. I could make arguments for doing it different, but that is how it is. You can make sure the allow rule in the macro refers to the global a by using (allow .a .a (file (read))). > > 3) > > I noticed that the types declared in a macro, being copied into the > caller namespace, can be used as parameters for the macro itself. > > For example, in the following > > > (type a) > > > (block A > > (macro m ((type x)) > > (type a) > > (allow x x (file (read)))) > > ) > > > (block B > > (call A.m(a)) > > ) > > > the resulting allow rule is (allow B.a B.a (file(read))), which in my > opinion is unexpected. > That is weird. I would have expected the global a. I will have to take a look at this. Thanks for your questions! Jim > > ############################################################# > > > Thank you for your time. > > > Cheers, > > Lorenzo Ceragioli