2006-04-11 21:52:54 +00:00
%{
/*
2007-04-11 08:12:51 +00:00
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* NOVELL (All rights reserved)
2012-02-24 04:21:59 -08:00
* Copyright (c) 2010-2012
* Canonical Ltd.
2006-04-11 21:52:54 +00:00
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
2010-06-04 18:57:01 -07:00
* along with this program; if not, contact Canonical, Ltd.
2006-04-11 21:52:54 +00:00
*/
#define YYERROR_VERBOSE 1
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <errno.h>
#include <fcntl.h>
2014-01-06 14:46:10 -08:00
#include <sys/apparmor.h>
2014-04-23 11:35:29 -07:00
#include <iostream>
2006-04-11 21:52:54 +00:00
/* #define DEBUG */
2020-07-03 02:19:41 -07:00
#include "capability.h"
2020-04-24 17:43:47 -07:00
#include "lib.h"
2006-04-11 21:52:54 +00:00
#include "parser.h"
2013-09-27 16:16:37 -07:00
#include "profile.h"
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
#include "mount.h"
2013-07-31 09:05:51 -07:00
#include "dbus.h"
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
#include "af_unix.h"
2010-06-04 18:47:44 -07:00
#include "parser_include.h"
2006-04-11 21:52:54 +00:00
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define CIDR_32 htonl(0xffffffff)
#define CIDR_24 htonl(0xffffff00)
#define CIDR_16 htonl(0xffff0000)
#define CIDR_8 htonl(0xff000000)
2009-08-20 15:27:12 +00:00
/* undefine linux/capability.h CAP_TO_MASK */
#ifdef CAP_TO_MASK
#undef CAP_TO_MASK
#endif
#define CAP_TO_MASK(x) (1ull << (x))
2006-04-11 21:52:54 +00:00
2016-05-31 15:38:36 -05:00
#define EXEC_MODE_EMPTY 0
#define EXEC_MODE_UNSAFE 1
#define EXEC_MODE_SAFE 2
2012-02-16 07:59:23 -08:00
int parser_token = 0;
2021-06-09 00:56:59 -07:00
struct cod_entry *do_file_rule(char *id, perms_t perms, char *link_id, char *nt);
2014-04-07 03:16:50 -07:00
mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
struct cond_entry *dst_conds, char *dst,
2021-06-09 00:56:59 -07:00
perms_t perms);
2014-04-07 03:16:50 -07:00
mnt_rule *do_pivot_rule(struct cond_entry *old, char *root,
char *transition);
2020-04-24 17:43:47 -07:00
static void abi_features(char *filename, bool search);
2008-04-16 04:45:02 +00:00
2006-04-11 21:52:54 +00:00
%}
%token TOK_ID
2012-02-16 07:51:33 -08:00
%token TOK_CONDID
2013-07-31 09:05:51 -07:00
%token TOK_CONDLISTID
2012-01-02 16:49:31 -08:00
%token TOK_CARET
2006-04-11 21:52:54 +00:00
%token TOK_OPEN
%token TOK_CLOSE
%token TOK_MODE
%token TOK_END_OF_RULE
%token TOK_EQUALS
2007-11-16 09:37:31 +00:00
%token TOK_ARROW
2006-04-11 21:52:54 +00:00
%token TOK_ADD_ASSIGN
2008-04-06 18:55:46 +00:00
%token TOK_LE
2006-04-11 21:52:54 +00:00
%token TOK_SET_VAR
%token TOK_BOOL_VAR
%token TOK_VALUE
%token TOK_IF
%token TOK_ELSE
%token TOK_NOT
%token TOK_DEFINED
2007-06-26 21:10:28 +00:00
%token TOK_CHANGE_PROFILE
2007-07-27 20:29:47 +00:00
%token TOK_NETWORK
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
%token TOK_UNIX
%token TOK_CREATE
%token TOK_SHUTDOWN
%token TOK_ACCEPT
%token TOK_CONNECT
%token TOK_LISTEN
%token TOK_SETOPT
%token TOK_GETOPT
%token TOK_SETATTR
%token TOK_GETATTR
2007-07-27 20:48:24 +00:00
%token TOK_HAT
2007-07-27 20:55:25 +00:00
%token TOK_UNSAFE
2010-12-20 11:58:05 -08:00
%token TOK_SAFE
2006-04-11 21:52:54 +00:00
%token TOK_COLON
2007-11-16 09:37:31 +00:00
%token TOK_LINK
2007-11-29 18:06:53 +00:00
%token TOK_OWNER
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
%token TOK_OTHER
2008-03-13 16:49:10 +00:00
%token TOK_SUBSET
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
%token TOK_AUDIT
%token TOK_DENY
2013-09-20 06:48:56 -07:00
%token TOK_ALLOW
2008-04-06 18:54:52 +00:00
%token TOK_PROFILE
2008-04-06 18:55:27 +00:00
%token TOK_SET
2008-04-09 09:03:17 +00:00
%token TOK_ALIAS
2008-04-09 09:04:08 +00:00
%token TOK_PTRACE
2012-01-02 16:48:34 -08:00
%token TOK_OPENPAREN
%token TOK_CLOSEPAREN
2012-02-16 07:49:12 -08:00
%token TOK_COMMA
2012-02-16 08:06:04 -08:00
%token TOK_FILE
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
%token TOK_MOUNT
%token TOK_REMOUNT
%token TOK_UMOUNT
%token TOK_PIVOTROOT
2012-03-26 06:17:40 -07:00
%token TOK_IN
2013-07-31 09:05:51 -07:00
%token TOK_DBUS
2014-04-23 11:35:29 -07:00
%token TOK_SIGNAL
2013-07-31 09:05:51 -07:00
%token TOK_SEND
%token TOK_RECEIVE
%token TOK_BIND
%token TOK_READ
%token TOK_WRITE
parser: Add dbus eavesdrop permission support to apparmor_parser
Allows for the policy writer to grant permission to eavesdrop on the
specified bus. Some example rules for granting the eavesdrop permission
are:
# Grant send, receive, bind, and eavesdrop
dbus,
# Grant send, receive, bind, and eavesdrop on the session bus
dbus bus=session,
# Grant send and eavesdrop on the system bus
dbus (send eavesdrop) bus=system,
# Grant eavesdrop on any bus
dbus eavesdrop,
Eavesdropping rules can contain the bus conditional. Any other
conditionals are not compatible with eavesdropping rules and the parser
will return an error.
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-12-06 11:17:43 -08:00
%token TOK_EAVESDROP
2013-07-31 09:05:51 -07:00
%token TOK_PEER
2014-04-23 11:38:04 -07:00
%token TOK_TRACE
%token TOK_TRACEDBY
%token TOK_READBY
2018-09-19 01:15:49 -07:00
%token TOK_ABI
2022-09-29 17:40:18 -03:00
%token TOK_USERNS
2022-02-07 19:15:11 -03:00
%token TOK_MQUEUE
%token TOK_DELETE
2023-03-20 12:28:53 -03:00
%token TOK_IO_URING
%token TOK_OVERRIDE_CREDS
%token TOK_SQPOLL
2023-09-21 20:39:27 -07:00
%token TOK_ALL
2006-04-11 21:52:54 +00:00
2008-04-06 18:55:46 +00:00
/* rlimits */
%token TOK_RLIMIT
%token TOK_SOFT_RLIMIT
%token TOK_RLIMIT_CPU
%token TOK_RLIMIT_FSIZE
%token TOK_RLIMIT_DATA
%token TOK_RLIMIT_STACK
%token TOK_RLIMIT_CORE
%token TOK_RLIMIT_RSS
%token TOK_RLIMIT_NOFILE
%token TOK_RLIMIT_OFILE
%token TOK_RLIMIT_AS
%token TOK_RLIMIT_NPROC
%token TOK_RLIMIT_MEMLOCK
%token TOK_RLIMIT_LOCKS
%token TOK_RLIMIT_SIGPENDING
%token TOK_RLIMIT_MSGQUEUE
%token TOK_RLIMIT_NICE
%token TOK_RLIMIT_RTPRIO
2006-04-11 21:52:54 +00:00
/* capabilities */
%token TOK_CAPABILITY
/* debug flag values */
%token TOK_FLAGS
2014-04-07 03:16:50 -07:00
%code requires {
2014-04-23 11:36:26 -07:00
#include "parser.h"
2014-04-07 03:16:50 -07:00
#include "profile.h"
#include "mount.h"
#include "dbus.h"
2014-04-23 11:35:29 -07:00
#include "signal.h"
2014-04-23 11:38:04 -07:00
#include "ptrace.h"
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
#include "af_unix.h"
2022-09-29 17:40:18 -03:00
#include "userns.h"
2022-02-07 19:15:11 -03:00
#include "mqueue.h"
2023-03-20 12:28:53 -03:00
#include "io_uring.h"
2023-06-26 14:39:39 -03:00
#include "network.h"
2023-09-21 20:39:27 -07:00
#include "all_rule.h"
2014-04-07 03:16:50 -07:00
}
2006-04-11 21:52:54 +00:00
%union {
char *id;
2007-11-16 09:31:33 +00:00
char *flag_id;
2006-04-11 21:52:54 +00:00
char *mode;
2023-06-26 14:39:39 -03:00
network_rule *network_entry;
2013-09-27 16:16:37 -07:00
Profile *prof;
2006-04-11 21:52:54 +00:00
struct cod_net_entry *net_entry;
struct cod_entry *user_entry;
2014-04-07 03:16:50 -07:00
mnt_rule *mnt_entry;
dbus_rule *dbus_entry;
2014-04-23 11:35:29 -07:00
signal_rule *signal_entry;
2014-04-23 11:38:04 -07:00
ptrace_rule *ptrace_entry;
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
unix_rule *unix_entry;
2022-09-29 17:40:18 -03:00
userns_rule *userns_entry;
2022-02-07 19:15:11 -03:00
mqueue_rule *mqueue_entry;
2023-03-20 12:28:53 -03:00
io_uring_rule *io_uring_entry;
2023-09-21 20:39:27 -07:00
all_rule *all_entry;
2021-09-04 03:46:23 -07:00
prefix_rule_t *prefix_entry;
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
2013-09-27 16:16:37 -07:00
flagvals flags;
2021-06-09 00:56:59 -07:00
perms_t fperms;
2009-08-20 15:27:12 +00:00
uint64_t cap;
2007-07-27 20:29:47 +00:00
unsigned int allowed_protocol;
2006-04-11 21:52:54 +00:00
char *set_var;
char *bool_var;
char *var_val;
struct value_list *val_list;
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
struct cond_entry *cond_entry;
2014-04-23 11:36:26 -07:00
struct cond_entry_list cond_entry_list;
2006-04-11 21:52:54 +00:00
int boolean;
2013-09-12 13:26:13 -07:00
struct prefixes prefix;
2021-04-20 01:32:41 -07:00
IncludeCache_t *includecache;
2021-08-28 02:11:11 -07:00
audit_t audit;
2021-09-09 01:42:51 -07:00
rule_mode_t rule_mode;
2006-04-11 21:52:54 +00:00
}
%type <id> TOK_ID
2012-02-16 07:53:04 -08:00
%type <id> TOK_CONDID
2013-07-31 09:05:51 -07:00
%type <id> TOK_CONDLISTID
2006-04-11 21:52:54 +00:00
%type <mode> TOK_MODE
2021-06-09 00:56:59 -07:00
%type <fperms> file_perms
2013-09-27 16:16:37 -07:00
%type <prof> profile_base
%type <prof> profile
%type <prof> rules
2023-02-19 02:41:22 -08:00
%type <prof> block
2013-09-27 16:16:37 -07:00
%type <prof> hat
%type <prof> local_profile
%type <prof> cond_rule
2007-07-27 20:29:47 +00:00
%type <network_entry> network_rule
2006-04-11 21:52:54 +00:00
%type <user_entry> rule
2012-02-16 08:06:04 -08:00
%type <user_entry> file_rule
%type <user_entry> file_rule_tail
%type <user_entry> link_rule
2010-12-20 11:58:05 -08:00
%type <user_entry> frule
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
%type <mnt_entry> mnt_rule
%type <cond_entry> opt_conds
%type <cond_entry> cond
2014-04-23 11:36:26 -07:00
%type <cond_entry_list> cond_list
%type <cond_entry_list> opt_cond_list
2006-04-11 21:52:54 +00:00
%type <flags> flags
%type <flags> flagvals
%type <flags> flagval
2007-11-16 09:32:38 +00:00
%type <cap> caps
2006-04-11 21:52:54 +00:00
%type <cap> capability
2007-06-26 21:10:28 +00:00
%type <user_entry> change_profile
2006-04-11 21:52:54 +00:00
%type <set_var> TOK_SET_VAR
%type <bool_var> TOK_BOOL_VAR
%type <var_val> TOK_VALUE
%type <val_list> valuelist
%type <boolean> expr
2007-11-16 09:30:08 +00:00
%type <id> id_or_var
2015-07-10 18:11:17 -07:00
%type <id> opt_id_or_var
2008-03-13 16:49:10 +00:00
%type <boolean> opt_subset_flag
2021-08-28 02:11:11 -07:00
%type <audit> opt_audit_flag
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
%type <boolean> opt_owner_flag
2008-04-06 18:54:52 +00:00
%type <boolean> opt_profile_flag
2012-02-16 07:49:12 -08:00
%type <boolean> opt_flags
2021-09-09 01:42:51 -07:00
%type <rule_mode> opt_rule_mode
2010-12-20 11:49:42 -08:00
%type <id> opt_id
2013-09-12 13:26:13 -07:00
%type <prefix> opt_prefix
2021-06-09 00:56:59 -07:00
%type <fperms> dbus_perm
%type <fperms> dbus_perms
%type <fperms> opt_dbus_perm
2013-07-31 09:05:51 -07:00
%type <dbus_entry> dbus_rule
2021-09-04 03:46:23 -07:00
%type <prefix_entry> prefix_rule
2021-06-09 00:56:59 -07:00
%type <fperms> signal_perm
%type <fperms> signal_perms
%type <fperms> opt_signal_perm
2014-04-23 11:35:29 -07:00
%type <signal_entry> signal_rule
2021-06-09 00:56:59 -07:00
%type <fperms> ptrace_perm
%type <fperms> ptrace_perms
%type <fperms> opt_ptrace_perm
2014-04-23 11:38:04 -07:00
%type <ptrace_entry> ptrace_rule
2021-06-09 00:56:59 -07:00
%type <fperms> net_perm
%type <fperms> net_perms
%type <fperms> opt_net_perm
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
%type <unix_entry> unix_rule
2016-02-26 18:44:16 -06:00
%type <id> opt_target
2016-03-18 17:28:51 -05:00
%type <id> opt_named_transition
2016-05-31 15:38:36 -05:00
%type <boolean> opt_exec_mode
2012-02-16 08:06:04 -08:00
%type <boolean> opt_file
2021-06-09 00:56:59 -07:00
%type <fperms> userns_perm
%type <fperms> userns_perms
%type <fperms> opt_userns_perm
2022-09-29 17:40:18 -03:00
%type <userns_entry> userns_rule
2021-06-09 00:56:59 -07:00
%type <fperms> mqueue_perm
%type <fperms> mqueue_perms
%type <fperms> opt_mqueue_perm
2022-02-07 19:15:11 -03:00
%type <mqueue_entry> mqueue_rule
2023-03-20 12:28:53 -03:00
%type <fperms> io_uring_perm
%type <fperms> io_uring_perms
%type <fperms> opt_io_uring_perm
%type <io_uring_entry> io_uring_rule
2023-09-21 20:39:27 -07:00
%type <all_entry> all_rule
2006-04-11 21:52:54 +00:00
%%
2020-04-24 17:43:47 -07:00
list: preamble
{
/* make sure abi is setup */
2020-07-21 05:10:46 -07:00
if (override_features) {
if (policy_features)
aa_features_unref(policy_features);
policy_features = aa_features_ref(override_features);
} else if (policy_features == NULL) {
2020-07-09 02:43:10 -07:00
if (pinned_features) {
policy_features = aa_features_ref(pinned_features);
2020-04-24 17:43:47 -07:00
/* use default feature abi */
2020-07-09 02:43:10 -07:00
} else {
if (aa_features_new_from_string(&policy_features,
default_features_abi,
strlen(default_features_abi))) {
yyerror(_("Failed to setup default policy feature abi"));
}
2020-08-28 08:35:45 -07:00
pwarn(WARN_ABI, _("%s: File '%s' missing feature abi, falling back to default policy feature abi\n"), progname, current_filename);
2020-04-24 17:43:47 -07:00
}
}
2020-07-03 02:19:41 -07:00
if (!add_cap_feature_mask(policy_features,
CAPFLAG_POLICY_FEATURE))
yyerror(_("Failed to add policy capabilities to known capabilities set"));
2020-04-24 17:43:47 -07:00
set_supported_features();
}
profilelist;
2006-04-11 21:52:54 +00:00
profilelist: { /* nothing */ };
profilelist: profilelist profile
{
PDEBUG("Matched: list profile\n");
add_to_list($2);
};
2008-04-06 18:54:52 +00:00
opt_profile_flag: { /* nothing */ $$ = 0; }
| TOK_PROFILE { $$ = 1; }
2008-11-07 12:54:52 +00:00
| hat_start { $$ = 2; }
2008-04-06 18:54:52 +00:00
2010-12-20 11:49:42 -08:00
opt_id: { /* nothing */ $$ = NULL; }
| TOK_ID { $$ = $1; }
2015-07-10 18:11:17 -07:00
opt_id_or_var: { /* nothing */ $$ = NULL; }
| id_or_var { $$ = $1; }
2021-04-20 01:32:41 -07:00
profile_base: TOK_ID opt_id_or_var opt_cond_list flags TOK_OPEN
2006-04-11 21:52:54 +00:00
{
2021-04-20 01:32:41 -07:00
/* mid rule action
* save current cache, restore at end of block
*/
$<includecache>$ = g_includecache;
g_includecache = new IncludeCache_t();
}
rules TOK_CLOSE
{
Profile *prof = $7;
2016-03-18 17:28:51 -05:00
bool self_stack = false;
2010-12-13 16:26:38 -08:00
2013-09-27 16:16:37 -07:00
if (!prof) {
2006-04-11 21:52:54 +00:00
yyerror(_("Memory allocation error."));
}
2007-11-16 09:18:48 +00:00
2016-03-18 17:28:51 -05:00
parse_label(&self_stack, &prof->ns, &prof->name, $1, true);
2016-02-18 15:58:06 -06:00
free($1);
2016-03-18 17:28:51 -05:00
if (self_stack) {
yyerror(_("Profile names must begin with a '/' or a namespace"));
}
2015-12-15 16:41:38 -06:00
/* Honor the --namespace-string command line option */
if (profile_ns) {
2016-02-18 15:58:06 -06:00
/**
* Print warning if the profile specified a namespace
* different than the one specified with the
* --namespace-string command line option
*/
if (prof->ns && strcmp(prof->ns, profile_ns))
2020-08-28 08:35:45 -07:00
pwarn(WARN_OVERRIDE, "%s: -n %s overriding policy specified namespace :%s:\n",
2016-02-18 15:58:06 -06:00
progname, profile_ns, prof->ns);
free(prof->ns);
2015-12-15 16:41:38 -06:00
prof->ns = strdup(profile_ns);
if (!prof->ns)
yyerror(_("Memory allocation error."));
}
2013-09-27 16:16:37 -07:00
prof->attachment = $2;
2015-07-10 18:11:17 -07:00
if ($2 && !($2[0] == '/' || strncmp($2, "@{", 2) == 0))
yyerror(_("Profile attachment must begin with a '/' or variable."));
2018-12-06 10:54:46 -08:00
if ($3.name) {
if (strcmp($3.name, "xattrs") != 0)
yyerror(_("profile id: invalid conditional group %s=()"), $3.name);
free ($3.name);
2019-08-17 05:01:39 -07:00
$3.name = NULL;
2018-12-06 10:54:46 -08:00
prof->xattrs = $3;
}
prof->flags = $4;
2014-04-23 11:00:32 -07:00
if (force_complain && kernel_abi_version == 5)
/* newer abis encode force complain as part of the
* header
*/
2018-07-04 09:26:27 -07:00
prof->flags.mode = MODE_COMPLAIN;
2006-04-11 21:52:54 +00:00
2021-09-08 00:25:28 -07:00
prof->post_parse_profile();
2018-07-04 09:26:27 -07:00
prof->flags.debug(cerr);
2021-04-20 01:32:41 -07:00
/* restore previous blocks include cache */
delete g_includecache;
g_includecache = $<includecache>6;
2013-09-27 16:16:37 -07:00
$$ = prof;
2010-12-13 16:29:16 -08:00
};
2016-02-18 15:58:06 -06:00
profile: opt_profile_flag profile_base
2010-12-13 16:29:16 -08:00
{
2016-02-18 15:58:06 -06:00
Profile *prof = $2;
if ($2->ns)
PDEBUG("Matched: :%s://%s { ... }\n", $2->ns, $2->name);
2010-12-13 16:29:16 -08:00
else
2016-02-18 15:58:06 -06:00
PDEBUG("Matched: %s { ... }\n", $2->name);
2010-12-13 16:29:16 -08:00
2020-05-04 00:51:18 -07:00
if ($2->name[0] == '/')
2020-08-28 08:35:45 -07:00
pwarn(WARN_DEPRECATED, _("The use of file paths as profile names is deprecated. See man apparmor.d for more information\n"));
2020-05-04 00:51:18 -07:00
2016-02-18 15:58:06 -06:00
if ($2->name[0] != '/' && !($1 || $2->ns))
2010-12-13 16:29:16 -08:00
yyerror(_("Profile names must begin with a '/', namespace or keyword 'profile' or 'hat'."));
if ($1 == 2)
2022-03-26 16:29:37 -07:00
prof->flags.flags |= FLAG_HAT;
2013-09-27 16:16:37 -07:00
$$ = prof;
2010-12-13 16:29:16 -08:00
};
local_profile: TOK_PROFILE profile_base
{
2013-09-27 16:16:37 -07:00
Profile *prof = $2;
2010-12-13 16:29:16 -08:00
if ($2)
2013-09-27 16:16:37 -07:00
PDEBUG("Matched: local profile %s { ... }\n", prof->name);
$$ = prof;
2010-12-13 16:29:16 -08:00
};
hat: hat_start profile_base
{
2013-09-27 16:16:37 -07:00
Profile *prof = $2;
2010-12-13 16:29:16 -08:00
if ($2)
2013-09-27 16:16:37 -07:00
PDEBUG("Matched: hat %s { ... }\n", prof->name);
2018-12-06 10:54:46 -08:00
/*
* It isn't clear what a xattrs match on a hat profile
* should do, disallow it for now.
*/
if ($2->xattrs.list)
yyerror("hat profiles can't use xattrs matches");
2010-12-13 16:29:16 -08:00
2022-03-26 16:29:37 -07:00
prof->flags.flags |= FLAG_HAT;
2013-09-27 16:16:37 -07:00
$$ = prof;
2006-04-11 21:52:54 +00:00
};
2008-11-14 16:25:44 +00:00
preamble: { /* nothing */ }
| preamble alias { /* nothing */ };
| preamble varassign { /* nothing */ };
2018-09-19 01:15:49 -07:00
| preamble abi_rule { /* nothing */ };
2008-04-09 09:03:17 +00:00
alias: TOK_ALIAS TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
{
if (!new_alias($2, $4))
yyerror(_("Failed to create alias %s -> %s\n"), $2, $4);
free($2);
free($4);
};
2006-04-11 21:52:54 +00:00
varassign: TOK_SET_VAR TOK_EQUALS valuelist
{
struct value_list *list = $3;
char *var_name = process_var($1);
int err;
if (!list || !list->value)
yyerror("Assert: valuelist returned NULL");
PDEBUG("Matched: set assignment for (%s)\n", $1);
err = new_set_var(var_name, list->value);
if (err) {
2016-01-25 15:27:16 -08:00
free(var_name);
2006-04-11 21:52:54 +00:00
yyerror("variable %s was previously declared", $1);
/* FIXME: it'd be handy to report the previous location */
}
for (list = list->next; list; list = list->next) {
err = add_set_value(var_name, list->value);
2016-01-25 15:27:16 -08:00
if (err) {
free(var_name);
2006-04-11 21:52:54 +00:00
yyerror("Error adding %s to set var %s",
list->value, $1);
2016-01-25 15:27:16 -08:00
}
2006-04-11 21:52:54 +00:00
}
free_value_list($3);
free(var_name);
free($1);
}
varassign: TOK_SET_VAR TOK_ADD_ASSIGN valuelist
{
struct value_list *list = $3;
char *var_name = process_var($1);
int err;
if (!list || !list->value)
yyerror("Assert: valuelist returned NULL");
PDEBUG("Matched: additive assignment for (%s)\n", $1);
/* do the first one outside the loop, subsequent
* failures are indicative of symtab failures */
err = add_set_value(var_name, list->value);
if (err) {
2016-01-25 15:27:16 -08:00
free(var_name);
2006-04-11 21:52:54 +00:00
yyerror("variable %s was not previously declared, but is being assigned additional values", $1);
}
for (list = list->next; list; list = list->next) {
err = add_set_value(var_name, list->value);
2016-01-25 15:27:16 -08:00
if (err) {
free(var_name);
2006-04-11 21:52:54 +00:00
yyerror("Error adding %s to set var %s",
list->value, $1);
2016-01-25 15:27:16 -08:00
}
2006-04-11 21:52:54 +00:00
}
free_value_list($3);
free(var_name);
free($1);
}
varassign: TOK_BOOL_VAR TOK_EQUALS TOK_VALUE
{
int boolean, err;
char *var_name = process_var($1);
PDEBUG("Matched: boolean assignment (%s) to %s\n", $1, $3);
boolean = str_to_boolean($3);
if (boolean == -1) {
yyerror("Invalid boolean assignment for (%s): %s is not true or false",
$1, $3);
}
err = add_boolean_var(var_name, boolean);
2016-01-25 15:27:16 -08:00
free(var_name);
2006-04-11 21:52:54 +00:00
if (err) {
yyerror("variable %s was previously declared", $1);
/* FIXME: it'd be handy to report the previous location */
}
free($1);
free($3);
}
valuelist: TOK_VALUE
{
2012-02-16 08:07:28 -08:00
struct value_list *val = new_value_list($1);
if (!val)
2006-04-11 21:52:54 +00:00
yyerror(_("Memory allocation error."));
PDEBUG("Matched: value (%s)\n", $1);
2012-02-16 08:07:28 -08:00
$$ = val;
2006-04-11 21:52:54 +00:00
}
valuelist: valuelist TOK_VALUE
{
2012-02-16 08:07:28 -08:00
struct value_list *val = new_value_list($2);
if (!val)
2006-04-11 21:52:54 +00:00
yyerror(_("Memory allocation error."));
2011-09-01 11:57:54 -07:00
PDEBUG("Matched: value list\n");
2006-04-11 21:52:54 +00:00
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
list_append($1, val);
$$ = $1;
2006-04-11 21:52:54 +00:00
}
flags: { /* nothing */
2023-08-17 01:30:50 -07:00
flagvals fv;
2006-04-11 21:52:54 +00:00
2023-08-17 01:30:50 -07:00
fv.init();
2006-04-11 21:52:54 +00:00
$$ = fv;
};
2012-02-16 07:49:12 -08:00
opt_flags: { /* nothing */ $$ = 0; }
2012-02-16 07:53:04 -08:00
| TOK_CONDID TOK_EQUALS
{
if (strcmp($1, "flags") != 0)
yyerror("expected flags= got %s=", $1);
2013-09-11 02:10:31 -07:00
free($1);
2012-02-16 07:53:04 -08:00
$$ = 1;
}
2006-04-11 21:52:54 +00:00
2012-02-16 07:49:12 -08:00
flags: opt_flags TOK_OPENPAREN flagvals TOK_CLOSEPAREN
2007-11-16 09:31:33 +00:00
{
2012-02-16 07:49:12 -08:00
$$ = $3;
};
2007-11-16 09:31:33 +00:00
2012-02-16 07:49:12 -08:00
flagvals: flagvals flagval
2006-04-11 21:52:54 +00:00
{
2023-08-17 01:30:50 -07:00
$1.merge($2);
2006-04-11 21:52:54 +00:00
$$ = $1;
};
flagvals: flagval
{
$$ = $1;
};
2012-02-16 07:49:12 -08:00
flagval: TOK_VALUE
2006-04-11 21:52:54 +00:00
{
2023-08-17 01:30:50 -07:00
flagvals fv;
fv.init($1);
2007-11-16 09:31:33 +00:00
free($1);
2006-04-11 21:52:54 +00:00
$$ = fv;
};
2021-09-08 02:50:31 -07:00
opt_subset_flag: { /* nothing */ $$ = false; }
| TOK_SUBSET { $$ = true; }
| TOK_LE { $$ = true; }
2008-03-13 16:49:10 +00:00
2021-08-28 02:11:11 -07:00
opt_audit_flag: { /* nothing */ $$ = AUDIT_UNSPECIFIED; }
| TOK_AUDIT { $$ = AUDIT_FORCE; };
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
opt_owner_flag: { /* nothing */ $$ = 0; }
| TOK_OWNER { $$ = 1; };
| TOK_OTHER { $$ = 2; };
2021-09-09 01:42:51 -07:00
opt_rule_mode: { /* nothing */ $$ = RULE_UNSPECIFIED; }
| TOK_ALLOW { $$ = RULE_ALLOW; }
| TOK_DENY { $$ = RULE_DENY; }
2013-09-12 13:26:13 -07:00
2021-09-09 01:42:51 -07:00
opt_prefix: opt_audit_flag opt_rule_mode opt_owner_flag
2013-09-12 13:26:13 -07:00
{
$$.audit = $1;
2021-09-09 01:42:51 -07:00
$$.rule_mode = $2;
2013-09-12 13:26:13 -07:00
$$.owner = $3;
}
2006-04-11 21:52:54 +00:00
rules: { /* nothing */
2013-09-27 16:16:37 -07:00
Profile *prof = new Profile();
if (!prof) {
2006-04-11 21:52:54 +00:00
yyerror(_("Memory allocation error."));
}
2013-09-27 16:16:37 -07:00
$$ = prof;
2006-04-11 21:52:54 +00:00
};
2018-09-19 01:15:49 -07:00
rules: rules abi_rule { /* nothing */ }
2013-09-12 13:26:13 -07:00
rules: rules opt_prefix rule
2006-04-11 21:52:54 +00:00
{
2023-02-21 02:02:02 -08:00
const char *error;
2006-04-11 21:52:54 +00:00
PDEBUG("matched: rules rule\n");
2013-09-12 13:26:13 -07:00
PDEBUG("rules rule: (%s)\n", $3->name);
if (!$3)
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
yyerror(_("Assert: `rule' returned NULL."));
2023-09-21 20:39:27 -07:00
if (!entry_add_prefix($3, $2, error)) {
2023-02-21 02:02:02 -08:00
yyerror(_("%s"), error);
}
2013-09-12 13:26:13 -07:00
add_entry_to_policy($1, $3);
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
$$ = $1;
};
2023-02-19 02:41:22 -08:00
block: TOK_OPEN rules TOK_CLOSE
{
$$ = $2;
};
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
2023-02-19 02:41:22 -08:00
rules: rules opt_prefix block
2007-11-29 18:06:53 +00:00
{
struct cod_entry *entry, *tmp;
2013-09-12 13:26:13 -07:00
2021-08-28 02:11:11 -07:00
PDEBUG("matched: %s%s%sblock\n", $2.audit == AUDIT_FORCE ? "audit " : "",
2021-09-09 01:42:51 -07:00
$2.rule_mode == RULE_DENY ? "deny " : "", $2.owner ? "owner " : "");
2023-02-19 02:41:22 -08:00
list_for_each_safe($3->entries, entry, tmp) {
2023-02-21 02:02:02 -08:00
const char *error;
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
entry->next = NULL;
2023-09-21 20:39:27 -07:00
if (!entry_add_prefix(entry, $2, error)) {
2023-02-21 02:02:02 -08:00
yyerror(_("%s"), error);
2007-11-29 18:06:53 +00:00
}
2023-02-21 02:02:02 -08:00
/* transfer rule for now, TODO keep block and just
* apply add_prefix to block rule and have it do
* the work
*/
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
add_entry_to_policy($1, entry);
2007-11-29 18:06:53 +00:00
}
2023-02-19 02:41:22 -08:00
$3->entries = NULL;
2013-09-27 16:16:37 -07:00
// fix me transfer rules and free sub profile
2023-02-19 02:41:22 -08:00
delete $3;
2007-11-29 18:06:53 +00:00
$$ = $1;
};
2006-04-11 21:52:54 +00:00
2013-09-12 13:26:13 -07:00
rules: rules opt_prefix network_rule
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
{
2023-06-26 14:39:39 -03:00
const char *error;
if (!$3->add_prefix($2, error))
yyerror(error);
/* class members need to be updated after prefix is added */
$3->update_compat_net();
auto nm_af_unix = $3->network_map.find(AF_UNIX);
if (nm_af_unix != $3->network_map.end()) {
for (auto& entry : nm_af_unix->second) {
unix_rule *rule = new unix_rule(entry.type,
$2.audit, $2.rule_mode);
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
if (!rule)
yyerror(_("Memory allocation error."));
$1->rule_ents.push_back(rule);
}
2007-07-27 20:29:47 +00:00
}
2023-06-26 14:39:39 -03:00
$1->rule_ents.push_back($3);
2008-11-18 17:33:38 +00:00
$$ = $1;
2007-07-27 20:29:47 +00:00
}
2021-09-04 03:46:23 -07:00
prefix_rule : mnt_rule { $$ = $1; }
| dbus_rule { $$ = $1; }
| signal_rule { $$ = $1; }
| ptrace_rule { $$ = $1; }
| unix_rule { $$ = $1; }
| userns_rule { $$ = $1; }
| mqueue_rule { $$ = $1; }
2023-03-20 12:28:53 -03:00
| io_uring_rule { $$ = $1; }
2023-09-21 20:39:27 -07:00
| all_rule { $$ = $1; }
2014-04-23 11:35:29 -07:00
2021-09-04 03:46:23 -07:00
rules: rules opt_prefix prefix_rule
2022-09-29 17:40:18 -03:00
{
2021-09-04 03:28:18 -07:00
const char *error;
if (!$3->add_prefix($2, error))
yyerror(error);
2022-09-29 17:40:18 -03:00
$1->rule_ents.push_back($3);
$$ = $1;
}
2015-06-06 01:28:43 -07:00
rules: rules opt_prefix change_profile
2007-06-26 21:10:28 +00:00
{
PDEBUG("matched: rules change_profile\n");
2015-06-06 01:28:43 -07:00
PDEBUG("rules change_profile: (%s)\n", $3->name);
if (!$3)
2007-06-26 21:10:28 +00:00
yyerror(_("Assert: `change_profile' returned NULL."));
2015-06-06 01:28:43 -07:00
if ($2.owner)
yyerror(_("owner prefix not allowed on unix rules"));
2021-09-09 01:42:51 -07:00
if (($2.rule_mode == RULE_DENY) && $2.audit == AUDIT_FORCE) {
$3->rule_mode = RULE_DENY;
} else if ($2.rule_mode == RULE_DENY) {
$3->rule_mode = RULE_DENY;
2021-08-30 14:31:03 -07:00
$3->audit = AUDIT_FORCE;
2021-08-28 02:11:11 -07:00
} else if ($2.audit != AUDIT_UNSPECIFIED) {
2021-08-30 14:31:03 -07:00
$3->audit = $2.audit;
2015-06-06 01:28:43 -07:00
}
add_entry_to_policy($1, $3);
2007-06-26 21:10:28 +00:00
$$ = $1;
};
2013-09-12 13:26:13 -07:00
rules: rules opt_prefix capability
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
{
2013-09-12 13:26:13 -07:00
if ($2.owner)
2013-12-06 21:41:41 +01:00
yyerror(_("owner prefix not allowed on capability rules"));
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
2021-09-09 01:42:51 -07:00
if ($2.rule_mode == RULE_DENY && $2.audit == AUDIT_FORCE) {
2013-09-27 16:16:37 -07:00
$1->caps.deny |= $3;
2021-09-09 01:42:51 -07:00
} else if ($2.rule_mode == RULE_DENY) {
2014-10-07 12:50:23 -07:00
$1->caps.deny |= $3;
$1->caps.quiet |= $3;
} else {
2013-09-27 16:16:37 -07:00
$1->caps.allow |= $3;
2021-08-28 02:11:11 -07:00
if ($2.audit != AUDIT_UNSPECIFIED)
2014-10-07 12:50:23 -07:00
$1->caps.audit |= $3;
}
2013-09-12 13:26:13 -07:00
2006-04-11 21:52:54 +00:00
$$ = $1;
};
rules: rules hat
{
PDEBUG("Matched: hat rule\n");
if (!$2)
yyerror(_("Assert: 'hat rule' returned NULL."));
add_hat_to_policy($1, $2);
$$ = $1;
};
2008-04-16 04:45:02 +00:00
rules: rules local_profile
{
PDEBUG("Matched: hat rule\n");
if (!$2)
yyerror(_("Assert: 'local_profile rule' returned NULL."));
add_hat_to_policy($1, $2);
$$ = $1;
};
2006-04-11 21:52:54 +00:00
rules: rules cond_rule
{
PDEBUG("Matched: conditional rules\n");
$$ = merge_policy($1, $2);
}
2015-07-10 18:16:09 -07:00
rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE opt_id TOK_END_OF_RULE
2008-04-06 18:55:46 +00:00
{
rlim_t value = RLIM_INFINITY;
long long tmp;
char *end;
int limit = get_rlimit($4);
if (limit == -1)
yyerror("INVALID RLIMIT '%s'\n", $4);
if (strcmp($6, "infinity") == 0) {
value = RLIM_INFINITY;
} else {
Update apparmor's handling of rlimits for cpu limit and more natural units
Allow for rlimit cpu to specified which is now supported by the kernel.
Previously the rlimit units where limited to K, M, G and would fail when
KB, MB, GB where used. Allow for both, also allow for units on lengths
of time, by specifying "seconds", "minutes", "hours".. or any unique subset
eg. "s", "sec", "m", "min", "h", "hour" ..
NOTE:
This patch does not extend rlimits to be able to handle setting of tasks
that are confined by other profiles.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-08-10 15:53:39 -07:00
const char *kb = "KB";
const char *mb = "MB";
const char *gb = "GB";
2008-04-06 18:55:46 +00:00
tmp = strtoll($6, &end, 0);
switch (limit) {
case RLIMIT_CPU:
Update apparmor's handling of rlimits for cpu limit and more natural units
Allow for rlimit cpu to specified which is now supported by the kernel.
Previously the rlimit units where limited to K, M, G and would fail when
KB, MB, GB where used. Allow for both, also allow for units on lengths
of time, by specifying "seconds", "minutes", "hours".. or any unique subset
eg. "s", "sec", "m", "min", "h", "hour" ..
NOTE:
This patch does not extend rlimits to be able to handle setting of tasks
that are confined by other profiles.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-08-10 15:53:39 -07:00
if (!end || $6 == end || tmp < 0)
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
2015-07-10 18:16:09 -07:00
tmp = convert_time_units(tmp, SECONDS_P_MS, $7);
if (tmp == -1LL)
yyerror("RLIMIT '%s %s' < minimum value of 1s\n", $4, $6);
else if (tmp < 0LL)
Update apparmor's handling of rlimits for cpu limit and more natural units
Allow for rlimit cpu to specified which is now supported by the kernel.
Previously the rlimit units where limited to K, M, G and would fail when
KB, MB, GB where used. Allow for both, also allow for units on lengths
of time, by specifying "seconds", "minutes", "hours".. or any unique subset
eg. "s", "sec", "m", "min", "h", "hour" ..
NOTE:
This patch does not extend rlimits to be able to handle setting of tasks
that are confined by other profiles.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2011-08-10 15:53:39 -07:00
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
2015-07-10 18:16:09 -07:00
if (!$7)
2020-08-28 08:35:45 -07:00
pwarn(WARN_MISSING, _("RLIMIT 'cpu' no units specified using default units of seconds\n"));
2015-07-10 18:16:09 -07:00
value = tmp;
2008-04-07 04:26:02 +00:00
break;
2017-09-27 11:31:10 +02:00
#ifdef RLIMIT_RTTIME
2014-01-24 11:06:31 -08:00
case RLIMIT_RTTIME:
/* RTTIME is measured in microseconds */
if (!end || $6 == end || tmp < 0)
2015-07-10 18:16:09 -07:00
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
tmp = convert_time_units(tmp, 1LL, $7);
if (tmp < 0LL)
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
if (!$7)
2020-08-28 08:35:45 -07:00
pwarn(WARN_MISSING, _("RLIMIT 'rttime' no units specified using default units of microseconds\n"));
2015-07-10 18:16:09 -07:00
value = tmp;
2014-01-24 11:06:31 -08:00
break;
2017-09-27 11:31:10 +02:00
#endif
2008-04-06 18:55:46 +00:00
case RLIMIT_NOFILE:
case RLIMIT_NPROC:
case RLIMIT_LOCKS:
case RLIMIT_SIGPENDING:
2008-06-09 21:17:41 +00:00
#ifdef RLIMIT_RTPRIO
2008-04-06 18:55:46 +00:00
case RLIMIT_RTPRIO:
2015-07-10 18:16:09 -07:00
if (!end || $6 == end || $7 || tmp < 0)
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
2008-04-06 18:55:46 +00:00
value = tmp;
break;
2008-06-09 21:17:41 +00:00
#endif
#ifdef RLIMIT_NICE
2008-04-06 18:55:46 +00:00
case RLIMIT_NICE:
2015-07-10 18:16:09 -07:00
if (!end || $6 == end || $7)
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
2008-04-06 18:55:46 +00:00
if (tmp < -20 || tmp > 19)
yyerror("RLIMIT '%s' out of range (-20 .. 19) %d\n", $4, tmp);
value = tmp + 20;
break;
2008-06-09 21:17:41 +00:00
#endif
2008-04-06 18:55:46 +00:00
case RLIMIT_FSIZE:
case RLIMIT_DATA:
case RLIMIT_STACK:
case RLIMIT_CORE:
case RLIMIT_RSS:
case RLIMIT_AS:
case RLIMIT_MEMLOCK:
case RLIMIT_MSGQUEUE:
if ($6 == end || tmp < 0)
2015-07-10 18:16:09 -07:00
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
if (!$7) {
; /* use default of bytes */
} else if (strstr(kb, $7) == kb) {
2008-04-06 18:55:46 +00:00
tmp *= 1024;
2015-07-10 18:16:09 -07:00
} else if (strstr(mb, $7) == mb) {
2008-04-06 18:55:46 +00:00
tmp *= 1024*1024;
2015-07-10 18:16:09 -07:00
} else if (strstr(gb, $7) == gb) {
2008-04-06 18:55:46 +00:00
tmp *= 1024*1024*1024;
2015-07-10 18:16:09 -07:00
} else {
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7);
2008-04-06 18:55:46 +00:00
}
value = tmp;
break;
default:
yyerror("Unknown RLIMIT %d\n", $4);
}
}
$1->rlimits.specified |= 1 << limit;
$1->rlimits.limits[limit] = value;
free($4);
free($6);
$$ = $1;
};
2023-02-19 02:41:22 -08:00
cond_rule: TOK_IF expr block
2006-04-11 21:52:54 +00:00
{
2013-09-27 16:16:37 -07:00
Profile *ret = NULL;
2006-04-11 21:52:54 +00:00
PDEBUG("Matched: found conditional rules\n");
if ($2) {
2023-02-19 02:41:22 -08:00
ret = $3;
2006-04-11 21:52:54 +00:00
} else {
2023-02-19 02:41:22 -08:00
delete $3;
2006-04-11 21:52:54 +00:00
}
$$ = ret;
}
2023-02-19 02:41:22 -08:00
cond_rule: TOK_IF expr block TOK_ELSE block
2006-04-11 21:52:54 +00:00
{
2013-09-27 16:16:37 -07:00
Profile *ret = NULL;
2006-04-11 21:52:54 +00:00
PDEBUG("Matched: found conditional else rules\n");
if ($2) {
2023-02-19 02:41:22 -08:00
ret = $3;
delete $5;
2006-04-11 21:52:54 +00:00
} else {
2023-02-19 02:41:22 -08:00
ret = $5;
delete $3;
2006-04-11 21:52:54 +00:00
}
$$ = ret;
}
2023-02-19 02:41:22 -08:00
cond_rule: TOK_IF expr block TOK_ELSE cond_rule
2006-04-11 21:52:54 +00:00
{
2013-09-27 16:16:37 -07:00
Profile *ret = NULL;
2006-04-11 21:52:54 +00:00
PDEBUG("Matched: found conditional else-if rules\n");
if ($2) {
2023-02-19 02:41:22 -08:00
ret = $3;
delete $5;
2006-04-11 21:52:54 +00:00
} else {
2023-02-19 02:41:22 -08:00
ret = $5;
delete $3;
2006-04-11 21:52:54 +00:00
}
$$ = ret;
}
expr: TOK_NOT expr
{
$$ = !$2;
}
expr: TOK_BOOL_VAR
{
char *var_name = process_var($1);
int boolean = get_boolean_var(var_name);
PDEBUG("Matched: boolean expr %s value: %d\n", $1, boolean);
if (boolean < 0) {
/* FIXME check for set var */
yyerror(_("Unset boolean variable %s used in if-expression"),
$1);
}
$$ = boolean;
free(var_name);
free($1);
}
expr: TOK_DEFINED TOK_SET_VAR
{
char *var_name = process_var($2);
void *set_value = get_set_var(var_name);
PDEBUG("Matched: defined set expr %s value %lx\n", $2, (long) set_value);
$$ = !! (long) set_value;
free(var_name);
free($2);
}
expr: TOK_DEFINED TOK_BOOL_VAR
{
char *var_name = process_var($2);
int boolean = get_boolean_var(var_name);
PDEBUG("Matched: defined set expr %s value %d\n", $2, boolean);
$$ = (boolean != -1);
free(var_name);
free($2);
}
2007-11-16 09:30:08 +00:00
id_or_var: TOK_ID { $$ = $1; }
id_or_var: TOK_SET_VAR { $$ = $1; };
2006-04-11 21:52:54 +00:00
2016-02-26 18:44:16 -06:00
opt_target: /* nothing */ { $$ = NULL; }
opt_target: TOK_ARROW id_or_var { $$ = $2; };
2016-03-18 17:28:51 -05:00
opt_named_transition: { /* nothing */ $$ = NULL; }
2008-04-16 04:45:02 +00:00
| TOK_ARROW id_or_var
{
2016-03-18 17:28:51 -05:00
$$ = $2;
2008-04-16 04:45:02 +00:00
};
2012-02-16 08:06:04 -08:00
rule: file_rule { $$ = $1; }
| link_rule { $$ = $1; }
2018-09-19 01:15:49 -07:00
abi_rule: TOK_ABI TOK_ID TOK_END_OF_RULE
{
2020-04-24 17:43:47 -07:00
abi_features($2, true);
2018-09-19 01:15:49 -07:00
free($2);
2020-04-24 17:43:47 -07:00
/* $$ = nothing, not used */
}
| TOK_ABI TOK_VALUE TOK_END_OF_RULE
{
abi_features($2, false);
free($2);
/* $$ = nothing, not used */
}
2018-09-19 01:15:49 -07:00
2016-05-31 15:38:36 -05:00
opt_exec_mode: { /* nothing */ $$ = EXEC_MODE_EMPTY; }
| TOK_UNSAFE { $$ = EXEC_MODE_UNSAFE; };
| TOK_SAFE { $$ = EXEC_MODE_SAFE; };
2010-12-20 11:56:30 -08:00
2012-02-16 08:06:04 -08:00
opt_file: { /* nothing */ $$ = 0; }
| TOK_FILE { $$ = 1; }
2010-12-20 11:58:05 -08:00
2021-06-09 00:56:59 -07:00
frule: id_or_var file_perms opt_named_transition TOK_END_OF_RULE
2010-12-20 11:58:05 -08:00
{
2016-03-18 17:28:51 -05:00
$$ = do_file_rule($1, $2, NULL, $3);
2010-12-20 11:58:05 -08:00
};
2010-12-20 11:56:30 -08:00
2021-06-09 00:56:59 -07:00
frule: file_perms opt_subset_flag id_or_var opt_named_transition TOK_END_OF_RULE
2010-12-20 11:58:05 -08:00
{
if ($2 && ($1 & ~AA_LINK_BITS))
2008-04-16 04:45:02 +00:00
yyerror(_("subset can only be used with link rules."));
2016-03-18 17:28:51 -05:00
if ($4 && ($1 & AA_LINK_BITS) && ($1 & AA_EXEC_BITS))
2008-04-16 04:45:02 +00:00
yyerror(_("link and exec perms conflict on a file rule using ->"));
2016-03-18 17:28:51 -05:00
if ($4 && label_contains_ns($4) && ($1 & AA_LINK_BITS))
2008-04-16 04:45:02 +00:00
yyerror(_("link perms are not allowed on a named profile transition.\n"));
2016-03-18 17:28:51 -05:00
2010-12-20 11:58:05 -08:00
if (($1 & AA_LINK_BITS)) {
2016-03-18 17:28:51 -05:00
$$ = do_file_rule($3, $1, $4, NULL);
2010-12-20 11:58:05 -08:00
$$->subset = $2;
2008-04-16 04:45:02 +00:00
} else {
2016-03-18 17:28:51 -05:00
$$ = do_file_rule($3, $1, NULL, $4);
2008-04-16 04:45:02 +00:00
}
2007-07-27 20:55:25 +00:00
};
2012-02-16 08:06:04 -08:00
file_rule: TOK_FILE TOK_END_OF_RULE
{
2012-03-15 12:16:56 -07:00
char *path = strdup("/{**,}");
2012-03-09 04:23:25 -08:00
int perms = ((AA_BASE_PERMS & ~AA_EXEC_TYPE) |
(AA_EXEC_INHERIT | AA_MAY_EXEC));
/* duplicate to other permission set */
perms |= perms << AA_OTHER_SHIFT;
2012-02-16 08:06:04 -08:00
if (!path)
yyerror(_("Memory allocation error."));
2016-03-18 17:28:51 -05:00
$$ = do_file_rule(path, perms, NULL, NULL);
2012-02-16 08:06:04 -08:00
}
| opt_file file_rule_tail { $$ = $2; }
2016-05-31 15:38:36 -05:00
file_rule_tail: opt_exec_mode frule
2012-02-16 08:06:04 -08:00
{
2016-05-31 15:38:36 -05:00
if ($1 != EXEC_MODE_EMPTY) {
2021-06-09 00:56:59 -07:00
if (!($2->perms & AA_EXEC_BITS))
2012-02-16 08:06:04 -08:00
yyerror(_("unsafe rule missing exec permissions"));
2016-05-31 15:38:36 -05:00
if ($1 == EXEC_MODE_UNSAFE) {
2021-06-09 00:56:59 -07:00
$2->perms |= (($2->perms & AA_EXEC_BITS) << 8) &
2012-02-16 08:06:04 -08:00
ALL_AA_EXEC_UNSAFE;
}
2016-05-31 15:38:36 -05:00
else if ($1 == EXEC_MODE_SAFE)
2021-06-09 00:56:59 -07:00
$2->perms &= ~ALL_AA_EXEC_UNSAFE;
2012-02-16 08:06:04 -08:00
}
$$ = $2;
};
2021-06-09 00:56:59 -07:00
file_rule_tail: opt_exec_mode id_or_var file_perms id_or_var
2006-04-11 21:52:54 +00:00
{
/* Oopsie, we appear to be missing an EOL marker. If we
* were *smart*, we could work around it. Since we're
* obviously not smart, we'll just punt with a more
* sensible error. */
2012-02-16 08:06:04 -08:00
yyerror(_("missing an end of line character? (entry: %s)"), $2);
2006-04-11 21:52:54 +00:00
};
2015-06-06 01:27:59 -07:00
link_rule: TOK_LINK opt_subset_flag id_or_var TOK_ARROW id_or_var TOK_END_OF_RULE
2007-11-16 09:37:31 +00:00
{
struct cod_entry *entry;
2008-03-13 16:49:10 +00:00
PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5);
2016-03-18 17:28:51 -05:00
entry = new_entry($3, AA_LINK_BITS, $5);
2008-03-13 16:49:10 +00:00
entry->subset = $2;
2007-11-16 09:37:31 +00:00
PDEBUG("rule.entry: link (%s)\n", entry->name);
$$ = entry;
};
2023-08-22 18:12:29 -03:00
network_rule: TOK_NETWORK opt_net_perm opt_conds opt_cond_list TOK_END_OF_RULE
2007-07-27 20:29:47 +00:00
{
2024-01-08 16:09:13 -03:00
network_rule *entry;
2023-08-22 18:12:29 -03:00
if ($4.name) {
if (strcmp($4.name, "peer") != 0)
yyerror(_("network rule: invalid conditional group %s=()"), $4.name);
free($4.name);
}
entry = new network_rule($2, $3, $4.list);
2007-07-27 20:29:47 +00:00
$$ = entry;
}
2023-08-22 18:12:29 -03:00
network_rule: TOK_NETWORK opt_net_perm TOK_ID opt_conds opt_cond_list TOK_END_OF_RULE
2007-07-27 20:29:47 +00:00
{
2024-01-08 16:09:13 -03:00
network_rule *entry;
2023-08-22 18:12:29 -03:00
if ($5.name) {
if (strcmp($5.name, "peer") != 0)
yyerror(_("network rule: invalid conditional group %s=()"), $5.name);
free($5.name);
}
entry = new network_rule($2, $3, NULL, NULL, $4, $5.list);
2024-01-08 16:09:13 -03:00
free($3);
2007-07-27 20:29:47 +00:00
$$ = entry;
}
2023-08-22 18:12:29 -03:00
network_rule: TOK_NETWORK opt_net_perm TOK_ID TOK_ID opt_conds opt_cond_list TOK_END_OF_RULE
2007-07-27 20:29:47 +00:00
{
2024-01-08 16:09:13 -03:00
network_rule *entry;
2023-08-22 18:12:29 -03:00
if ($6.name) {
if (strcmp($6.name, "peer") != 0)
yyerror(_("network rule: invalid conditional group %s=()"), $6.name);
free($6.name);
2024-01-08 16:09:13 -03:00
}
2023-08-22 18:12:29 -03:00
entry = new network_rule($2, $3, $4, NULL, $5, $6.list);
2007-07-27 20:29:47 +00:00
free($3);
2024-01-08 16:09:13 -03:00
free($4);
2007-07-27 20:29:47 +00:00
$$ = entry;
}
2006-04-11 21:52:54 +00:00
2019-08-17 05:22:10 -07:00
cond: TOK_CONDID
{
struct cond_entry *ent;
ent = new_cond_entry($1, 0, NULL);
if (!ent)
yyerror(_("Memory allocation error."));
$$ = ent;
}
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
cond: TOK_CONDID TOK_EQUALS TOK_VALUE
{
struct cond_entry *ent;
struct value_list *value = new_value_list($3);
if (!value)
yyerror(_("Memory allocation error."));
2012-03-26 06:17:40 -07:00
ent = new_cond_entry($1, 1, value);
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
if (!ent) {
free_value_list(value);
yyerror(_("Memory allocation error."));
}
$$ = ent;
}
cond: TOK_CONDID TOK_EQUALS TOK_OPENPAREN valuelist TOK_CLOSEPAREN
{
2012-03-26 06:17:40 -07:00
struct cond_entry *ent = new_cond_entry($1, 1, $4);
if (!ent)
yyerror(_("Memory allocation error."));
$$ = ent;
}
cond: TOK_CONDID TOK_IN TOK_OPENPAREN valuelist TOK_CLOSEPAREN
{
struct cond_entry *ent = new_cond_entry($1, 0, $4);
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
if (!ent)
yyerror(_("Memory allocation error."));
$$ = ent;
}
opt_conds: { /* nothing */ $$ = NULL; }
| opt_conds cond
{
$2->next = $1;
$$ = $2;
}
2013-07-31 09:05:51 -07:00
cond_list: TOK_CONDLISTID TOK_EQUALS TOK_OPENPAREN opt_conds TOK_CLOSEPAREN
{
2014-04-23 11:36:26 -07:00
$$.name = $1;
$$.list = $4;
2013-07-31 09:05:51 -07:00
}
2014-04-23 11:36:26 -07:00
opt_cond_list: { /* nothing */ $$ = { NULL, NULL }; }
2013-07-31 09:05:51 -07:00
| cond_list { $$ = $1; }
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
mnt_rule: TOK_MOUNT opt_conds opt_id TOK_END_OF_RULE
{
$$ = do_mnt_rule($2, $3, NULL, NULL, AA_MAY_MOUNT);
}
mnt_rule: TOK_MOUNT opt_conds opt_id TOK_ARROW opt_conds TOK_ID TOK_END_OF_RULE
{
$$ = do_mnt_rule($2, $3, $5, $6, AA_MAY_MOUNT);
}
mnt_rule: TOK_REMOUNT opt_conds opt_id TOK_END_OF_RULE
{
$$ = do_mnt_rule($2, NULL, NULL, $3, AA_DUMMY_REMOUNT);
}
mnt_rule: TOK_UMOUNT opt_conds opt_id TOK_END_OF_RULE
{
$$ = do_mnt_rule($2, NULL, NULL, $3, AA_MAY_UMOUNT);
}
2016-02-26 18:44:16 -06:00
mnt_rule: TOK_PIVOTROOT opt_conds opt_id opt_target TOK_END_OF_RULE
2012-03-15 12:14:15 -07:00
{
2016-02-26 18:44:16 -06:00
$$ = do_pivot_rule($2, $3, $4);
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
}
2013-07-31 09:05:51 -07:00
dbus_perm: TOK_VALUE
{
if (strcmp($1, "bind") == 0)
$$ = AA_DBUS_BIND;
else if (strcmp($1, "send") == 0 || strcmp($1, "write") == 0)
$$ = AA_DBUS_SEND;
else if (strcmp($1, "receive") == 0 || strcmp($1, "read") == 0)
$$ = AA_DBUS_RECEIVE;
parser: Add dbus eavesdrop permission support to apparmor_parser
Allows for the policy writer to grant permission to eavesdrop on the
specified bus. Some example rules for granting the eavesdrop permission
are:
# Grant send, receive, bind, and eavesdrop
dbus,
# Grant send, receive, bind, and eavesdrop on the session bus
dbus bus=session,
# Grant send and eavesdrop on the system bus
dbus (send eavesdrop) bus=system,
# Grant eavesdrop on any bus
dbus eavesdrop,
Eavesdropping rules can contain the bus conditional. Any other
conditionals are not compatible with eavesdropping rules and the parser
will return an error.
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-12-06 11:17:43 -08:00
else if (strcmp($1, "eavesdrop") == 0)
$$ = AA_DBUS_EAVESDROP;
2013-07-31 09:05:51 -07:00
else if ($1) {
2021-06-09 00:56:59 -07:00
parse_dbus_perms($1, &$$, 1);
2013-07-31 09:05:51 -07:00
} else
$$ = 0;
if ($1)
free($1);
}
| TOK_BIND { $$ = AA_DBUS_BIND; }
| TOK_SEND { $$ = AA_DBUS_SEND; }
| TOK_RECEIVE { $$ = AA_DBUS_RECEIVE; }
| TOK_READ { $$ = AA_DBUS_RECEIVE; }
| TOK_WRITE { $$ = AA_DBUS_SEND; }
parser: Add dbus eavesdrop permission support to apparmor_parser
Allows for the policy writer to grant permission to eavesdrop on the
specified bus. Some example rules for granting the eavesdrop permission
are:
# Grant send, receive, bind, and eavesdrop
dbus,
# Grant send, receive, bind, and eavesdrop on the session bus
dbus bus=session,
# Grant send and eavesdrop on the system bus
dbus (send eavesdrop) bus=system,
# Grant eavesdrop on any bus
dbus eavesdrop,
Eavesdropping rules can contain the bus conditional. Any other
conditionals are not compatible with eavesdropping rules and the parser
will return an error.
Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2013-12-06 11:17:43 -08:00
| TOK_EAVESDROP { $$ = AA_DBUS_EAVESDROP; }
2013-07-31 09:05:51 -07:00
| TOK_MODE
{
2021-06-09 00:56:59 -07:00
parse_dbus_perms($1, &$$, 1);
2013-09-11 02:10:31 -07:00
free($1);
2013-07-31 09:05:51 -07:00
}
dbus_perms: { /* nothing */ $$ = 0; }
| dbus_perms dbus_perm { $$ = $1 | $2; }
| dbus_perms TOK_COMMA dbus_perm { $$ = $1 | $3; }
opt_dbus_perm: { /* nothing */ $$ = 0; }
| dbus_perm { $$ = $1; }
| TOK_OPENPAREN dbus_perms TOK_CLOSEPAREN { $$ = $2; }
dbus_rule: TOK_DBUS opt_dbus_perm opt_conds opt_cond_list TOK_END_OF_RULE
{
2014-04-07 03:16:50 -07:00
dbus_rule *ent;
2013-07-31 09:05:51 -07:00
2014-04-23 11:36:26 -07:00
if ($4.name) {
if (strcmp($4.name, "peer") != 0)
yyerror(_("dbus rule: invalid conditional group %s=()"), $4.name);
free($4.name);
}
ent = new dbus_rule($2, $3, $4.list);
2013-07-31 09:05:51 -07:00
if (!ent) {
yyerror(_("Memory allocation error."));
}
$$ = ent;
}
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
net_perm: TOK_VALUE
{
if (strcmp($1, "create") == 0)
$$ = AA_NET_CREATE;
else if (strcmp($1, "bind") == 0)
$$ = AA_NET_BIND;
else if (strcmp($1, "listen") == 0)
$$ = AA_NET_LISTEN;
else if (strcmp($1, "accept") == 0)
$$ = AA_NET_ACCEPT;
else if (strcmp($1, "connect") == 0)
$$ = AA_NET_CONNECT;
else if (strcmp($1, "shutdown") == 0)
$$ = AA_NET_SHUTDOWN;
else if (strcmp($1, "getattr") == 0)
$$ = AA_NET_GETATTR;
else if (strcmp($1, "setattr") == 0)
$$ = AA_NET_SETATTR;
else if (strcmp($1, "getopt") == 0)
$$ = AA_NET_GETOPT;
else if (strcmp($1, "setopt") == 0)
$$ = AA_NET_SETOPT;
else if (strcmp($1, "send") == 0 || strcmp($1, "write") == 0)
$$ = AA_NET_SEND;
else if (strcmp($1, "receive") == 0 || strcmp($1, "read") == 0)
$$ = AA_NET_RECEIVE;
else if ($1) {
2021-06-09 00:56:59 -07:00
parse_net_perms($1, &$$, 1);
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
} else
$$ = 0;
if ($1)
free($1);
}
| TOK_CREATE { $$ = AA_NET_CREATE; }
| TOK_BIND { $$ = AA_NET_BIND; }
| TOK_LISTEN { $$ = AA_NET_LISTEN; }
| TOK_ACCEPT { $$ = AA_NET_ACCEPT; }
| TOK_CONNECT { $$ = AA_NET_CONNECT; }
| TOK_SHUTDOWN { $$ = AA_NET_SHUTDOWN; }
| TOK_GETATTR { $$ = AA_NET_GETATTR; }
| TOK_SETATTR { $$ = AA_NET_SETATTR; }
| TOK_GETOPT { $$ = AA_NET_GETOPT; }
| TOK_SETOPT { $$ = AA_NET_SETOPT; }
| TOK_SEND { $$ = AA_NET_SEND; }
| TOK_RECEIVE { $$ = AA_NET_RECEIVE; }
| TOK_READ { $$ = AA_NET_RECEIVE; }
| TOK_WRITE { $$ = AA_NET_SEND; }
| TOK_MODE
{
2021-06-09 00:56:59 -07:00
parse_unix_perms($1, &$$, 1);
parser: first step implementing fine grained mediation for unix domain sockets
This patch implements parsing of fine grained mediation for unix domain
sockets, that have abstract and anonymous paths. Sockets with file
system paths are handled by regular file access rules.
The unix network rules follow the general fine grained network
rule pattern of
[<qualifiers>] af_name [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
specifically for af_unix this is
[<qualifiers>] 'unix' [<access expr>] [<rule conds>] [<local expr>] [<peer expr>]
<qualifiers> = [ 'audit' ] [ 'allow' | 'deny' ]
<access expr> = ( <access> | <access list> )
<access> = ( 'server' | 'create' | 'bind' | 'listen' | 'accept' |
'connect' | 'shutdown' | 'getattr' | 'setattr' |
'getopt' | 'setopt' |
'send' | 'receive' | 'r' | 'w' | 'rw' )
(some access modes are incompatible with some rules or require additional
parameters)
<access list> = '(' <access> ( [','] <WS> <access> )* ')'
<WS> = white space
<rule conds> = ( <type cond> | <protocol cond> )*
each cond can appear at most once
<type cond> = 'type' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<protocol cond> = 'protocol' '=' ( <AARE> | '(' ( '"' <AARE> '"' | <AARE> )+ ')' )
<local expr> = ( <path cond> | <attr cond> | <opt cond> )*
each cond can appear at most once
<peer expr> = 'peer' '=' ( <path cond> | <label cond> )+
each cond can appear at most once
<path cond> = 'path' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<label cond> = 'label' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')')
<attr cond> = 'attr' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<opt cond> = 'opt' '=' ( <AARE> | '(' '"' <AARE> '"' | <AARE> ')' )
<AARE> = ?*[]{}^ ( see man page )
unix domain socket rules are accumulated so that the granted unix
socket permissions are the union of all the listed unix rule permissions.
unix domain socket rules are broad and general and become more restrictive
as further information is specified. Policy may be specified down to
the path and label level. The content of the communication is not
examined.
Some permissions are not compatible with all unix rules.
unix socket rule permissions are implied when a rule does not explicitly
state an access list. By default if a rule does not have an access list
all permissions that are compatible with the specified set of local
and peer conditionals are implied.
The 'server', 'r', 'w' and 'rw' permissions are aliases for other permissions.
server = (create, bind, listen, accept)
r = (receive, getattr, getopt)
w = (create, connect, send, setattr, setopt)
In addition it supports the v7 kernel abi semantics around generic
network rules. The v7 abi removes the masking unix and netlink
address families from the generic masking and uses fine grained
mediation for an address type if supplied.
This means that the rules
network unix,
network netlink,
are now enforced instead of ignored. The parser previously could accept
these but the kernel would ignore anything written to them. If a network
rule is supplied it takes precedence over the finer grained mediation
rule. If permission is not granted via a broad network access rule
fine grained mediation is applied.
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2014-09-03 13:22:26 -07:00
free($1);
}
net_perms: { /* nothing */ $$ = 0; }
| net_perms net_perm { $$ = $1 | $2; }
| net_perms TOK_COMMA net_perm { $$ = $1 | $3; }
opt_net_perm: { /* nothing */ $$ = 0; }
| net_perm { $$ = $1; }
| TOK_OPENPAREN net_perms TOK_CLOSEPAREN { $$ = $2; }
unix_rule: TOK_UNIX opt_net_perm opt_conds opt_cond_list TOK_END_OF_RULE
{
unix_rule *ent;
if ($4.name) {
if (strcmp($4.name, "peer") != 0)
yyerror(_("unix rule: invalid conditional group %s=()"), $4.name);
free($4.name);
}
ent = new unix_rule($2, $3, $4.list);
if (!ent) {
yyerror(_("Memory allocation error."));
}
$$ = ent;
}
2014-04-23 11:35:29 -07:00
signal_perm: TOK_VALUE
{
if (strcmp($1, "send") == 0 || strcmp($1, "write") == 0)
$$ = AA_MAY_SEND;
else if (strcmp($1, "receive") == 0 || strcmp($1, "read") == 0)
$$ = AA_MAY_RECEIVE;
else if ($1) {
2021-06-09 00:56:59 -07:00
parse_signal_perms($1, &$$, 1);
2014-04-23 11:35:29 -07:00
} else
$$ = 0;
if ($1)
free($1);
}
| TOK_SEND { $$ = AA_MAY_SEND; }
| TOK_RECEIVE { $$ = AA_MAY_RECEIVE; }
| TOK_READ { $$ = AA_MAY_RECEIVE; }
| TOK_WRITE { $$ = AA_MAY_SEND; }
| TOK_MODE
{
2021-06-09 00:56:59 -07:00
parse_signal_perms($1, &$$, 1);
2014-04-23 11:35:29 -07:00
free($1);
}
signal_perms: { /* nothing */ $$ = 0; }
| signal_perms signal_perm { $$ = $1 | $2; }
| signal_perms TOK_COMMA signal_perm { $$ = $1 | $3; }
opt_signal_perm: { /* nothing */ $$ = 0; }
| signal_perm { $$ = $1; }
| TOK_OPENPAREN signal_perms TOK_CLOSEPAREN { $$ = $2; }
signal_rule: TOK_SIGNAL opt_signal_perm opt_conds TOK_END_OF_RULE
{
2014-04-23 11:36:26 -07:00
signal_rule *ent = new signal_rule($2, $3);
2014-04-23 11:35:29 -07:00
$$ = ent;
}
2014-04-23 11:38:04 -07:00
ptrace_perm: TOK_VALUE
{
if (strcmp($1, "trace") == 0 || strcmp($1, "write") == 0)
$$ = AA_MAY_TRACE;
else if (strcmp($1, "read") == 0)
$$ = AA_MAY_READ;
else if (strcmp($1, "tracedby") == 0)
$$ = AA_MAY_TRACEDBY;
else if (strcmp($1, "readby") == 0)
$$ = AA_MAY_READBY;
else if ($1)
2021-06-09 00:56:59 -07:00
parse_ptrace_perms($1, &$$, 1);
2014-04-23 11:38:04 -07:00
else
$$ = 0;
if ($1)
free($1);
}
| TOK_TRACE { $$ = AA_MAY_TRACE; }
| TOK_TRACEDBY { $$ = AA_MAY_TRACEDBY; }
| TOK_READ { $$ = AA_MAY_READ; }
| TOK_WRITE { $$ = AA_MAY_TRACE; }
| TOK_READBY { $$ = AA_MAY_READBY; }
| TOK_MODE
{
2021-06-09 00:56:59 -07:00
parse_ptrace_perms($1, &$$, 1);
2014-04-23 11:38:04 -07:00
free($1);
}
ptrace_perms: { /* nothing */ $$ = 0; }
| ptrace_perms ptrace_perm { $$ = $1 | $2; }
| ptrace_perms TOK_COMMA ptrace_perm { $$ = $1 | $3; }
opt_ptrace_perm: { /* nothing */ $$ = 0; }
| ptrace_perm { $$ = $1; }
| TOK_OPENPAREN ptrace_perms TOK_CLOSEPAREN { $$ = $2; }
ptrace_rule: TOK_PTRACE opt_ptrace_perm opt_conds TOK_END_OF_RULE
{
2014-04-23 11:39:59 -07:00
ptrace_rule *ent = new ptrace_rule($2, $3);
2014-04-23 11:38:04 -07:00
$$ = ent;
}
2022-09-29 17:40:18 -03:00
userns_perm: TOK_VALUE
{
if (strcmp($1, "create") == 0)
$$ = AA_USERNS_CREATE;
else
$$ = 0;
if ($1)
free($1);
}
| TOK_CREATE { $$ = AA_USERNS_CREATE; }
userns_perms: { /* nothing */ $$ = 0; }
| userns_perms userns_perm { $$ = $1 | $2; }
| userns_perms TOK_COMMA userns_perm { $$ = $1 | $3; }
opt_userns_perm: { /* nothing */ $$ = 0; }
| userns_perm { $$ = $1; }
| TOK_OPENPAREN userns_perms TOK_CLOSEPAREN { $$ = $2; }
userns_rule: TOK_USERNS opt_userns_perm opt_conds TOK_END_OF_RULE
{
userns_rule *ent = new userns_rule($2, $3);
$$ = ent;
}
2022-02-07 19:15:11 -03:00
mqueue_perm: TOK_VALUE
{
if (strcmp($1, "create") == 0)
$$ = AA_MQUEUE_CREATE;
else if (strcmp($1, "open") == 0)
$$ = AA_MQUEUE_OPEN;
else if (strcmp($1, "delete") == 0)
$$ = AA_MQUEUE_DELETE;
else if (strcmp($1, "getattr") == 0)
$$ = AA_MQUEUE_GETATTR;
else if (strcmp($1, "setattr") == 0)
$$ = AA_MQUEUE_SETATTR;
else if (strcmp($1, "write") == 0)
$$ = AA_MQUEUE_WRITE;
else if (strcmp($1, "read") == 0)
$$ = AA_MQUEUE_READ;
else if ($1) {
2021-06-09 00:56:59 -07:00
parse_mqueue_perms($1, &$$, 1);
2022-02-07 19:15:11 -03:00
} else
$$ = 0;
if ($1)
free($1);
}
| TOK_CREATE { $$ = AA_MQUEUE_CREATE; }
| TOK_OPEN { $$ = AA_MQUEUE_OPEN; }
| TOK_DELETE { $$ = AA_MQUEUE_DELETE; }
| TOK_GETATTR { $$ = AA_MQUEUE_GETATTR; }
| TOK_SETATTR { $$ = AA_MQUEUE_SETATTR; }
| TOK_WRITE { $$ = AA_MQUEUE_WRITE; }
| TOK_READ { $$ = AA_MQUEUE_READ; }
| TOK_MODE
{
2021-06-09 00:56:59 -07:00
parse_mqueue_perms($1, &$$, 1);
2022-02-07 19:15:11 -03:00
free($1);
}
mqueue_perms: { /* nothing */ $$ = 0; }
| mqueue_perms mqueue_perm { $$ = $1 | $2; }
| mqueue_perms TOK_COMMA mqueue_perm { $$ = $1 | $3; }
opt_mqueue_perm: { /* nothing */ $$ = 0; }
| mqueue_perm { $$ = $1; }
| TOK_OPENPAREN mqueue_perms TOK_CLOSEPAREN { $$ = $2; }
mqueue_rule: TOK_MQUEUE opt_mqueue_perm opt_conds TOK_END_OF_RULE
{
mqueue_rule *ent = new mqueue_rule($2, $3);
$$ = ent;
}
| TOK_MQUEUE opt_mqueue_perm opt_conds TOK_ID TOK_END_OF_RULE
{
mqueue_rule *ent = new mqueue_rule($2, $3, $4);
$$ = ent;
}
2023-03-20 12:28:53 -03:00
io_uring_perm: TOK_VALUE
{
if (strcmp($1, "override_creds") == 0)
$$ = AA_IO_URING_OVERRIDE_CREDS;
else if (strcmp($1, "sqpoll") == 0)
$$ = AA_IO_URING_SQPOLL;
else
$$ = 0;
if ($1)
free($1);
}
| TOK_OVERRIDE_CREDS { $$ = AA_IO_URING_OVERRIDE_CREDS; }
| TOK_SQPOLL { $$ = AA_IO_URING_SQPOLL; }
io_uring_perms: { /* nothing */ $$ = 0; }
| io_uring_perms io_uring_perm { $$ = $1 | $2; }
| io_uring_perms TOK_COMMA io_uring_perm { $$ = $1 | $3; }
opt_io_uring_perm: { /* nothing */ $$ = 0; }
| io_uring_perm { $$ = $1; }
| TOK_OPENPAREN io_uring_perms TOK_CLOSEPAREN { $$ = $2; }
io_uring_rule: TOK_IO_URING opt_io_uring_perm opt_conds opt_cond_list TOK_END_OF_RULE
{
io_uring_rule *ent;
ent = new io_uring_rule($2, $3, $4.list);
if (!ent)
yyerror(_("Memory allocation error."));
$$ = ent;
}
2023-09-21 20:39:27 -07:00
all_rule: TOK_ALL TOK_END_OF_RULE
{
all_rule *ent = new all_rule();
if (!ent)
yyerror(_("Memory allocation error."));
$$ = ent;
}
2012-01-02 16:49:31 -08:00
hat_start: TOK_CARET {}
2007-07-27 20:48:24 +00:00
| TOK_HAT {}
2021-06-09 00:56:59 -07:00
file_perms: TOK_MODE
2007-07-27 20:47:17 +00:00
{
2007-11-16 09:35:31 +00:00
/* A single TOK_MODE maps to the same permission in all
Add Audit control to AppArmor through, the use of audit and deny
key words. Deny is also used to subtract permissions from the
profiles permission set.
the audit key word can be prepended to any file, network, or capability
rule, to force a selective audit when that rule is matched. Audit
permissions accumulate just like standard permissions.
eg.
audit /bin/foo rw,
will force an audit message when the file /bin/foo is opened for
read or write.
audit /etc/shadow w,
/etc/shadow r,
will force an audit message when /etc/shadow is opened for writing.
The audit message is per permission bit so only opening the file
for read access will not, force an audit message.
audit can also be used in block form instead of prepending audit
to every rule.
audit {
/bin/foo rw,
/etc/shadow w,
}
/etc/shadow r, # don't audit r access to /etc/shadow
the deny key word can be prepended to file, network and capability
rules, to result in a denial of permissions when matching that rule.
The deny rule specifically does 3 things
- it gives AppArmor the ability to remember what has been denied
so that the tools don't prompt for what has been denied in
previous profiling sessions.
- it subtracts globally from the allowed permissions. Deny permissions
accumulate in the the deny set just as allow permissions accumulate
then, the deny set is subtracted from the allow set.
- it quiets known rejects. The default audit behavior of deny rules
is to quiet known rejects so that audit logs are not flooded
with already known rejects. To have known rejects logged prepend
the audit keyword to the deny rule. Deny rules do not have a
block form.
eg.
deny /foo/bar rw,
audit deny /etc/shadow w,
audit {
deny owner /blah w,
deny other /foo w,
deny /etc/shadow w,
}
2008-03-13 17:39:03 +00:00
* of user::other */
2021-06-09 00:56:59 -07:00
$$ = parse_perms($1);
2007-07-27 20:47:17 +00:00
free($1);
}
2006-04-11 21:52:54 +00:00
2016-05-31 15:38:36 -05:00
change_profile: TOK_CHANGE_PROFILE opt_exec_mode opt_id opt_named_transition TOK_END_OF_RULE
2015-06-06 01:28:27 -07:00
{
struct cod_entry *entry;
2021-06-09 00:56:59 -07:00
perms_t perms = AA_CHANGE_PROFILE;
2016-05-31 15:32:08 -05:00
int exec_mode = $2;
char *exec = $3;
char *target = $4;
2016-06-02 22:24:22 -07:00
if (exec) {
/* exec bits required to trigger rule conflict if
* for overlapping safe and unsafe exec rules
*/
2021-06-09 00:56:59 -07:00
perms |= AA_EXEC_BITS;
2016-06-02 22:24:22 -07:00
if (exec_mode == EXEC_MODE_UNSAFE)
2021-06-09 00:56:59 -07:00
perms |= ALL_AA_EXEC_UNSAFE;
2016-06-02 22:24:22 -07:00
else if (exec_mode == EXEC_MODE_SAFE &&
2020-08-28 08:35:45 -07:00
!features_supports_stacking) {
pwarn(WARN_RULE_DOWNGRADED, "downgrading change_profile safe rule to unsafe due to lack of necessary kernel support\n");
2016-05-31 15:32:08 -05:00
/**
2016-05-31 15:38:36 -05:00
* No need to do anything because 'unsafe' exec
* mode is the only supported mode of
2016-05-31 15:32:08 -05:00
* change_profile rules in non-stacking kernels
*/
}
2016-06-02 22:24:22 -07:00
} else if (exec_mode != EXEC_MODE_EMPTY)
yyerror(_("Exec condition is required when unsafe or safe keywords are present"));
2016-05-28 11:58:41 -05:00
if (exec && !(exec[0] == '/' || strncmp(exec, "@{", 2) == 0))
yyerror(_("Exec condition must begin with '/'."));
2016-02-18 15:58:11 -06:00
2016-05-28 11:58:41 -05:00
if (target) {
PDEBUG("Matched change_profile: tok_id (%s)\n", target);
} else {
2016-02-18 15:58:11 -06:00
PDEBUG("Matched change_profile,\n");
2016-05-28 11:58:41 -05:00
target = strdup("**");
if (!target)
yyerror(_("Memory allocation error."));
2016-02-18 15:58:11 -06:00
}
2016-05-28 11:58:41 -05:00
2021-06-09 00:56:59 -07:00
entry = new_entry(target, perms, exec);
2007-06-26 21:10:28 +00:00
if (!entry)
yyerror(_("Memory allocation error."));
2016-02-18 15:58:11 -06:00
2007-06-26 21:10:28 +00:00
PDEBUG("change_profile.entry: (%s)\n", entry->name);
$$ = entry;
};
2007-11-16 09:32:38 +00:00
capability: TOK_CAPABILITY caps TOK_END_OF_RULE
2006-04-11 21:52:54 +00:00
{
2012-02-16 08:01:47 -08:00
if ($2 == 0) {
/* bare capability keyword - set all caps */
$$ = 0xffffffffffffffff;
} else
$$ = $2;
2006-04-11 21:52:54 +00:00
};
2012-02-16 08:01:47 -08:00
caps: { /* nothing */ $$ = 0; }
| caps TOK_ID
2007-11-16 09:32:38 +00:00
{
2020-07-07 07:31:06 -07:00
int backmap, cap = name_to_capability($2);
2007-11-16 09:32:38 +00:00
if (cap == -1)
yyerror(_("Invalid capability %s."), $2);
2009-08-20 15:27:12 +00:00
free($2);
2020-07-07 07:31:06 -07:00
backmap = capability_backmap(cap);
if (backmap != NO_BACKMAP_CAP && !capability_in_kernel(cap)) {
/* TODO: special backmap warning */
cap = backmap;
}
2007-11-16 09:32:38 +00:00
$$ = $1 | CAP_TO_MASK(cap);
}
2006-04-11 21:52:54 +00:00
%%
#define MAXBUFSIZE 4096
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
void vprintyyerror(const char *msg, va_list argptr)
2006-04-11 21:52:54 +00:00
{
char buf[MAXBUFSIZE];
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
vsnprintf(buf, sizeof(buf), msg, argptr);
2006-04-11 21:52:54 +00:00
if (profilename) {
2010-06-04 18:47:44 -07:00
PERROR(_("AppArmor parser error for %s%s%s at line %d: %s\n"),
profilename,
2020-06-12 04:24:30 -07:00
current_filename ? " in profile " : "",
2010-06-04 18:47:44 -07:00
current_filename ? current_filename : "",
current_lineno, buf);
2006-04-11 21:52:54 +00:00
} else {
2020-06-12 04:24:30 -07:00
PERROR(_("AppArmor parser error at line %d: %s\n"),
2006-04-11 21:52:54 +00:00
current_lineno, buf);
}
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
}
void printyyerror(const char *msg, ...)
{
va_list arg;
va_start(arg, msg);
vprintyyerror(msg, arg);
va_end(arg);
}
void yyerror(const char *msg, ...)
{
va_list arg;
va_start(arg, msg);
vprintyyerror(msg, arg);
va_end(arg);
2006-04-11 21:52:54 +00:00
exit(1);
}
2021-06-09 00:56:59 -07:00
struct cod_entry *do_file_rule(char *id, perms_t perms, char *link_id, char *nt)
2007-07-27 20:55:25 +00:00
{
struct cod_entry *entry;
2021-06-09 00:56:59 -07:00
PDEBUG("Matched: tok_id (%s) tok_perms (0x%x)\n", id, perms);
entry = new_entry(id, perms, link_id);
2007-07-27 20:55:25 +00:00
if (!entry)
yyerror(_("Memory allocation error."));
2008-04-16 04:45:02 +00:00
entry->nt_name = nt;
2007-07-27 20:55:25 +00:00
PDEBUG("rule.entry: (%s)\n", entry->name);
return entry;
}
2008-04-16 04:45:02 +00:00
2013-09-27 16:13:22 -07:00
static const char *mnt_cond_msg[] = {"",
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
" not allowed as source conditional",
" not allowed as target conditional",
"",
NULL};
int verify_mnt_conds(struct cond_entry *conds, int src)
{
struct cond_entry *entry;
int error = 0;
if (!conds)
return 0;
list_for_each(conds, entry) {
int res = is_valid_mnt_cond(entry->name, src);
if (res <= 0) {
printyyerror(_("invalid mount conditional %s%s"),
entry->name,
res == -1 ? "" : mnt_cond_msg[src]);
error++;
}
}
return error;
}
2014-04-07 03:16:50 -07:00
mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
struct cond_entry *dst_conds, char *dst,
2021-06-09 00:56:59 -07:00
perms_t perms)
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
{
if (verify_mnt_conds(src_conds, MNT_SRC_OPT) != 0)
yyerror(_("bad mount rule"));
/* FIXME: atm conditions are not supported on dst
if (verify_conds(dst_conds, DST_OPT) != 0)
yyerror(_("bad mount rule"));
*/
if (dst_conds)
yyerror(_("mount point conditions not currently supported"));
2021-06-09 00:56:59 -07:00
mnt_rule *ent = new mnt_rule(src_conds, src, dst_conds, dst, perms);
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
if (!ent) {
yyerror(_("Memory allocation error."));
}
return ent;
}
2014-04-07 03:16:50 -07:00
mnt_rule *do_pivot_rule(struct cond_entry *old, char *root, char *transition)
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
{
2012-03-15 12:14:15 -07:00
char *device = NULL;
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
if (old) {
if (strcmp(old->name, "oldroot") != 0)
yyerror(_("invalid pivotroot conditional '%s'"), old->name);
2012-03-15 12:14:15 -07:00
if (old->vals) {
device = old->vals->value;
old->vals->value = NULL;
}
free_cond_entry(old);
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
}
2014-04-07 03:16:50 -07:00
mnt_rule *ent = new mnt_rule(NULL, device, NULL, root, AA_MAY_PIVOTROOT);
Add mount rules
Add the ability to control mounting and unmounting
The basic form of the rules are.
[audit] [deny] mount [conds]* [device] [ -> [conds] path],
[audit] [deny] remount [conds]* [path],
[audit] [deny] umount [conds]* [path],
[audit] [deny] pivotroot [oldroot=<value>] <path> -> <profile>
remount is just a short cut for mount options=remount
where [conds] can be
fstype=<expr>
options=<expr>
conds follow the extended conditional syntax of allowing either:
* a single value after the equals, which has the same character range as
regular IDS (ie most anything but it can't be terminated with a , (comma)
and if spaces or other characters are needed it can be quoted
eg.
options=foo
options = foo
options="foo bar"
* a list of values after the equals, the list of values is enclosed within
parenthesis () and its has a slightly reduced character set but again
elements can be quoted.
the separation between elements is whitespace and commas.
eg.
options=(foo bar)
options=(foo, bar)
options=(foo , bar)
options=(foo,bar)
The rules are flexible and follow a similar pattern as network, capability,
etc.
mount, # allow all mounts, but not umount or pivotroot
mount fstype=procfs, # allow mounting procfs anywhere
mount options=(bind, ro) /foo -> /bar, # readonly bind mount
mount /dev/sda -> /mnt,
mount /dev/sd** -> /mnt/**,
mount fstype=overlayfs options=(rw,upperdir=/tmp/upper/,lowerdir=/) overlay -> /mnt/
umount,
umount /m*,
Currently variables and regexs are are supported on the device and mount
point. ie.
mount <devince> -> <mount point>,
Regexes are supported in fstype and options. The options have a further
caveat that regexs only work if the option is fs specific option.
eg. options=(upperdir=/tmp/*,lowerdir=/)
regex's will not currently work against the standard options like ro, rw
nosuid
Conditionals (fstype) can only be applied to the device (source) at this
time and will be disregarded in situations where the mount is manipulating
an existing mount (bind, remount).
Options can be specified multiple times
mount option=rw option=(nosuid,upperdir=/foo),
and will be combined together into a single set of values
The ordering of the standard mount options (rw,ro, ...) does not matter
but the ordering of fs specific options does.
Specifying that the value of a particular option does not matter can be
acheived by providing both the positive and negative forms of and option
option=(rw,ro) options=(suid,nosuid)
For the fs specific options specifying that a particular value does not
matter is achieve using a regex with alternations.
Improvements to the syntax and order restrictions are planned for the
future.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2012-02-24 04:19:38 -08:00
ent->trans = transition;
return ent;
}
2020-04-24 17:43:47 -07:00
static int abi_features_base(struct aa_features **features, char *filename, bool search)
{
autofclose FILE *f = NULL;
struct stat my_stat;
2023-03-16 18:03:57 -03:00
autofree char *fullpath = NULL;
2021-04-20 01:32:41 -07:00
bool cached;
2020-04-24 17:43:47 -07:00
if (search) {
if (strcmp(filename, "kernel") == 0)
return aa_features_new_from_kernel(features);
2021-04-20 01:32:41 -07:00
f = search_path(filename, &fullpath, &cached);
PDEBUG("abi lookup '%s' -> '%s' f %p cached %d\n", filename, fullpath, f, cached);
if (!f && cached) {
*features = NULL;
return 0;
}
2020-04-24 17:43:47 -07:00
} else {
f = fopen(filename, "r");
PDEBUG("abi relpath '%s' f %p\n", filename, f);
}
if (!f) {
yyerror(_("Could not open '%s': %m"),
fullpath ? fullpath: filename);
}
if (fstat(fileno(f), &my_stat))
yyerror(_("fstat failed for '%s': %m"), fullpath ? fullpath : filename);
if (S_ISREG(my_stat.st_mode)) {
return aa_features_new_from_file(features, fileno(f));
}
return -1;
}
static void abi_features(char *filename, bool search)
{
struct aa_features *tmp_features;
if (abi_features_base(&tmp_features, filename, search) == -1) {
yyerror(_("failed to find features abi '%s': %m"), filename);
}
if (policy_features) {
2021-04-20 01:32:41 -07:00
if (tmp_features) {
if (!aa_features_is_equal(tmp_features, policy_features)) {
pwarn(WARN_ABI, _("%s: %s features abi '%s' differs from policy declared feature abi, using the features abi declared in policy\n"), progname, current_filename, filename);
}
aa_features_unref(tmp_features);
2020-04-24 17:43:47 -07:00
}
2021-04-20 01:32:41 -07:00
} else if (!tmp_features) {
/* skipped reinclude, but features not set */
yyerror(_("failed features abi not set but include cache skipped\n"));
2020-04-24 17:43:47 -07:00
} else {
/* first features abi declaration */
policy_features = tmp_features;
}
};
2023-02-21 02:02:02 -08:00