SELinux Userspace

repository·main·Indexed 23 days ago

https://github.com/selinuxproject/selinux

Utilities and system libraries for configuring and managing Mandatory Access Control (MAC) on Linux systems. Includes Python and Ruby bindings for libselinux, core components like libsepol, and a comprehensive reference for the Common Intermediate Language (CIL) used for policy representation.

Tokens
75.6K
Snippets
160
Records
478
Agent score
82%

What's inside selinux

  1. Introduction to CIL (Common Intermediate Language)

    main
    CIL (Common Intermediate Language) is the intermediate language used by SELinux for policy representation. It provides a structured way to define security policies, including access vector rules, type enforcement, and various labeling statements. The language is designed with specific goals regarding design philosophy, scalability, and ease of manipulation by tools.
  2. What is SELinux Common Intermediate Language (CIL)?

    main

    The SELinux Common Intermediate Language (CIL) is an intermediate language designed to sit between high-level policy languages (like the current module language) and the low-level kernel policy representation.

    CIL serves as a bridge that enables:

    • Cross-language interaction: Multiple high-level languages can consume and produce language constructs (like interfaces) that have more features than the raw kernel policy.
    • Domain-specific policy languages: It simplifies the creation of specialized languages such as CDS Framework, Lobster, and Shrimp.
    • Unified policy analysis: It provides a semantically rich representation that allows a single set of analysis tools to process the output of various high-level languages without losing high-level information.
  3. CIL Namespaces and the Global Namespace

    main

    CIL supports namespaces using containers like the block statement. When a block is resolved, a dot . is used to represent the parent/child relationship.

    Namespace Resolution

    • Namespaced Access: A type process inside block example_ns resolves to example_ns.process.
    • Global Namespace: Any symbol declared outside a container is in the global namespace.
    • Referencing Global Symbols: To explicitly reference a symbol in the global namespace from within a block, prefix it with a dot . (e.g., .tmpfs).
    • Implicit Resolution: If a symbol is not prefixed, CIL searches the current namespace first. If not found, it searches the global namespace.
    ; This type is the global tmpfs:
    (type tmpfs)
    
    (block file
        ; file namespace tmpfs
        (type tmpfs)
        (class file (open read write getattr))
    
        ; This rule will reference the local namespace for src and global for tgt:
        (allow tmpfs .tmpfs (file (read)))
    
        ; This rule will reference the global namespace for src and tgt:
        (allow .tmpfs .tmpfs (file (write)))
    )
  4. Define MLS levels and sensitivity categories

    main

    To define a complete MLS level, you must first associate sensitivities with categories using sensitivitycategory.

    1. Associate categories with sensitivity: (sensitivitycategory <sensitivity_id> <categoryset_id>) This statement is required before a level can be declared.

    2. Declare a level: (level <level_id> (<sensitivity_id> [<categoryset_id>])) A level combines a sensitivity and zero or more categories (via a categoryset or a list of identifiers).

    3. Declare a level range: (levelrange <levelrange_id> (<low_level_id> <high_level_id>)) Defines a range between two previously declared level identifiers.

  5. Use common identifiers to share permissions across classes

    main

    To avoid redundancy, you can define a common identifier containing a set of permissions and then associate it with one or more classes using classcommon.

    1. Define common permissions: Use (common common_id (permission_id ...)).
    2. Associate with a class: Use (classcommon class_id common_id).
    3. Add additional permissions: Use a class statement for the same class_id to add more permissions. The final set for the class will be the union of the common permissions and the class-specific permissions.

    Example:

    (common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
    (classcommon dir file)
    (class dir (add_name remove_name reparent search rmdir open audit_access execmod))

    This results in the dir class having all permissions from the file common set plus its own specific permissions.

    (common file (ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton))
    
    (classcommon dir file)
    (class dir (add_name remove_name reparent search rmdir open audit_access execmod))
  6. Key features enabled by CIL

    main

    CIL enables several advanced SELinux policy capabilities that are difficult to achieve with traditional policy languages:

    • Policy customization without breaking updates: Allows administrators to modify access (e.g., removing unwanted access) without directly modifying shipped vendor policy files, ensuring future updates can still be applied.
    • First-class interfaces: Transforms interfaces from pre-processor constructs into first-class language features. This allows compilers and analysis tools to understand them, removing the need to recompile all modules when an interface changes.
    • Rich policy relationships: Provides language features to create new types or modules based on existing ones with varying degrees of change, supporting ad-hoc creation of policy modules.
    • Policy management support: Enables management tools (like semanage) to generate and consume CIL to perform policy modifications, rather than directly manipulating private data stores and binary formats.
  7. Core design principles of CIL

    main

    CIL is designed with several key principles to ensure it remains a robust intermediate layer:

    • Intermediate focus: It provides rich semantics for cross-language interaction but avoids adding features purely for convenience if they can be handled by a high-level language.
    • Machine-first syntax: The syntax is designed to be easy for compilers, analysis tools, and policy generation tools to parse and generate. Machine processing is prioritized over human readability.
    • Faithful kernel representation: CIL aims to fully and faithfully represent the kernel policy without obscuring or hiding the essence of kernel enforcement. It acts like "portable assembler" rather than a pure functional language.
    • Source-oriented workflow: CIL assumes a source-policy-oriented world. Binary formats should only be used for communication with the kernel.
    • Declarative and order-independent: Like existing SELinux policies, CIL maintains a declarative, order-independent style.
    • Elimination of M4: CIL is intended to eliminate the need for M4 and other pre-processors to avoid side-effect issues.
    • Single compilation unit: The language is processed as a single compilation unit rather than module-by-module to simplify processing and improve error reporting.
  8. CIL Expressions and Prefix Notation

    main

    CIL expressions use prefix (Polish) notation, which may be nested. This differs from the kernel policy language, which uses infix notation.

    Expression Syntax

    • expr_set = (name ... | expr ...)
    • expr = (expr_key expr_set ...)

    Supported Keys by Statement Type

    expr_keyclasspermissionset / roleattributeset / typeattributesetcategorysetbooleanif / tunableifconstrain / mlsconstrain / validatetrans / mlsvalidatetrans
    domX
    dombyX
    incompX
    eqXX
    neXX
    andXXXX
    orXXXX
    notXXXX
    xorXXX
    allXXX
    rangeX

    Usage Examples

    Type Attributes with Logic

    (typeattributeset all_fs_type_except_usermodehelper_and_proc_security
        (and
            (and
                fs_type
                (not file.usermodehelper)
            )
            (not file.proc_security)
        )
    )

    Boolean Conditionals

    (booleanif (and (not disableAudio) (not disableAudioCapture))
        (true
            (allow process device.audio_capture_device (chr_file_set (rw_file_perms)))
        )
    )

    Constraints (MLS/Transition)

    ; Process read operations: No read up unless trusted.
    (mlsconstrain (process (getsched getsession getpgid getcap getattr ptrace share))
        (or (dom l1 l2) (eq t1 mlstrustedsubject)))
  9. Map multiple classes and permissions using classmap

    main

    A classmap allows you to group multiple classmapping identifiers. This is useful for rules that support a list of classes (like typetransition, typechange, etc.) or for linking multiple classpermissionsets to a single rule.

    1. Define the map: (classmap classmap_id (classmapping_id ...))
    2. Define mappings: (classmapping classmap_id classmapping_id classpermissionset_id)

    Example:

    (classmap android_classes (set_1 set_2))
    
    (classmapping android_classes set_1 (binder (all)))
    (classmapping android_classes set_1 (property_service (set)))
    
    (allow type_1 self (android_classes (set_1)))

    This allow rule will resolve into multiple AV rules, one for each mapping in set_1.

    (classmap android_classes (set_1 set_2))
    (classmapping android_classes set_1 (binder (all)))
    (classmapping android_classes set_1 (property_service (set)))
  10. CIL Declarations and Definitions

    main

    CIL uses declarations to create objects and definitions to build upon them.

    Declarations

    Declarations can be named or anonymous:

    • Named Declarations: Create new objects with an identifier. Examples include (type process), (typeattribute domain), and (class file (read write)).
    • Explicit Anonymous Declarations: Currently restricted to IP addresses (e.g., (127.0.0.1) or (::1)).
    • Anonymous Declarations: Reference objects that have already been declared.

    Definitions

    Definitions build on existing objects. They can be repeated multiple times; duplicates are resolved to a single definition during compilation.

    • Example: (typeattributeset domain (process)) adds the type process to the attribute domain.
    • Example: (allow domain process (file (read write)))) adds an access rule.
  11. Understand the CIL syntax and structure

    main

    CIL's design focuses on simplicity and regularity through the following characteristics:

    1. S-expression based: The syntax is extremely regular and easy to parse because it is based on s-expressions.
    2. Minimalist statements: Statements are reduced to the bare minimum, with exactly one way to express any given syntax.
    3. Unambiguous: Statements are unambiguous and have well-defined overlaps, avoiding the context-dependent declarations found in older policy languages.
    4. Declarative: The language is declarative and removes ordering constraints.

    Note on Semantics: CIL preserves the current kernel policy almost unchanged (using different syntax) and layers on features from the module language and reference policy. While it introduces new constructs for managing namespaces, existing concepts like types retain their current semantics.

  12. Understand Access Vector (AV) Rules in CIL

    main

    Access Vector rules define the relationship between a source type, a target type, and specific class permissions or extended permissions.

    Rule Structure: (av_flavor source_id target_id|self|notself|other classpermission_id|permissionx_id)

    Key Components:

    • av_flavor: The type of rule (e.g., allow, deny, neverallow).
    • source_id: A previously defined type, typealias, or typeattribute.
    • target_id: A type, typealias, or typeattribute. Special keywords include:
      • self: The source and target are the same. If the source is an attribute, each type in the attribute is paired with itself.
      • notself: The target is all types except those in the source.
      • other: A shorthand for a rule where each type in the source is paired with all other types in the source as the target.
    • classpermission_id: A classpermissionset or a set of classmap/classmapping identifiers (used for standard rules).
    • permissionx_id: A permissionx identifier (used for extended permission rules).