Section 5.2. Types, Attributes, and Aliases


5.2. Types, Attributes, and Aliases

Types, as you might guess from the term type enforcement, are the basic building blocks for TE rules. SELinux primarily uses types to determine what access is allowed. Attributes and aliases are policy features that ease the management and use of types. We use attributes to refer to a group of types with a single identifier. For the most part, the policy language allows us to use attributes in place of types in TE rules. Aliases are a convenience mechanism that allows us to define alternate names for a type. The alias identifier and the type identifier are treated identically as far as the policy is concerned.

5.2.1. Declaring Types

We must explicitly declare a type identifier using the type statement before using it. SELinux has no predefined types; we must explicitly declare them all. For example, suppose we want to declare a type (httpd_t) we intend to use as the domain type for a Web server and another type (http_user_content_t) we intend to apply to user data files that the Web server needs to access to display their content. We make these declarations using the type statement. For example:

type httpd_t; type http_user_content;


Once declared, we can use types in security contexts, TE rules, and other policy statements where required. You can see the full syntax for the type statement in the sidebar on page 92.

Type Statement Syntax

You use the type statement to declare types and optionally, associated alias names and attributes with the type. The full syntax for a type declaration is as follows:

type type_name [ alias alias_set ] [, attribute_set] ;


type_name

An identifier for the type. The identifier can be any length and can contain ASCII characters, numbers, an underscore (_), or a period (.).

alias_set

One or more alias identifiers. Alias identifiers have the same naming restrictions as type identifiers. If more than one alias identifier is specified, a space-separated list enclosed in braces ({ }) is used (for example, alias { aliasa_t aliasb_t }).

attribute_set

One or more previously declared attribute identifiers. If more than one attribute is specified, a comma-separated list is used (for example, type bin_t, file_type, exec_type;).


Type statements are valid in monolithic policies, base loadable modules, and nonbase loadable modules. They are not valid in conditional statements.


5.2.2. Types and Attributes

As you might imagine, a large, complex policy may have many hundreds or thousands of types to represent all of the different resources on a system. The Fedora Core 4 (FC4) targeted policy, for example, which is deliberately relatively small, declares more than 800 types. Combine this with the fact that all access is denied unless explicitly allowed means that directly expressing all the allowed access between types would be verbose. This is where attributes help in the policy language. Attributes can be thought of in two ways: 1) as a property or characteristic of a type, or 2) as a group of types. In either case, the mechanism is the same.

Suppose we want to allow a backup application to have read access to all files. We start by creating a domain type of the backup application (backup_t) and giving that type allowed access to every type associated with any file:

type backup_t; allow backup_t httpd_user_content_t : file read; allow backup_t shadow_t : file read; # additional rules granting read access to every other type used with file objects


Here we give the domain type backup_t access to two file types: our httpd_user_content_t example from earlier; and the type shadow_t, which we expect to be the type of the /etc/shadow file. Both are on-disk files that a backup application must read.

To complete this example, we would have to write a rule for every other type used for any file. Depending on how many of the hundreds of declared types are ever used with a file object, we would need hundreds of allow rules to give the backup application the necessary access (one for each type). Further, every time we add a file type to the policy, we would have to remember to add an allow rule for backup_t. This is a tedious and error-prone process. Attributes makes this kind of "group access" easier to specify. By defining an attribute that we associate with all the file types and then granting access to that attribute (rather than the individual types), we can give backup_t the necessary access with a single rule.

We declare attributes with the attribute statement, as follows:

attribute file_type;


This statement declares an attribute called file_type. Types and attributes share the same namespace, so it is not possible to have a type and an attribute with the same name. Assuming that we associated the attribute file_type with all appropriate types, we can then allow backup_t read access to both of these files with a single allow rule:

allow backup_t file_type : file read;


Note

Whereas it is common to append a _t to all type names, the common convention for attributes is to have no additional suffix added to the name. Because types and attributes share the same name space, this makes it easier to recognize a type from an attribute when writing and examining TE rules.


Now instead of hundreds of allow rules, we have a single rule that grants the same access. When this policy is compiled, this rule will automatically be expanded to the hundred of rules necessary to control access based on the various file types. More important, when we define a new type for files, all we have to do is associate the new type with the file_type attribute and the domain type backup_t will automatically be given read access.

The full syntax for the attribute statement can be seen in the following sidebar.

