Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for a source policy HLL #54

Open
stephensmalley opened this issue May 10, 2017 · 13 comments
Open

Add support for a source policy HLL #54

stephensmalley opened this issue May 10, 2017 · 13 comments

Comments

@stephensmalley
Copy link
Member

With the transition to CIL, we would like to move away from using binary policy modules/packages; they merely add overhead in time and space and create a maintenance/development burden when adding new features. There is already one SELinux feature that is not even supported in binary policy modules (xperms). Policies that are written and maintained directly in CIL do not have this problem, but CIL was designed to be an intermediate language not a language for humans and is not IMHO as human-friendly as .te files, plus there are many users already familiar with (and many existing policy modules written in) .te file syntax. Monolithic policies can already be compiled directly to CIL via checkpolicy -C, which is the approach used for Android. However we do not have a good solution for modular refpolicy-based policies in Linux distributions; those are still being compiled to binary policy modules/packages. libsemanage already supports adding new high level languages via /usr/libexec/selinux/hll; we just need one that handles source policy (.te file + .fc file concatenated or otherwise packaged together in some way). The converter would need to run m4 with all of the system definitions and headers over the source first, and then parse the result and output a CIL module. This differs from the current convertors for pp files or a complete policy.conf because those already have all macros expanded and are either already in policydb format or are compiled first to a policydb before generating CIL.

@stephensmalley
Copy link
Member Author

We probably want to also include the .if file as part of the source policy module to ensure that we use consistent headers when converting the source module to CIL. But we may still have a dependency on other content in /usr/share/selinux/devel (selinux-policy-devel) for e.g. build.conf settings, unless we pull that into policy in some way.
Disadvantage of using current source policy modules is that it would make m4 a runtime dependency.
Alternative approach for this issue would be to create a real HLL that combines the human-friendly aspects of .te file syntax with the higher level language features implemented in CIL that are rely on m4 macros currently, and then convert all of refpolicy to that language. That's the better long term solution, but may take a while.

@pcmoore
Copy link
Member

pcmoore commented May 12, 2017

Alternative approach for this issue would be to create a real HLL that combines the human-friendly aspects of .te file syntax with the higher level language features implemented in CIL that are rely on m4 macros currently, and then convert all of refpolicy to that language. That's the better long term solution, but may take a while.

Are you aware of an any efforts towards creating a SELinux policy HLL on top of CIL? I agree that this is the best long term solution, and could be very interesting, but I'm not aware of any efforts.

@ghost
Copy link

ghost commented May 14, 2017 via email

@stephensmalley
Copy link
Member Author

A real HLL is on @jwcart2 's plate but no one has started one yet AFAIK.
Agree that is the optimal long term solution, but not sure how long it will take, and don't like the idea of having to keep using and extending binary policy modules indefinitely. The only reason refpolicy is still building binary modules is because we don't have a direct {.te,.fc} -> CIL compiler/converter; we only have a .pp -> CIL converter. So providing such a compiler/converter would provide an interim means of eliminating the need to use binary modules, at which point distributions could stop building them going forward and we could stop adding new binary module versions to support new features.
Aside from syntax, CIL also intentionally omits any feature that might complicate parsing / automation, which creates more work for the user (e.g. inability to specify type lists in an allow rule, requiring creation of a separate type attribute). That's fine for its intended purpose (intermediate language) but not so great for end users. Trying to make CIL itself be the HLL seems to create a tension between making it optimal as an intermediate language vs making it optimal as a high level language. If creating a HLL with a goal of minimal disruption to users, existing documentation, and existing policies, then the logical choice would be to keep it as close to .te/policy.conf as possible, only differing where it matters (e.g. dropping requires, introducing high level support to eliminate need for m4isms, etc). So I see .te syntax as the more likely starting point for a HLL anyway.

@mgrepl
Copy link
Contributor

mgrepl commented May 15, 2017

Hello, I like this conversation. So you see as a reasonable step to provide a converter from .te -> .cil and call ".te" as a HLL for CIL?

@cgzones
Copy link
Contributor

cgzones commented May 15, 2017 via email

@stephensmalley
Copy link
Member Author

So you see as a reasonable step to provide a converter from .te -> .cil and call ".te" as a HLL for CIL?

Yes, I see that as a reasonable interim step until we have a real HLL. To be precise, it would need to take a (.te, .fc) pair and produce a CIL module. And we have to figure out what to do about the m4 macros; we either need to run m4 during policy build (as with current refpolicy builds) and then the converter just deals with postprocessed .te/.fc files, or we would need to integrate m4 as the first stage preprocessor of the converter itself. The advantage of the former is that it avoids a runtime dependency on m4 and on selinux-policy-devel; the advantage of the latter is that it allows users to directly insert, extract, and edit the original source .te/.fc files with macros and all. This reflects the fact that .te files are both higher level than CIL (wrt to syntax, support for type lists, etc) and lower level than CIL (no direct support for interfaces, requiring use of a preprocessor like m4).

