SELinuxProject / selinux

This is the upstream repository for the Security Enhanced Linux (SELinux) userland libraries and tools. The software provided by this project complements the SELinux features integrated into the Linux kernel and is used by Linux distributions. All bugs and patches should be submitted to selinux@vger.kernel.org
Other
1.35k stars 362 forks source link

Add support for a source policy HLL #54

Open stephensmalley opened 7 years ago

stephensmalley commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

On Fri, May 12, 2017 at 02:51:24PM -0700, Paul Moore wrote:

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.

I have had the impression that Chris was "looking into it", but compilers aren't his thing

Do not take this the wrong way but:

  1. .te files and .fc files indicate module policy (monolithic policy uses policy.conf and file_contexts)
  2. we should ask "users" what is more "user friendly", ohh wait I am a "user"..
  3. module policy is not very modular (compiler cannot give meaningful information needed for dep solving)
  4. cil policy is source oriented this allowes the compiler to point to a line in a file (makes .cil more modular because allows for dep solving)
  5. cil policy does not require that you "require" identifiers and access vectors which makes writing policy more pleasurable.
  6. cil policy allows one to associate type attributes with type attributes which takes away a limitation
  7. the cil language has parenthesis (that is not user friendly, i will admit (until you want to automate parsing/generation)

But to say that raw policy language is that much more user friendly than cil, i think is a bit of a stretch

If somehow the pain of parenthesis in CIL could eased a little then i think that would make a nice language for HLL

I am all for a new HLL on top of CIL, but i question whether it would be able to add compelling value without taking away much of the value of plain CIL

-- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/SELinuxProject/selinux/issues/54#issuecomment-301194287

-- Key fingerprint = 5F4D 3CDB D3F8 3652 FBD8 02D5 3B6C 5F1D 2C7B 6B02 https://sks-keyservers.net/pks/lookup?op=get&search=0x3B6C5F1D2C7B6B02 Dominick Grift

stephensmalley commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

Side note: I search regarding this topic once and found PLEASE http://www.fsl.cs.stonybrook.edu/project-please.html

On 15 May 2017 6:53 pm, "Miroslav Grepl" notifications@github.com wrote:

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?

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/SELinuxProject/selinux/issues/54#issuecomment-301535416, or mute the thread https://github.com/notifications/unsubscribe-auth/AF2QrVPfWafjNeRQCeAG7e9mEYjENHYeks5r6IMlgaJpZM4NXL53 .

stephensmalley commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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

garyttierney commented 7 years ago

ACK. Will send a message to the list.

jwcart2 commented 7 years ago

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 commented 5 years ago

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:

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(...)