Attribute Statement Syntax

You use the attribute statement to declare attributes. The full syntax of the attribute statement is as follows:

attribute attribute_name;


attribute_name

An identifier for the attribute. The identifier can be any length and can contain ASCII characters, numbers, an underscore (_), or a period (.) . Attributes are in the same namespace as types and aliases and therefore cannot have the same name as another type or alias.


Attribute statements are valid in monolithic policies, base loadable modules, and non-base loadable modules. They are not valid in conditional statements.


5.2.3. Associating Types and Attributes

So far, we discussed how to define types and attributes but not how to associate the two. Types are most commonly associated with attributes when the types are declared using the type statement. For example, we can associate the attribute file_type with the type httpd_user_content_t by changing the type declaration to the following:

type httpd_user_content_t, file_type;


The common way to describe this declaration is that the type httpd_user_content_t has the file_type attribute. Mechanically, this statement adds the type httpd_user_content_t to the group of types that "have" the file_type attribute, but conceptually it also changes the nature of the httpd_user_content_t type such that it now "has" access permissions based on an attribute, and not just on permissions granted to the type itself.

Just as httpd_user_content_t comes to represent files served by the Web server through use, attributes gain meaning through consistent use. In this example, we are creating an attribute, file_type, which means all file types used on permanent storage. Thus, we as policy writers can write rules for access to "all files" without having to explicitly address each and every file type.

Types are not limited to one attribute, and in normal use it is common for a type to have several associated attributes. For example, we can create the attribute httpdcontent for all files intended to be available through the Web server. The types that have the httpdcontent attribute would likely be a subset of the types with the file_type attribute. To extend our earlier example, let's look at the following statements:

type httpd_user_content_t, file_type, httpdcontent; type shadow_t, file_type; allow backup_t file_type : file read; allow httpd_t httpdcontent : file read;


We have now added two attributes to the http_user_content_t type, file_type (indicating this is a type of an on-disk file) and httpdcontent (indicating that this type is to be read by the Web server). For the more privileged type shadow_t, we associated only the attribute file_type (because allowing the Web server to display the shadow password file does not seem like a good idea!). We also have two allow rules giving the Web server and the backup program the access they need for the types associated with each attribute. The result is that the Web server (httpd_t) can read all files with the httpdcontent attribute but not other files such as shadow_t. On the other hand, the backup application (backup_t) can read all files that have the file_type attribute.

No practical limit applies to the number of attributes that a type can have and, just as with types, we can define as many or as few attributes as we want within reason.

Note

At the time of this writing, the coded limit to the number of types and attributes we may define is 232 identifiers. This is the size limit supported by the version of SELinux released with Red Hat Enterprise Linux, version 4 (RHEL4). By the time this book is published, that size will likely be changed to 216 identifiers (due to a significant optimization of SELinux memory usage). However, in practical terms, the number of types we can define is probably at most a few thousand (because the number of associated TE rules would likely become unwieldy). So, even the most complicated policy we have seen has had fewer than two thousand types and attributes declared.


In addition to associating attributes with types using the type statements, we can associate attributes to types using the typeattribute statement. This statement allows us to associate attributes to types separately from their declaration, potentially in another part of the policy that is in a separate file. For example, take our type statement for http_user_content_t from above:

type httpd_user_content_t, file_type, httpdcontent;


The following type and typeattribute statements are equivalent to the single type statement:

# The following two statements... type httpd_user_content_t; typeattribute httpd_user_content_t file_type, httpdcontent; # are equivalent to the following single statement. type httpd_user_content_t, file_type, httpdcontent;


Tip