@pebenito
Copy link
Member

My preference for the end goal would be to mutate refpolicy to replace m4 with HLL equivalents so interfaces are proper objects in the HLL.

@garyttierney
Copy link
Contributor

I've started prototyping a compiler (https://github.com/garyttierney/rust-csp) that takes most of the existing syntax from the kernel policy language and enhances it with the new functionality introduced by CIL. The result is a very C-style variant of CIL:

level low = s0;
level high = s1;
level_range low_high = low-high;
context ctx = user:role:type:low_high;
type_attribute my_types;

macro my_macro_name(type t) {
    // Assignment operators still a WIP
    my_types |= t;
}

block my_block {
    type my_type;
    my_macro_name(my_type);
}

abstract block_my_abstract_block {
    if !my_bool {
        // ...
    }
}

Some of the syntax used here isn't fully supported by the compiler yet, but is used to show what the parser accepts so far.

I'd like very much to get some discussion going on what a new HLL might look like beyond emulating CIL. As Dominick mentioned, there isn't much significant value in this language compared to CIL beyond syntactic sugar. There's been some higher-level implementations long before the HLL infrastructure that attempt to abstract away SELinux concepts, albeit somewhat now obsoleted by CIL (i.e. permissions in PLEASE can be replaced with CILs class mappings and class permission sets):

Has there been any design work / thoughts on this since it had last been raised? (perhaps by @jwcart2)

@stephensmalley
Copy link
Member Author

This discussion should occur on the selinux list, not in the github issue tracker.

@garyttierney
Copy link
Contributor

ACK. Will send a message to the list.

@jwcart2
Copy link
Contributor

jwcart2 commented Sep 7, 2017

Currently, I am trying to lay the foundation for a modular source policy to CIL converter. I have a lua program that can convert a fairly heavily patched modular source policy to CIL and the goal is to try to get that to work without having to modify the modular source policy first. This is not an easy task.

@garyttierney
Copy link
Contributor

garyttierney commented Oct 21, 2019

I've spent a bit of time doing some prototype work around the first half of this issue (bundling .te, .fc, and .if files into a single source policy file).

The basic idea is a parser that looks for the following:

  • interface(
  • template(
  • file_contexts( <- New Macro used to collect file contexts

And extracts their content to their respective files (.if, .fc), emitting what remains to the .te file. These can then be compiled to a .pp file using the standard module packaging tools, and that .pp file compiled straight to CIL and emitted by this new source policy compiler.

The resulting source file looks something like this:

policy_module(evolution, 2.9.1)

file_contexts(`
    HOME_DIR/\.camel_certs(/.*)?	gen_context(system_u:object_r:evolution_home_t,s0)
    HOME_DIR/\.config/evolution(/.*)?	gen_context(system_u:object_r:evolution_xdg_config_t,s0)
    HOME_DIR/\.evolution(/.*)?	gen_context(system_u:object_r:evolution_home_t,s0)
    HOME_DIR/\.local/share/evolution(/.*)?	gen_context(system_u:object_r:evolution_xdg_config_t,s0)
    ... snip ...
')

########################################
## <summary>
##	Create objects in the evolution home
##	directories with a private type.
## </summary>
## <param name="domain">
##	<summary>
##	Domain allowed access.
##	</summary>
## </param>
## <param name="private_type">
##	<summary>
##	Private file type.
##	</summary>
## </param>
## <param name="object_class">
##	<summary>
##	Class of the object being created.
##	</summary>
## </param>
## <param name="name" optional="true">
##	<summary>
##	The name of the object being created.
##	</summary>
## </param>
#
interface(`evolution_home_filetrans',`
	gen_require(`
		type evolution_home_t;
	')

	userdom_search_user_home_dirs($1)
	filetrans_pattern($1, evolution_home_t, $2, $3, $4)
')

... snip ....


## <desc>
## <p>
## Allow evolution to create and write
## user certificates in addition to
## being able to read them
## </p>
## </desc>
gen_tunable(evolution_manage_user_certs, false)

attribute_role evolution_roles;

type evolution_t;
type evolution_exec_t;
userdom_user_application_domain(evolution_t, evolution_exec_t)
role evolution_roles types evolution_t;

optional_policy(`
	wm_application_domain(evolution_t, evolution_exec_t)
')

I have an RFC patch that I'm going to send to the list shortly when I have a working version of this. Does anyone spot any immediate problems here?

The rough flow is:

-> semodule -i my.spp
   -> /usr/libexec/selinux/hll/spp -
      -> parse to .te, .if, .fc in tmpdir
          -> run /usr/share/selinux/devel/Makefile on module files in tmpdir
      -> semodule_package_to_cil(...)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants