SELinux: How to create a CIL from a TE file
For a project, I needed to compile and install a SELinux module only when necessary. Unfortunatelly, there is no versioning on stored modules; I can't check and compare with the source module. I came up with an idea: using MD5 signatures.
Modules are stored in /var/lib/selinux/Policy/active/modules/400/ModuleName/cil
The Policy can be found with sestatus
:
# sestatus SELinux status: enabled SELinuxfs mount: /sys/fs/selinux SELinux root directory: /etc/selinux Loaded policy name: targeted ...Stored modules are actually compressed CIL, which can easily been dumped with
bzcat
:
# bzcat /var/lib/selinux/targeted/active/modules/400/my-httpd/cil (typeattributeset cil_gen_require httpd_t) (typeattributeset cil_gen_require default_t) (typeattributeset cil_gen_require sysstat_log_t) (typeattributeset cil_gen_require usr_t) (allow httpd_t usr_t (file (write create unlink setattr))) (allow httpd_t default_t (file (open read))) (allow httpd_t sysstat_log_t (dir (add_name write))) (allow httpd_t sysstat_log_t (file (open create)))Piping the result to
md5sum
provides a signature.The trickiest part is transforming the source (a .te file) to a CIL. A TE files looks like:
module my-httpd 1.2; require { type httpd_t; type default_t; type sysstat_log_t; type usr_t; class dir { add_name write }; class file { open read write create unlink setattr }; } #============= httpd_t ============== allow httpd_t usr_t:file { write create unlink setattr }; allow httpd_t default_t:file { open read }; allow httpd_t sysstat_log_t:dir { add_name write }; allow httpd_t sysstat_log_t:file { create open };Hopefully, both syntax are similar, so the transformation can be achieved via
sed
with this simple program:
# remove semi-columns s/;//g # remove comments s/#.*$//g # turn multiple space chars into one s/[ \t]\+/ /g # remove leading and trailing spaces s/^ \+\| \+$// # Turn { to ( s/ *{ */ (/ # Turn } to ) s/ *}/)/ # For each declaration of new type, add a line with the typeattribute, # another line with the typeattributeset and a third line with the type. s/^type \(.\+_t\), *\(.\+\)/(typeattribute \2)\n(typeattributeset \2 (\1))\n(type \2)/ # Turn the declaration of a existing type to a typeattributeset s/^type \(.\+_t\)/(typeattributeset cil_gen_require \1)/ # Rule with 3 levels s/^\(allow\|deny\|dontaudit\) *\(.\+_t\) \(.\+\):\(.\+\) \((.\+)\)/(\1 \2 \3 (\4 \5))/ # Rule with 4 levels s/^\(allow\|deny\|dontaudit\) *\(.\+_t\) \(.\+\):\(.\+\) \(.\+\)/(\1 \2 \3 (\4 (\5)))/ # Remove any space before ) s/ \+)/)/g # Remove lines not starting with ( /^(/!dThen, to turn the TE into CIL, simply do:
# sed -f te2cil.sed source-module.teHowever, another issue arose: the order of attributes within a class.
(allow ... (file (open create)))will not provide the same signature as
(allow ... (file (create open))).
Sure enough, I could check all my sources and make sure the attributes are in alphabetical order, but I always prefer automation. So I came up with this awk file which does the trick:
NF>4 { gsub(/\(|\)/,""); for(i=5;i<=NF;i++) A[i-5]=$i; n=asort(A); C=""; for(i=5;i<=NF;i++)C=C" "A[i-4]; delete A; print "("$1,$2,$3" ("$4,"("substr(C,2)")))" }Hence, getting the signature of the CIL becomes:
# sed -f te2cil.sed source-module.te | awk -f te2cil.awk | sort | md5sum
Finally, I make sure to sort the stored module as well:
# bzcat /var/lib/selinux/targeted/active/modules/400/my-httpd/cil | sed -f te2cil.sed | awk -f te2cil.awk | sort | md5sum
Comments