For the first time, we used a comment in our policy statement. For the policy compiler, the pound symbol (#) indicates a comment. All text following the pound symbol to the end of the line is ignored by the compiler.


It may not be clear from this example why the typeattribute statement is needed, but as you read in later chapters, the flexibility given by this statement will become clear. Basically, this statement allows us define a type in one place and associate attributes in another, increasing the language flexibility and allowing stronger modularity in the design of policy source files.

The full syntax for the typeattribute statement can be seen on page 97.

Warning

Attributes are a convenient feature of the policy language, but they can be dangerous. Associating an attribute with a type can potentially allow a large amount of access to that type. This access may or may not be appropriate; it depends on our security goals. For example, associating a domain type with an attribute will likely give that type a large amount of access, the impact of which you may not fully understand. This is often similar to granting a process a powerful privilege. You should be certain that the access for the attribute is warranted for the associated type and be careful about the impacts of future TE rules that reference that attribute.


Typeattribute Statement Syntax

The typeattribute statement allows you to associate previously declared type and attributes. You can use this statement to associate an attribute with a type when the association is not done as part of the type declaration. The full syntax for the typeattribute statement is as follows:

typeattribute type_name attrib_names;


type_name

The name of the type to which to add the attributes. The type must be declared separately using a type statement and only one type may be specified.

attrib_names

One or more previously declared attribute identifiers. If more than one attribute is specified, a comma-separated list is used (for example, typeattribute bin_t file_type, exec_type;).


Typeattribute statements are valid in monolithic policies, base loadable modules, and non-base loadable modules. They are not valid in conditional statements.


5.2.4. Aliases

Aliases are alternate names used to refer to a type. We can use an alias anywhere that we would use a type name, including TE rules, security contexts, and labeling statements. Aliases are typically used for compatibility when making policy changes. For example, an older policy might refer to the type netscape_t. An updated policy might switch to the type name to mozilla_t, but provide netscape_t as an alias to allow older modules to correctly compile.

We declare aliases in one of two ways. The first method is as part of the type declaration using the type statement. We can declare the type mozilla_t with the alias netscape_t by using the alias keyword in the type statement, as follows:

type mozilla_t alias netscape_t, domain;


Notice that the alias declaration comes before the attributes for the type.

We can also declare aliases separately from the type declaration using the typealias statement. The following statements are equivalent to the single type statement above:

# These two statements are equivalent... type mozilla_t, domain; typealias mozilla_t alias netscape_t; # to the following single statement. type mozilla_t alias netscape_t, domain;


The typealias statement is useful when the structure of the policy makes it difficult to declare the alias as part of the type declaration. We can see the full syntax for aliases as part of type statements in the sidebar on page 92 and the full syntax for typealias in the sidebar on page 98.

Typealias Statement Syntax

The typealias statement allows you define an alias name for a type. This is an alternative method to defining the alias as part of the type declaration using the type statement. The full syntax for the typealias statement is as follows:

typealias type_name alias alias_names;


type_name

The name of the type to which to add the aliases. Types must be declared separately using the type statement, and only one type may be specified.

alias_names

One or more alias identifiers. Alias identifiers have the same naming restrictions as type identifiers. If more than one alias identifier is specified, a space-separated list enclosed in braces ({ }) is used (for example, { aliasa_t aliasb_t }).


Typealias statements are valid in monolithic policies, base loadable modules, and non-base loadable modules. They are not valid in conditional statements.


Domain Types and Other Kinds of Types

In Chapter 2, you learned that types used on processes are sometimes called "domain types." Throughout this book, we also often use other adjectives in front of the word type, such as "file type" and "directory type." All these adjectives simply refer to the way that the types are used and do not reflect any special treatment of the type in the policy language. A file type, for example, is simply a way to refer to a type used as part of the security context for files. In reality, the type could be used for other object classes, too; there is nothing intrinsic to the language that makes a type a file type or a domain type. All the types in SELinux are exactly the same and can be used to label any object class instance if the appropriate access is present.

This means, for example, that a domain type such as httpd_t could be used on both a process and a file with the addition of a few rules. Traditionally, this dual use has been avoided in SELinux policies, mainly for clarity. But, in some circumstances, we have used a type as both a domain type and a file type. The distinction is completely up to the policy writer.

In the case of domain types, however, there are some technical reasons to not use these types for files and directories. In Linux, every process has files and directories automatically created in /proc/ by the kernel. These objects are used to get and set properties about these processes. In SELinux, the type of the process is automatically used for these files and directories. That would mean that for a process with type httpd_t, if the process ID (PID) of the process were 1000, the directory /proc/1000/ and all of its files and directories would also have the type httpd_t. If the type httpd_t was also used for regular files, that would mean that granting access for other domain types to regular files of type httpd_t would also grant access to the files and directories in /proc/, with potentially unwanted side effects.





SELinux by Example(c) Using Security Enhanced Linux
SELinux by Example: Using Security Enhanced Linux
ISBN: 0131963694
EAN: 2147483647
Year: 2007
Pages: 154

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net