| subdomain.d - syntax for security profiles for the SubDomain and NetDomain components of AppArmor |
subdomain.d - syntax for security profiles for the SubDomain and NetDomain components of AppArmor
SubDomain profiles describe mandatory access rights granted to given
programs and are fed to the SubDomain policy enforcement module using
subdomain_parser(8). This man page describes the format of the SubDomain
configuration files; see subdomain(7) for an overview of SubDomain.
The following is a BNF-style description of SubDomain policy configuration files; see below for an example SubDomain policy file. SubDomain configuration files are line-oriented; # introduces a comment, similar to shell scripting languages. The exception to this rule is that #include will include the contents of a file inline to the policy; this behavior is modelled after cpp(1).
INCLUDE = '#include' ( ABS PATH | MAGIC PATH )
ABS PATH = '``' path '''' (the path is passed to open(2))
MAGIC PATH = '<' relative path '>' (the path is relative to /etc/subdomain.d/)
COMMENT = '#' TEXT
TEXT = any characters
PROFILE = [ COMMENT ... ] PROGRAM [ flags=(complain) ]'{' [ ( RESOURCE RULE | COMMENT | INCLUDE ) ... ] '}' [ SUBPROFILE ... ]
SUBPROFILE = [ COMMENT ... ] PROGRAMHAT '{' [ ( FILE RULE | COMMENT | INCLUDE ) ... ] '}'
PROGRAM = (non-whitespace characters except for ^, must start with '/')
PROGRAMHAT = PROGRAM '^' (non-whitespace characters; see change_hat(2) for a description of how this ``hat'' is used.)
RESOURCE RULE = ( FILE RULE | NETWORK RULE ) ','
FILE RULE = ( FILENAME | FILEGLOB ) ACCESS
FILENAME = (non-whitespace characters except for ?*[]{}^, must start with '/')
FILEGLOB = (non-whitespace characters, must start with '/', ?*[]{}^ have special meanings; see below.)
ACCESS = ( 'r' | 'w' | 'l' | 'ix' | 'ux' | 'px' ) ACCESS (not all combinations are allowed; see below.)
NETWORK RULE = ( 'tcp_connect' | 'tcp_accept' | 'udp_send' | 'udp_receive' ) [ ( 'to' IP | 'from' IP ) ] [ 'via' IFACE ] (Obviously, at most one 'to' and at most one 'from' is allowed per line.)
IP = NUM '.' NUM '.' NUM '.' NUM [ '/' NETMASK ] [ ':' ( PORT | PORTRANGE ) ]
NUM = [0-9]+
NETMASK = NUM [ NUM ... ] (CIDR notation)
PORT = NUM [ NUM ... ] (0-65535, inclusive)
PORTRANGE = PORT '-' PORT (low port, high port, inclusive)
IFACE = [a-z0-9]+ (name of interface; e.g., 'eth0')
To give
# comments
/path/to/program/program_name {
#include <additional/rules>
#include "/still/more/rules"
/path/name/file rwl,
#comment about bar
/path/name/bar ux,
tcp_connect to 192.168.0.2:31337 from 192.168.0.3:1025-65535,
udp_send to 192.168.0.2:53 from 192.168.0.3,
}
/path/to/program/program_name^hat_name {
/path/resource access_mode,
/path/resource access_mode,
}
All resources and programs need a full path. There may be any number
of subprofiles (``hats'') in a profile, limited only by kernel memory.
Subprofile names are limited to 974 characters. Subprofiles must be in the
same file as the parent profile. Not all profiles benefit from subprofiles
--- applications must either be written or modified to use change_hat(2)
to take advantage of subprofiles. (Both the Apache and OpenSSH daemons
provided with the Immunix Security Module have been modified to use change_hat(2).)
File permission access modes consists of combinations of the following seven modes:
gdb(1).)
This mode is useful when a confined program needs to be able to perform
a privileged operation, such as rebooting the machine. By placing the
privileged section in another executable and granting unconstrained
execution rights, it is possible to bypass the mandatory constraints
imposed on all confined processes. For more information on what is
constrained, see the subdomain(7) man page.
WARNING this should only be used in very special cases. It enables the designated child processes to be run without any SubDomain protection. Use at your own risk.
execve(2) when the
profiled program executes the resource. Instead, the executed resource
will inherit the current profile. Incompatible with Unconstrained and Discrete Profile execute entries.
This mode is useful when a confined program needs to call another confined program without gaining the permissions of the target's profile, or losing the permissions of the current profile. This mode is infrequently used.
Comments start with # and may begin at any place within a line. The comment ends when the line ends. This is the same comment style as shell scripts.
File resources may be specified with a globbing syntax similar to that used by popular shells, such as csh(1), bash(1), zsh(1).
SubDomain also performs mandatory per-process mediation of network use, similar to tcp_wrappers (hosts_access(5)). Network access control is handled a little differently than file system access control --- a process only has network use mediated by SubDomain if there are any network rules in the program's profile.
All network rules accept specifications for a ``from'' address, a ``to'' address, and an interface to use. Leaving a ``from'' or ``to'' address unspecified is the same as using ``0.0.0.0'' --- a wildcard equivalent to INADDR_ANY. Leaving the ports unspecified for a ``from'' or ``to'' address is equivalent to using the range 0-65535.
accept(2) to
accept an incoming TCP session setup handshake. An incoming connection
that does not match any of the loaded rules is rejected; if no accept
rule is loaded, the accept(2) system call is quickly rejected with
-EACCES. If the process is allowed to perform an accept(2), rejected
connections do NOT cause an error out of the system call --- the
connection is simply dropped with an RST.
connect(2) to
initiate an outgoing TCP session setup handshake. An outgoing connection
that does not match any of the loaded rules is rejected with -EACCES.
(It is a known issue that tcp_connect does not mediate TCP session
setup when only a ``via iface'' is specified; read(2) and write(2)
mediation will still occur, so explicit data transfer is impossible.)
write(2) to communicate using a UDP socket. No outgoing
packet is sent, and -EACCES is returned to the process.
(It is a known issue that udp_send does not mediate outgoing UDP
packets when only a ``via iface'' rule is specified. If the socket is
connected, read(2) and write(2) mediation will still occur; however,
explicit data transfer is possible.)
read(2) to communicate using a UDP socket. The incoming
packet is thrown away and no notice is sent to the communicating peer;
if no receive rule is loaded, the system calls are quickly rejected with
-EACCES. If the process is allowed to receive, rejected packets do NOT
cause an error out of the system call --- the packet is simply dropped.
Of special note is programs spawned by inetd(8), xinetd(8), tcpserver,
or similar programs; as the inetd will perform an accept(2) on behalf of
a configured service, the profile for inetd must include a tcp_accept
rule that allows connections to the service. In addition, if the program
spawned by the inetd uses a different profile than the inetd (strongly
recommended), then the spawned program's profile must also include a
tcp_accept or tcp_connect rule, so that the short-circuit tests
may be satisfied.
SubDomain provides an easy abstraction mechanism to group common file access requirements; this abstraction is an extremely flexible way to grant site-specific rights and makes writing new SubDomain profiles very simple by assembling the needed building blocks for any given program.
The use of '#include' is modelled directly after cpp(1); its use will replace the '#include' statement with the specified file's contents. #include ``/absolute/path'' specifies that /absolute/path should be used. #include ``relative/path'' specifies that relative/path should be used, where the path is relative to the current working directory. #include <magic/path> is the most common usage; it will load magic/file relative to a directory specified to subdomain_parser(8). /etc/subdomain.d/ is the Immunix default.
The Immunix-supplied SubDomain profiles follow several conventions; the abstractions stored in /etc/subdomain.d/abstractions/ are some large clusters that are used in most profiles. What follows are short descriptions of how some of the abstractions are used.
wtmp(5) and utmp(5)
databases, used with the w(1) and associated commands.
The abstractions stored in /etc/subdomain.d/program-chunks/ are intended for use by single programs; most networking rules have been placed in these files to facilitate better constraints. (The SubDomain network policies allow communication with all IP addresses, and restrict access to specific ports only. A system administrator may wish to allow certain services to communicate only with specific subnets.)
References to user home directories in profiles are usually confined to abstractions stored in files with names beginning with ``user-''. There are many here suitable for customization; a few notable entries:
change_hat(2) conventions that don't have a more specific
subprofile in Apache's profile.
An example SubDomain profile:
# a comment about foo.
/usr/bin/foo {
/bin/mount ux,
/dev/{,u}random r,
/etc/ld.so.cache r,
/etc/foo.conf r,
/etc/foo/* r,
/lib/ld-*.so* x,
/lib/lib*.so* r,
/proc/[0-9]** r,
/usr/lib/** r,
/tmp/foo.pid wr,
/tmp/foo.* lrw,
}
# a comment about foo's subprofile, bar.
/usr/bin/foo^bar {
/lib/ld-*.so* x,
/usr/bin/bar x,
/var/spool/* rwl,
}
subdomain(7), complain(1), enforce(1), subdomain_parser(1), and change_hat(2).
| subdomain.d - syntax for security profiles for the SubDomain and NetDomain components of AppArmor |