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)
|
2013-10-14 14:34:12 -07:00
|
|
|
* Copyright (c) 2010 - 2013
|
|
|
|
* Canonical Ltd. (All rights reserved)
|
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
|
|
|
*/
|
|
|
|
|
|
|
|
/* Definitions section */
|
|
|
|
/* %option main */
|
|
|
|
|
2020-04-21 16:54:56 -07:00
|
|
|
/* options set to noXXX eliminates need to link with libfl */
|
2006-04-11 21:52:54 +00:00
|
|
|
%option noyywrap
|
2020-04-21 16:54:56 -07:00
|
|
|
/* set %option noyy_top_state in Makefile, so can be used when DEBUG=1 */
|
2010-11-09 13:39:18 -08:00
|
|
|
%option nounput
|
2012-01-02 16:48:24 -08:00
|
|
|
%option stack
|
2020-06-11 22:15:07 +02:00
|
|
|
%option nodefault
|
2006-04-11 21:52:54 +00:00
|
|
|
|
|
|
|
%{
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2009-07-24 07:35:39 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
2013-11-18 16:23:23 -08:00
|
|
|
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <string>
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
#include "parser.h"
|
2013-09-27 16:16:37 -07:00
|
|
|
#include "profile.h"
|
2009-07-24 07:35:39 +00:00
|
|
|
#include "parser_include.h"
|
2006-04-11 21:52:54 +00:00
|
|
|
#include "parser_yacc.h"
|
2012-08-16 16:26:03 -07:00
|
|
|
#include "lib.h"
|
2015-03-25 17:09:25 -05:00
|
|
|
#include "policy_cache.h"
|
2021-04-20 01:32:41 -07:00
|
|
|
#include "file_cache.h"
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2009-07-24 07:35:39 +00:00
|
|
|
#ifdef PDEBUG
|
|
|
|
#undef PDEBUG
|
|
|
|
#endif
|
2006-04-11 21:52:54 +00:00
|
|
|
/* #define DEBUG */
|
|
|
|
#ifdef DEBUG
|
2013-09-12 12:37:04 -07:00
|
|
|
static int yy_top_state(void);
|
2014-04-23 11:16:08 -07:00
|
|
|
#define PDEBUG(fmt, args...) fprintf(stderr, "Lexer (Line %d) (state %s): " fmt, current_lineno, state_names[YY_START].c_str(), ## args)
|
2006-04-11 21:52:54 +00:00
|
|
|
#else
|
|
|
|
#define PDEBUG(fmt, args...) /* Do nothing */
|
|
|
|
#endif
|
|
|
|
#define NPDEBUG(fmt, args...) /* Do nothing */
|
|
|
|
|
2010-06-26 13:13:52 -07:00
|
|
|
#define DUMP_PREPROCESS do { if (preprocess_only) ECHO; } while (0)
|
2013-09-12 12:37:04 -07:00
|
|
|
|
|
|
|
#define DUMP_AND_DEBUG(X...) \
|
2013-07-31 09:05:51 -07:00
|
|
|
do { \
|
|
|
|
DUMP_PREPROCESS; \
|
2013-09-12 12:37:04 -07:00
|
|
|
PDEBUG(X); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define EAT_TOKEN(X...) DUMP_AND_DEBUG(X)
|
|
|
|
|
|
|
|
#define RETURN_TOKEN(X) \
|
|
|
|
do { \
|
2014-04-23 11:16:08 -07:00
|
|
|
DUMP_AND_DEBUG("Matched: '%s' Returning(%s)\n", yytext, #X); \
|
2013-09-12 12:37:04 -07:00
|
|
|
return (X); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define POP() \
|
|
|
|
do { \
|
2013-11-18 16:23:23 -08:00
|
|
|
DUMP_AND_DEBUG(" (pop_to(%s)): Matched: %s\n", state_names[yy_top_state()].c_str(), yytext); \
|
2013-09-12 12:37:04 -07:00
|
|
|
yy_pop_state(); \
|
|
|
|
} while (0)
|
|
|
|
|
2014-04-23 11:17:08 -07:00
|
|
|
#define POP_NODUMP() \
|
|
|
|
do { \
|
|
|
|
PDEBUG(" (pop_to(%s)): Matched: %s\n", state_names[yy_top_state()].c_str(), yytext); \
|
|
|
|
yy_pop_state(); \
|
|
|
|
} while (0)
|
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
#define PUSH(X) \
|
|
|
|
do { \
|
2013-11-18 16:23:23 -08:00
|
|
|
DUMP_AND_DEBUG(" (push(%s)): Matched: %s\n", state_names[(X)].c_str(), yytext); \
|
2013-09-12 12:37:04 -07:00
|
|
|
yy_push_state(X); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define POP_AND_RETURN(X) \
|
|
|
|
do { \
|
|
|
|
POP(); \
|
2013-07-31 09:05:51 -07:00
|
|
|
return (X); \
|
|
|
|
} while (0)
|
2010-06-26 13:13:52 -07:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
#define PUSH_AND_RETURN(X, Y) \
|
|
|
|
do { \
|
|
|
|
PUSH(X); \
|
|
|
|
return (Y); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
#define BEGIN_AND_RETURN(X, Y) \
|
|
|
|
do { \
|
2013-11-18 16:23:23 -08:00
|
|
|
DUMP_AND_DEBUG(" (begin(%s)): Matched: %s\n", state_names[(X)].c_str(), yytext); \
|
2013-09-12 12:37:04 -07:00
|
|
|
BEGIN(X); \
|
|
|
|
return (Y); \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
2010-07-26 09:22:45 -07:00
|
|
|
#define YY_NO_INPUT
|
|
|
|
|
2013-11-18 16:23:23 -08:00
|
|
|
#define STATE_TABLE_ENT(X) {X, #X }
|
|
|
|
extern unordered_map<int, string> state_names;
|
2012-08-16 16:26:03 -07:00
|
|
|
|
|
|
|
struct cb_struct {
|
|
|
|
const char *fullpath;
|
|
|
|
const char *filename;
|
|
|
|
};
|
|
|
|
|
2015-06-15 15:11:51 -05:00
|
|
|
static int include_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
2012-08-16 16:26:03 -07:00
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
struct cb_struct *d = (struct cb_struct *) data;
|
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
autofree char *path = NULL;
|
2012-08-16 16:26:03 -07:00
|
|
|
|
|
|
|
if (asprintf(&path, "%s/%s", d->fullpath, name) < 0)
|
|
|
|
yyerror("Out of memory");
|
|
|
|
|
2015-03-25 17:09:26 -05:00
|
|
|
if (is_blacklisted(name, path))
|
2012-08-16 16:26:03 -07:00
|
|
|
return 0;
|
|
|
|
|
2021-04-20 01:32:41 -07:00
|
|
|
if (g_includecache->find(path)) {
|
|
|
|
PDEBUG("skipping reinclude of \'%s\' in \'%s\'\n", path,
|
|
|
|
d->filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-02-16 12:59:24 -08:00
|
|
|
/* Handle symlink here. See _aa_dirat_for_each in private.c */
|
|
|
|
|
2012-08-16 16:26:03 -07:00
|
|
|
if (S_ISREG(st->st_mode)) {
|
|
|
|
if (!(yyin = fopen(path,"r")))
|
|
|
|
yyerror(_("Could not open '%s' in '%s'"), path, d->filename);
|
|
|
|
PDEBUG("Opened include \"%s\" in \"%s\"\n", path, d->filename);
|
2021-04-20 01:32:41 -07:00
|
|
|
(void) g_includecache->insert(path);
|
2015-03-25 17:09:25 -05:00
|
|
|
update_mru_tstamp(yyin, path);
|
2012-08-16 16:26:03 -07:00
|
|
|
push_include_stack(path);
|
|
|
|
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-01-07 01:06:10 -08:00
|
|
|
void include_filename(char *filename, int search, bool if_exists)
|
2009-07-24 07:35:39 +00:00
|
|
|
{
|
|
|
|
FILE *include_file = NULL;
|
|
|
|
struct stat my_stat;
|
2015-03-25 17:09:26 -05:00
|
|
|
autofree char *fullpath = NULL;
|
2021-04-20 01:32:41 -07:00
|
|
|
bool cached;
|
2009-07-24 07:35:39 +00:00
|
|
|
|
2009-07-24 11:56:07 +00:00
|
|
|
if (search) {
|
2021-04-20 01:32:41 -07:00
|
|
|
include_file = search_path(filename, &fullpath, &cached);
|
|
|
|
if (!include_file && cached) {
|
|
|
|
goto skip;
|
|
|
|
} else if (!include_file && preprocess_only) {
|
|
|
|
fprintf(yyout, "\n\n##failed include <%s>\n", filename);
|
2023-05-29 21:33:54 +02:00
|
|
|
} else if (preprocess_only) {
|
|
|
|
fprintf(yyout, "\n\n##included <%s>\n", filename);
|
2021-04-20 01:32:41 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
} else if (g_includecache->find(filename)) {
|
|
|
|
/* duplicate entry skip */
|
|
|
|
goto skip;
|
2009-07-24 11:56:07 +00:00
|
|
|
} else {
|
2010-06-26 13:13:52 -07:00
|
|
|
if (preprocess_only)
|
|
|
|
fprintf(yyout, "\n\n##included \"%s\"\n", filename);
|
2009-07-24 07:35:39 +00:00
|
|
|
fullpath = strdup(filename);
|
|
|
|
include_file = fopen(fullpath, "r");
|
2021-04-20 01:32:41 -07:00
|
|
|
if (include_file)
|
|
|
|
/* ignore failure to insert into cache */
|
|
|
|
(void) g_includecache->insert(filename);
|
2009-07-24 07:35:39 +00:00
|
|
|
}
|
|
|
|
|
2018-01-07 01:06:10 -08:00
|
|
|
if (!include_file) {
|
|
|
|
if (if_exists)
|
|
|
|
return;
|
2010-06-04 18:47:44 -07:00
|
|
|
yyerror(_("Could not open '%s'"),
|
|
|
|
fullpath ? fullpath: filename);
|
2018-01-07 01:06:10 -08:00
|
|
|
}
|
2009-07-24 07:35:39 +00:00
|
|
|
|
2018-01-07 01:06:10 -08:00
|
|
|
if (fstat(fileno(include_file), &my_stat))
|
2009-07-24 07:35:39 +00:00
|
|
|
yyerror(_("fstat failed for '%s'"), fullpath);
|
|
|
|
|
|
|
|
if (S_ISREG(my_stat.st_mode)) {
|
|
|
|
yyin = include_file;
|
2015-03-25 17:09:25 -05:00
|
|
|
update_mru_tstamp(include_file, fullpath);
|
2009-07-24 07:35:39 +00:00
|
|
|
PDEBUG("Opened include \"%s\"\n", fullpath);
|
2010-06-04 18:47:44 -07:00
|
|
|
push_include_stack(fullpath);
|
2009-07-24 07:35:39 +00:00
|
|
|
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
|
2012-08-16 16:26:03 -07:00
|
|
|
} else if (S_ISDIR(my_stat.st_mode)) {
|
|
|
|
struct cb_struct data = { fullpath, filename };
|
2021-05-30 02:58:28 -07:00
|
|
|
update_mru_tstamp(include_file, fullpath);
|
2009-07-24 07:35:39 +00:00
|
|
|
fclose(include_file);
|
|
|
|
include_file = NULL;
|
2015-06-15 15:11:51 -05:00
|
|
|
if (dirat_for_each(AT_FDCWD, fullpath, &data, include_dir_cb)) {
|
2012-08-16 16:26:03 -07:00
|
|
|
yyerror(_("Could not process include directory"
|
|
|
|
" '%s' in '%s'"), fullpath, filename);;
|
2009-07-24 07:35:39 +00:00
|
|
|
}
|
|
|
|
}
|
2021-04-20 01:32:41 -07:00
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
skip:
|
|
|
|
if (preprocess_only)
|
|
|
|
fprintf(yyout, "\n\n##skipped duplicate include <%s>\n", filename);
|
|
|
|
return;
|
2009-07-24 07:35:39 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 17:43:47 -07:00
|
|
|
static char *lsntrim(char *s, int l)
|
|
|
|
{
|
|
|
|
const char *end = s + l;
|
|
|
|
|
|
|
|
while (s <= end && isspace(*s))
|
|
|
|
s++;
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int rsntrim(const char *s, int l)
|
|
|
|
{
|
|
|
|
const char *r = s + l;
|
|
|
|
|
|
|
|
while (r > s && isspace(*--r))
|
|
|
|
l--;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
%}
|
|
|
|
|
2012-01-02 16:49:31 -08:00
|
|
|
CARET "^"
|
2006-04-11 21:52:54 +00:00
|
|
|
OPEN_BRACE \{
|
|
|
|
CLOSE_BRACE \}
|
|
|
|
SLASH \/
|
|
|
|
COLON :
|
2016-03-18 17:28:51 -05:00
|
|
|
AMPERSAND &
|
2006-04-11 21:52:54 +00:00
|
|
|
END_OF_RULE [,]
|
|
|
|
RANGE -
|
2009-08-20 15:41:10 +00:00
|
|
|
MODE_CHARS ([RrWwaLlMmkXx])|(([Pp]|[Cc])[Xx])|(([Pp]|[Cc])?([IiUu])[Xx])
|
2007-11-29 18:06:53 +00:00
|
|
|
MODES {MODE_CHARS}+
|
2006-04-11 21:52:54 +00:00
|
|
|
WS [[:blank:]]
|
|
|
|
NUMBER [[:digit:]]+
|
2012-02-16 07:46:43 -08:00
|
|
|
|
parser: make lead # in assignment value indicate a comment
technically a # leading a value in an assignment expression is allowed,
however people are also using it to a comment at the end of a line.
ie.
@{var1}=value1 # comment about this value or for a given system
this unsurprisingly leads to odd/unexpected behavior when the variable
is used.
allow rw /@{var1},
expands into
allow rw /{value1,#,comment,about,this,value,or,for,a,given,system},
change a leading # as value in an assignment expression to a comment.
If the # is really supposed to lead the value, require it to be escaped
or in quotes.
ie.
@{var1}=value1 \#not_a_comment
Note: this could potentially break som policy if the # was used as the
leading character for a value in an assignment expression, but
is worth it to avoid the confusion.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-06-07 16:43:22 -07:00
|
|
|
ID_FIRST_CHARS [^ \t\r\n"!,#]
|
|
|
|
ID_FIRST {ID_CHARS}|(,{ID_CHARS}|\\[ ]|\\\t|\\\"|\\!|\\,|\\#)
|
2018-01-08 03:34:59 -08:00
|
|
|
ID_CHARS [^ \t\r\n"!,]
|
2014-10-01 15:54:30 -07:00
|
|
|
ID {ID_CHARS}|(,{ID_CHARS}|\\[ ]|\\\t|\\\"|\\!|\\,)
|
parser: make lead # in assignment value indicate a comment
technically a # leading a value in an assignment expression is allowed,
however people are also using it to a comment at the end of a line.
ie.
@{var1}=value1 # comment about this value or for a given system
this unsurprisingly leads to odd/unexpected behavior when the variable
is used.
allow rw /@{var1},
expands into
allow rw /{value1,#,comment,about,this,value,or,for,a,given,system},
change a leading # as value in an assignment expression to a comment.
If the # is really supposed to lead the value, require it to be escaped
or in quotes.
ie.
@{var1}=value1 \#not_a_comment
Note: this could potentially break som policy if the # was used as the
leading character for a value in an assignment expression, but
is worth it to avoid the confusion.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-06-07 16:43:22 -07:00
|
|
|
IDS {ID_FIRST}{ID}*
|
2020-04-24 17:43:47 -07:00
|
|
|
INC_ID [^ \t\r\n"!,<>]|(,[^ \t\r\n"!,<>]|\\[ ]|\\\t|\\\"|\\!|\\,)
|
|
|
|
INC_IDS {INC_ID}+
|
2012-02-16 07:46:43 -08:00
|
|
|
POST_VAR_ID_CHARS [^ \t\n"!,]{-}[=\+]
|
2014-10-01 15:54:30 -07:00
|
|
|
POST_VAR_ID {POST_VAR_ID_CHARS}|(,{POST_VAR_ID_CHARS}|\\[ ]|\\\t|\\\"|\\!|\\,|\\\(|\\\))
|
|
|
|
LIST_VALUE_ID_CHARS ([^ \t\n"!,]{-}[()]|\\[ ]|\\\t|\\\"|\\!|\\,|\\\(|\\\))
|
|
|
|
LIST_VALUE_QUOTED_ID_CHARS [^\0"]|\\\"
|
2012-02-16 07:49:12 -08:00
|
|
|
LIST_VALUE_ID {LIST_VALUE_ID_CHARS}+
|
2014-10-01 15:54:30 -07:00
|
|
|
QUOTED_LIST_VALUE_ID \"{LIST_VALUE_QUOTED_ID_CHARS}+\"
|
2019-08-17 05:22:10 -07:00
|
|
|
ID_CHARS_NOEQ [^ \t\n"!,]{-}[=)]
|
2013-09-12 12:37:04 -07:00
|
|
|
LEADING_ID_CHARS_NOEQ [^ \t\n"!,]{-}[=()+&]
|
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
|
|
|
ID_NOEQ {ID_CHARS_NOEQ}|(,{ID_CHARS_NOEQ})
|
2013-07-31 09:05:51 -07:00
|
|
|
IDS_NOEQ {LEADING_ID_CHARS_NOEQ}{ID_NOEQ}*
|
2006-04-11 21:52:54 +00:00
|
|
|
ALLOWED_QUOTED_ID [^\0"]|\\\"
|
|
|
|
QUOTED_ID \"{ALLOWED_QUOTED_ID}*\"
|
|
|
|
|
2012-02-16 07:46:43 -08:00
|
|
|
IP {NUMBER}\.{NUMBER}\.{NUMBER}\.{NUMBER}
|
|
|
|
|
parser: add the ability to specify a priority prefix to rules
This enables adding a priority to a rules in policy, finishing out the
priority work done to plumb priority support through the internals in
the previous patch.
Rules have a default priority of 0. The priority prefix can be added
before the other currently support rule prefixes, ie.
[priority prefix][audit qualifier][rule mode][owner]
If present a numerical priority can be assigned to the rule, where the
greater the number the higher the priority. Eg.
priority=1 audit file r /etc/passwd,
priority=-1 deny file w /etc/**,
Rule priority allows the rule with the highest priority to completely
override lower priority rules where they overlap. Within a given
priority level rules will accumulate in standard apparmor fashion.
Eg. given
priority=1 w /*c,
priority=0 r /a*,
priority=-1 k /*b*,
/abc, /bc, /ac .. will have permissions of w
/ab, /abb, /aaa, .. will have permissions of r
/b, /bcb, /bab, .. will have permissions of k
User specified rule priorities are currently capped at the arbitrary
values of 1000, and -1000.
Notes:
* not all rule types support the priority prefix. Rukes like
- network
- capability
- rlimits need to be reworked
need to be reworked to properly preserve the policy rule structure.
* this patch does not support priority on rule blocks
* this patch does not support using a variable in the priority value.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-05-11 23:33:42 -07:00
|
|
|
INTEGER [+-]?{NUMBER}
|
2012-01-02 16:48:53 -08:00
|
|
|
HAT hat{WS}*
|
|
|
|
PROFILE profile{WS}*
|
2006-04-11 21:52:54 +00:00
|
|
|
KEYWORD [[:alpha:]_]+
|
|
|
|
VARIABLE_NAME [[:alpha:]][[:alnum:]_]*
|
|
|
|
SET_VAR_PREFIX @
|
|
|
|
SET_VARIABLE {SET_VAR_PREFIX}(\{{VARIABLE_NAME}\}|{VARIABLE_NAME})
|
|
|
|
BOOL_VARIABLE $(\{{VARIABLE_NAME}\}|{VARIABLE_NAME})
|
|
|
|
|
2016-03-18 17:28:51 -05:00
|
|
|
LABEL (\/|{SET_VARIABLE}{POST_VAR_ID}|{COLON}|{AMPERSAND}){ID}*
|
|
|
|
QUOTED_LABEL \"(\/|{SET_VAR_PREFIX}|{COLON}|{AMPERSAND})([^\0"]|\\\")*\"
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2012-01-02 16:48:34 -08:00
|
|
|
OPEN_PAREN \(
|
|
|
|
CLOSE_PAREN \)
|
2012-02-16 07:49:12 -08:00
|
|
|
COMMA \,
|
2006-04-11 21:52:54 +00:00
|
|
|
EQUALS =
|
|
|
|
ADD_ASSIGN \+=
|
2007-11-16 09:37:31 +00:00
|
|
|
ARROW ->
|
2008-04-06 18:55:46 +00:00
|
|
|
LT_EQUAL <=
|
2018-09-19 01:15:49 -07:00
|
|
|
LT <
|
|
|
|
GT >
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2020-06-12 01:10:07 -07:00
|
|
|
/* IF adding new state please update state_names table and default rule (just
|
|
|
|
* above the state_names table) at the eof.
|
|
|
|
*
|
|
|
|
* The nodefault option is set so missing adding to the default rule isn't
|
|
|
|
* fatal but can't take advantage of additional debug the default rule might
|
|
|
|
* have.
|
|
|
|
*
|
|
|
|
* If a state is not added to the default rule it can result in the message
|
|
|
|
* "flex scanner jammed"
|
|
|
|
*/
|
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
|
|
|
%x SUB_ID
|
2016-05-31 15:32:08 -05:00
|
|
|
%x SUB_ID_WS
|
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
|
|
|
%x SUB_VALUE
|
2012-02-16 07:51:33 -08:00
|
|
|
%x EXTCOND_MODE
|
2013-07-31 09:05:51 -07:00
|
|
|
%x EXTCONDLIST_MODE
|
2007-07-27 20:29:47 +00:00
|
|
|
%x NETWORK_MODE
|
2012-02-16 07:49:12 -08:00
|
|
|
%x LIST_VAL_MODE
|
2013-07-31 09:05:51 -07:00
|
|
|
%x LIST_COND_MODE
|
|
|
|
%x LIST_COND_VAL
|
|
|
|
%x LIST_COND_PAREN_VAL
|
2006-04-11 21:52:54 +00:00
|
|
|
%x ASSIGN_MODE
|
2008-04-06 18:55:46 +00:00
|
|
|
%x RLIMIT_MODE
|
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
|
|
|
%x MOUNT_MODE
|
2013-07-31 09:05:51 -07:00
|
|
|
%x DBUS_MODE
|
2014-04-23 11:35:29 -07:00
|
|
|
%x SIGNAL_MODE
|
2014-04-23 11:38:04 -07:00
|
|
|
%x PTRACE_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
|
|
|
%x UNIX_MODE
|
2009-07-23 21:18:37 +00:00
|
|
|
%x CHANGE_PROFILE_MODE
|
2009-07-24 07:35:39 +00:00
|
|
|
%x INCLUDE
|
2018-01-07 01:06:10 -08:00
|
|
|
%x INCLUDE_EXISTS
|
2018-09-19 01:15:49 -07:00
|
|
|
%x ABI_MODE
|
2022-09-29 17:40:18 -03:00
|
|
|
%x USERNS_MODE
|
2022-02-07 19:15:11 -03:00
|
|
|
%x MQUEUE_MODE
|
2023-03-20 12:28:53 -03:00
|
|
|
%x IOURING_MODE
|
parser: add the ability to specify a priority prefix to rules
This enables adding a priority to a rules in policy, finishing out the
priority work done to plumb priority support through the internals in
the previous patch.
Rules have a default priority of 0. The priority prefix can be added
before the other currently support rule prefixes, ie.
[priority prefix][audit qualifier][rule mode][owner]
If present a numerical priority can be assigned to the rule, where the
greater the number the higher the priority. Eg.
priority=1 audit file r /etc/passwd,
priority=-1 deny file w /etc/**,
Rule priority allows the rule with the highest priority to completely
override lower priority rules where they overlap. Within a given
priority level rules will accumulate in standard apparmor fashion.
Eg. given
priority=1 w /*c,
priority=0 r /a*,
priority=-1 k /*b*,
/abc, /bc, /ac .. will have permissions of w
/ab, /abb, /aaa, .. will have permissions of r
/b, /bcb, /bab, .. will have permissions of k
User specified rule priorities are currently capped at the arbitrary
values of 1000, and -1000.
Notes:
* not all rule types support the priority prefix. Rukes like
- network
- capability
- rlimits need to be reworked
need to be reworked to properly preserve the policy rule structure.
* this patch does not support priority on rule blocks
* this patch does not support using a variable in the priority value.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-05-11 23:33:42 -07:00
|
|
|
%x INTEGER_MODE
|
2006-04-11 21:52:54 +00:00
|
|
|
%%
|
|
|
|
|
2012-02-16 07:59:23 -08:00
|
|
|
%{
|
|
|
|
/* Copied directly into yylex function */
|
|
|
|
if (parser_token) {
|
|
|
|
int t = parser_token;
|
|
|
|
parser_token = 0;
|
|
|
|
return t;
|
|
|
|
}
|
|
|
|
%}
|
|
|
|
|
parser: add the ability to specify a priority prefix to rules
This enables adding a priority to a rules in policy, finishing out the
priority work done to plumb priority support through the internals in
the previous patch.
Rules have a default priority of 0. The priority prefix can be added
before the other currently support rule prefixes, ie.
[priority prefix][audit qualifier][rule mode][owner]
If present a numerical priority can be assigned to the rule, where the
greater the number the higher the priority. Eg.
priority=1 audit file r /etc/passwd,
priority=-1 deny file w /etc/**,
Rule priority allows the rule with the highest priority to completely
override lower priority rules where they overlap. Within a given
priority level rules will accumulate in standard apparmor fashion.
Eg. given
priority=1 w /*c,
priority=0 r /a*,
priority=-1 k /*b*,
/abc, /bc, /ac .. will have permissions of w
/ab, /abb, /aaa, .. will have permissions of r
/b, /bcb, /bab, .. will have permissions of k
User specified rule priorities are currently capped at the arbitrary
values of 1000, and -1000.
Notes:
* not all rule types support the priority prefix. Rukes like
- network
- capability
- rlimits need to be reworked
need to be reworked to properly preserve the policy rule structure.
* this patch does not support priority on rule blocks
* this patch does not support using a variable in the priority value.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-05-11 23:33:42 -07:00
|
|
|
<INITIAL,SUB_ID_WS,INCLUDE,INCLUDE_EXISTS,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,ABI_MODE,USERNS_MODE,MQUEUE_MODE,IOURING_MODE,INTEGER_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
|
|
|
|
}
|
2009-07-24 07:35:39 +00:00
|
|
|
|
2018-09-19 01:15:49 -07:00
|
|
|
<INCLUDE,INCLUDE_EXISTS,ABI_MODE>{
|
2020-04-24 17:43:47 -07:00
|
|
|
(\<((([^"\>\t\r\n])+)|{QUOTED_ID})\>|{QUOTED_ID}|({INC_IDS})) { /* <filename> | <"filename"> | "filename" | filename */
|
2018-09-19 23:14:14 -07:00
|
|
|
int lt = *yytext == '<' ? 1 : 0;
|
2020-04-24 17:43:47 -07:00
|
|
|
int len = yyleng - lt*2;
|
|
|
|
char *s = yytext + lt;
|
|
|
|
char * filename = lsntrim(s, yyleng);
|
2018-09-19 21:09:50 -07:00
|
|
|
bool exists = YYSTATE == INCLUDE_EXISTS;
|
2018-01-07 01:06:10 -08:00
|
|
|
|
2020-04-24 17:43:47 -07:00
|
|
|
filename = processid(filename, rsntrim(filename, len - (filename - s)));
|
2018-09-19 23:14:14 -07:00
|
|
|
if (!filename)
|
|
|
|
yyerror(_("Failed to process filename\n"));
|
2018-09-19 01:15:49 -07:00
|
|
|
if (YYSTATE == ABI_MODE) {
|
|
|
|
yylval.id = filename;
|
2020-04-24 17:43:47 -07:00
|
|
|
if (lt)
|
|
|
|
RETURN_TOKEN(TOK_ID);
|
|
|
|
else
|
|
|
|
RETURN_TOKEN(TOK_VALUE);
|
2018-09-19 01:15:49 -07:00
|
|
|
}
|
2018-09-19 23:14:14 -07:00
|
|
|
include_filename(filename, lt, exists);
|
2018-09-19 01:15:49 -07:00
|
|
|
free(filename);
|
2014-04-23 11:17:08 -07:00
|
|
|
POP_NODUMP();
|
2013-09-12 12:37:04 -07:00
|
|
|
}
|
2009-07-24 07:35:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
<<EOF>> {
|
2010-03-12 01:50:26 -08:00
|
|
|
fclose(yyin);
|
2010-06-04 18:47:44 -07:00
|
|
|
pop_include_stack();
|
2009-07-24 07:35:39 +00:00
|
|
|
yypop_buffer_state();
|
2013-09-12 12:37:04 -07:00
|
|
|
if ( !YY_CURRENT_BUFFER )
|
|
|
|
yyterminate();
|
2009-07-24 07:35:39 +00:00
|
|
|
}
|
|
|
|
|
2023-08-02 11:57:24 -03:00
|
|
|
<INITIAL,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,MQUEUE_MODE,NETWORK_MODE>{
|
2018-12-06 10:54:46 -08:00
|
|
|
(peer|xattrs)/{WS}*={WS}*\( {
|
2014-04-23 11:36:26 -07:00
|
|
|
/* we match to the = in the lexer so that we can switch scanner
|
|
|
|
* state. By the time the parser see the = it may be too late
|
|
|
|
* as bison may have requested the next token from the scanner
|
|
|
|
*/
|
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
PUSH_AND_RETURN(EXTCONDLIST_MODE, TOK_CONDLISTID);
|
|
|
|
}
|
parser: add the ability to specify a priority prefix to rules
This enables adding a priority to a rules in policy, finishing out the
priority work done to plumb priority support through the internals in
the previous patch.
Rules have a default priority of 0. The priority prefix can be added
before the other currently support rule prefixes, ie.
[priority prefix][audit qualifier][rule mode][owner]
If present a numerical priority can be assigned to the rule, where the
greater the number the higher the priority. Eg.
priority=1 audit file r /etc/passwd,
priority=-1 deny file w /etc/**,
Rule priority allows the rule with the highest priority to completely
override lower priority rules where they overlap. Within a given
priority level rules will accumulate in standard apparmor fashion.
Eg. given
priority=1 w /*c,
priority=0 r /a*,
priority=-1 k /*b*,
/abc, /bc, /ac .. will have permissions of w
/ab, /abb, /aaa, .. will have permissions of r
/b, /bcb, /bab, .. will have permissions of k
User specified rule priorities are currently capped at the arbitrary
values of 1000, and -1000.
Notes:
* not all rule types support the priority prefix. Rukes like
- network
- capability
- rlimits need to be reworked
need to be reworked to properly preserve the policy rule structure.
* this patch does not support priority on rule blocks
* this patch does not support using a variable in the priority value.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-05-11 23:33:42 -07:00
|
|
|
priority/{WS}*= {
|
|
|
|
/* has to be before {VARIABLE_NAME} matches below */
|
|
|
|
PUSH_AND_RETURN(INTEGER_MODE, TOK_PRIORITY);
|
|
|
|
|
|
|
|
}
|
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
|
|
|
{VARIABLE_NAME}/{WS}*= {
|
2013-09-12 12:37:04 -07:00
|
|
|
/* we match to the = in the lexer so that we can switch scanner
|
|
|
|
* state. By the time the parser see the = it may be too late
|
|
|
|
* as bison may have requested the next token from the scanner
|
|
|
|
*/
|
2014-04-23 11:36:26 -07:00
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
PUSH_AND_RETURN(EXTCOND_MODE, TOK_CONDID);
|
2013-09-12 12:37:04 -07:00
|
|
|
}
|
2012-03-26 06:17:40 -07:00
|
|
|
{VARIABLE_NAME}/{WS}+in{WS}*\( {
|
2013-09-12 12:37:04 -07:00
|
|
|
/* we match to 'in' in the lexer so that we can switch scanner
|
|
|
|
* state. By the time the parser see the 'in' it may be to
|
|
|
|
* late as bison may have requested the next token from the
|
|
|
|
* scanner
|
|
|
|
*/
|
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
PUSH_AND_RETURN(EXTCOND_MODE, TOK_CONDID);
|
|
|
|
}
|
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-02-16 07:53:04 -08:00
|
|
|
|
2016-05-31 15:38:36 -05:00
|
|
|
<SUB_ID,SUB_ID_WS>{
|
2016-05-31 15:32:08 -05:00
|
|
|
({IDS}|{QUOTED_ID}) {
|
|
|
|
/* Go into separate state to match generic ID strings */
|
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
POP_AND_RETURN(TOK_ID);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
<SUB_VALUE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
({IDS}|{QUOTED_ID}) {
|
|
|
|
/* Go into separate state to match generic VALUE strings */
|
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
POP_AND_RETURN(TOK_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
|
|
|
}
|
|
|
|
|
2012-02-16 07:49:12 -08:00
|
|
|
<LIST_VAL_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{CLOSE_PAREN} { POP_AND_RETURN(TOK_CLOSEPAREN); }
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{COMMA} { EAT_TOKEN("listval: ,\n"); }
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
({LIST_VALUE_ID}|{QUOTED_ID}) {
|
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2012-02-16 07:51:33 -08:00
|
|
|
<EXTCOND_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{EQUALS}{WS}*/[^(\n]{-}{WS} { BEGIN_AND_RETURN(SUB_VALUE, TOK_EQUALS);}
|
2012-02-16 07:51:33 -08:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{EQUALS} { RETURN_TOKEN(TOK_EQUALS); }
|
2012-02-16 07:51:33 -08:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
/* Don't push state here as this is a transition start condition and
|
|
|
|
* we want to return to the start condition that invoked <EXTCOND_MODE>
|
|
|
|
* when LIST_VAL_ID is done
|
|
|
|
*/
|
|
|
|
{OPEN_PAREN} { BEGIN_AND_RETURN(LIST_VAL_MODE, TOK_OPENPAREN); }
|
2012-02-16 07:51:33 -08:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
in { RETURN_TOKEN(TOK_IN); }
|
2012-02-16 07:51:33 -08:00
|
|
|
}
|
|
|
|
|
2013-07-31 09:05:51 -07:00
|
|
|
<LIST_COND_VAL>{
|
|
|
|
({LIST_VALUE_ID}|{QUOTED_LIST_VALUE_ID}) {
|
2013-09-12 12:37:04 -07:00
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
POP_AND_RETURN(TOK_VALUE);
|
|
|
|
}
|
2013-07-31 09:05:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
<LIST_COND_PAREN_VAL>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{CLOSE_PAREN} { POP(); }
|
2013-07-31 09:05:51 -07:00
|
|
|
|
|
|
|
({LIST_VALUE_ID}|{QUOTED_LIST_VALUE_ID}) {
|
2013-09-12 12:37:04 -07:00
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
|
|
}
|
2013-07-31 09:05:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
<LIST_COND_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{CLOSE_PAREN} { POP_AND_RETURN(TOK_CLOSEPAREN); }
|
2013-07-31 09:05:51 -07:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{COMMA} { EAT_TOKEN("listcond: , \n"); }
|
2013-07-31 09:05:51 -07:00
|
|
|
|
|
|
|
{ID_CHARS_NOEQ}+ {
|
2013-09-12 12:37:04 -07:00
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
RETURN_TOKEN(TOK_CONDID);
|
|
|
|
}
|
2013-07-31 09:05:51 -07:00
|
|
|
|
|
|
|
{EQUALS}{WS}*{OPEN_PAREN} {
|
2013-09-12 12:37:04 -07:00
|
|
|
PUSH_AND_RETURN(LIST_COND_PAREN_VAL, TOK_EQUALS);
|
|
|
|
}
|
2013-07-31 09:05:51 -07:00
|
|
|
|
|
|
|
{EQUALS} {
|
2013-09-12 12:37:04 -07:00
|
|
|
PUSH_AND_RETURN(LIST_COND_VAL, TOK_EQUALS);
|
|
|
|
}
|
2013-07-31 09:05:51 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
<EXTCONDLIST_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{EQUALS} { RETURN_TOKEN(TOK_EQUALS); }
|
2013-07-31 09:05:51 -07:00
|
|
|
|
|
|
|
{OPEN_PAREN} {
|
2013-09-12 12:37:04 -07:00
|
|
|
/* Don't push state here as this is a transition
|
|
|
|
* start condition and we want to return to the start
|
|
|
|
* condition that invoked <EXTCONDLIST_MODE> when
|
|
|
|
* LIST_VAL_ID is done
|
|
|
|
*/
|
|
|
|
BEGIN_AND_RETURN(LIST_COND_MODE, TOK_OPENPAREN);
|
|
|
|
}
|
2013-07-31 09:05:51 -07:00
|
|
|
}
|
|
|
|
|
2006-04-11 21:52:54 +00:00
|
|
|
<ASSIGN_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
({IDS}|{QUOTED_ID}) {
|
|
|
|
yylval.var_val = processid(yytext, yyleng);
|
|
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{END_OF_RULE} {
|
|
|
|
yylval.id = strdup(yytext);
|
|
|
|
DUMP_PREPROCESS;
|
|
|
|
yyerror(_("Variable declarations do not accept trailing commas"));
|
|
|
|
}
|
2010-11-19 01:42:04 -08:00
|
|
|
|
parser: make lead # in assignment value indicate a comment
technically a # leading a value in an assignment expression is allowed,
however people are also using it to a comment at the end of a line.
ie.
@{var1}=value1 # comment about this value or for a given system
this unsurprisingly leads to odd/unexpected behavior when the variable
is used.
allow rw /@{var1},
expands into
allow rw /{value1,#,comment,about,this,value,or,for,a,given,system},
change a leading # as value in an assignment expression to a comment.
If the # is really supposed to lead the value, require it to be escaped
or in quotes.
ie.
@{var1}=value1 \#not_a_comment
Note: this could potentially break som policy if the # was used as the
leading character for a value in an assignment expression, but
is worth it to avoid the confusion.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-06-07 16:43:22 -07:00
|
|
|
#.*\r?\n { /* normal comment */
|
|
|
|
DUMP_AND_DEBUG("comment(%d): %s\n", current_lineno, yytext);
|
|
|
|
current_lineno++;
|
|
|
|
POP();
|
|
|
|
}
|
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
\\\n { DUMP_PREPROCESS; current_lineno++ ; }
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
\r?\n {
|
2020-06-12 02:05:35 -07:00
|
|
|
/* don't use shared rule because we need POP() here */
|
2013-09-12 12:37:04 -07:00
|
|
|
DUMP_PREPROCESS;
|
|
|
|
current_lineno++;
|
2014-04-23 11:16:08 -07:00
|
|
|
POP();
|
2013-09-12 12:37:04 -07:00
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
}
|
|
|
|
|
2007-07-27 20:29:47 +00:00
|
|
|
|
2009-07-23 21:18:37 +00:00
|
|
|
<CHANGE_PROFILE_MODE>{
|
2016-05-31 15:32:08 -05:00
|
|
|
safe { RETURN_TOKEN(TOK_SAFE); }
|
|
|
|
unsafe { RETURN_TOKEN(TOK_UNSAFE); }
|
|
|
|
|
|
|
|
{ARROW} {
|
|
|
|
/**
|
|
|
|
* Push state so that we can return TOK_ID even when the
|
|
|
|
* change_profile target is 'safe' or 'unsafe'.
|
|
|
|
*/
|
|
|
|
PUSH_AND_RETURN(SUB_ID_WS, TOK_ARROW);
|
|
|
|
}
|
2009-07-23 21:18:37 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
({IDS}|{QUOTED_ID}) {
|
|
|
|
yylval.id = processid(yytext, yyleng);
|
2015-06-12 15:25:10 -07:00
|
|
|
RETURN_TOKEN(TOK_ID);
|
2013-09-12 12:37:04 -07:00
|
|
|
}
|
2009-07-23 21:18:37 +00:00
|
|
|
}
|
|
|
|
|
2008-04-06 18:55:46 +00:00
|
|
|
<RLIMIT_MODE>{
|
2015-07-10 18:16:09 -07:00
|
|
|
-?{NUMBER} {
|
2013-09-12 12:37:04 -07:00
|
|
|
yylval.var_val = strdup(yytext);
|
|
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
|
|
}
|
2008-04-06 18:55:46 +00:00
|
|
|
|
|
|
|
{KEYWORD} {
|
2013-09-12 12:37:04 -07:00
|
|
|
yylval.id = strdup(yytext);
|
|
|
|
if (strcmp(yytext, "infinity") == 0)
|
|
|
|
RETURN_TOKEN(TOK_VALUE);
|
|
|
|
RETURN_TOKEN(TOK_ID);
|
|
|
|
}
|
2008-04-06 18:55:46 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{LT_EQUAL} { RETURN_TOKEN(TOK_LE); }
|
2008-04-06 18:55:46 +00:00
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2024-01-08 16:09:13 -03:00
|
|
|
<UNIX_MODE,NETWORK_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
|
|
|
listen { RETURN_TOKEN(TOK_LISTEN); }
|
|
|
|
accept { RETURN_TOKEN(TOK_ACCEPT); }
|
|
|
|
connect { RETURN_TOKEN(TOK_CONNECT); }
|
|
|
|
getopt { RETURN_TOKEN(TOK_GETOPT); }
|
|
|
|
setopt { RETURN_TOKEN(TOK_SETOPT); }
|
|
|
|
shutdown { RETURN_TOKEN(TOK_SHUTDOWN); }
|
|
|
|
}
|
|
|
|
|
2024-01-08 16:09:13 -03:00
|
|
|
<UNIX_MODE,USERNS_MODE,MQUEUE_MODE,NETWORK_MODE>{
|
2022-09-29 17:40:18 -03:00
|
|
|
create { RETURN_TOKEN(TOK_CREATE); }
|
|
|
|
}
|
|
|
|
|
2022-02-07 19:15:11 -03:00
|
|
|
<MQUEUE_MODE>{
|
|
|
|
open { RETURN_TOKEN(TOK_OPEN); }
|
|
|
|
delete { RETURN_TOKEN(TOK_DELETE); }
|
|
|
|
}
|
|
|
|
|
2024-01-08 16:09:13 -03:00
|
|
|
<UNIX_MODE,MQUEUE_MODE,NETWORK_MODE>{
|
2022-02-07 19:15:11 -03:00
|
|
|
getattr { RETURN_TOKEN(TOK_GETATTR); }
|
|
|
|
setattr { RETURN_TOKEN(TOK_SETATTR); }
|
|
|
|
}
|
|
|
|
|
2024-01-08 16:09:13 -03:00
|
|
|
<DBUS_MODE,UNIX_MODE,NETWORK_MODE>{
|
2014-04-23 11:35:29 -07:00
|
|
|
bind { RETURN_TOKEN(TOK_BIND); }
|
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
|
|
|
}
|
|
|
|
|
|
|
|
<DBUS_MODE>{
|
2014-04-23 11:35:29 -07:00
|
|
|
eavesdrop { RETURN_TOKEN(TOK_EAVESDROP); }
|
|
|
|
}
|
|
|
|
|
2024-01-08 16:09:13 -03:00
|
|
|
<DBUS_MODE,SIGNAL_MODE,UNIX_MODE,NETWORK_MODE>{
|
2013-07-31 09:05:51 -07:00
|
|
|
send { RETURN_TOKEN(TOK_SEND); }
|
|
|
|
receive { RETURN_TOKEN(TOK_RECEIVE); }
|
2014-04-23 11:38:04 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
<PTRACE_MODE>{
|
|
|
|
trace { RETURN_TOKEN(TOK_TRACE); }
|
|
|
|
readby { RETURN_TOKEN(TOK_READBY); }
|
|
|
|
tracedby { RETURN_TOKEN(TOK_TRACEDBY); }
|
|
|
|
}
|
|
|
|
|
2024-01-08 16:09:13 -03:00
|
|
|
<DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,MQUEUE_MODE,NETWORK_MODE>{
|
2013-07-31 09:05:51 -07:00
|
|
|
read { RETURN_TOKEN(TOK_READ); }
|
|
|
|
write { RETURN_TOKEN(TOK_WRITE); }
|
|
|
|
{OPEN_PAREN} {
|
2014-04-23 11:16:08 -07:00
|
|
|
PUSH_AND_RETURN(LIST_VAL_MODE, TOK_OPENPAREN);
|
2013-07-31 09:05:51 -07:00
|
|
|
}
|
|
|
|
(r|w|rw|wr)/([[:space:],]) {
|
|
|
|
yylval.mode = strdup(yytext);
|
|
|
|
RETURN_TOKEN(TOK_MODE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-23 11:38:04 -07:00
|
|
|
<MOUNT_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{ARROW} { RETURN_TOKEN(TOK_ARROW); }
|
2014-04-23 11:38:04 -07: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
|
|
|
|
2023-03-20 12:28:53 -03:00
|
|
|
<IOURING_MODE>{
|
|
|
|
override_creds { RETURN_TOKEN(TOK_OVERRIDE_CREDS); }
|
|
|
|
sqpoll { RETURN_TOKEN(TOK_SQPOLL); }
|
|
|
|
}
|
|
|
|
|
2023-08-30 14:06:22 -03:00
|
|
|
<MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,MQUEUE_MODE,IOURING_MODE,NETWORK_MODE>{
|
2016-02-18 15:58:06 -06:00
|
|
|
({IDS_NOEQ}|{LABEL}|{QUOTED_ID}) {
|
2013-09-12 12:37:04 -07:00
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
RETURN_TOKEN(TOK_ID);
|
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
parser: add the ability to specify a priority prefix to rules
This enables adding a priority to a rules in policy, finishing out the
priority work done to plumb priority support through the internals in
the previous patch.
Rules have a default priority of 0. The priority prefix can be added
before the other currently support rule prefixes, ie.
[priority prefix][audit qualifier][rule mode][owner]
If present a numerical priority can be assigned to the rule, where the
greater the number the higher the priority. Eg.
priority=1 audit file r /etc/passwd,
priority=-1 deny file w /etc/**,
Rule priority allows the rule with the highest priority to completely
override lower priority rules where they overlap. Within a given
priority level rules will accumulate in standard apparmor fashion.
Eg. given
priority=1 w /*c,
priority=0 r /a*,
priority=-1 k /*b*,
/abc, /bc, /ac .. will have permissions of w
/ab, /abb, /aaa, .. will have permissions of r
/b, /bcb, /bab, .. will have permissions of k
User specified rule priorities are currently capped at the arbitrary
values of 1000, and -1000.
Notes:
* not all rule types support the priority prefix. Rukes like
- network
- capability
- rlimits need to be reworked
need to be reworked to properly preserve the policy rule structure.
* this patch does not support priority on rule blocks
* this patch does not support using a variable in the priority value.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-05-11 23:33:42 -07:00
|
|
|
<INTEGER_MODE>{
|
|
|
|
{EQUALS} { RETURN_TOKEN(TOK_EQUALS); }
|
|
|
|
|
|
|
|
{INTEGER} {
|
|
|
|
yylval.mode = strdup(yytext);
|
|
|
|
POP_AND_RETURN(TOK_VALUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-07 01:06:10 -08:00
|
|
|
#include{WS}+if{WS}+exists/{WS}.*\r?\n {
|
|
|
|
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
|
|
|
* It needs to be handled specially
|
|
|
|
*/
|
2022-07-28 15:03:39 -07:00
|
|
|
pwarn(WARN_INCLUDE, _("deprecated use of '#include'\n"));
|
2018-01-07 01:06:10 -08:00
|
|
|
yy_push_state(INCLUDE_EXISTS);
|
|
|
|
}
|
|
|
|
|
|
|
|
include{WS}+if{WS}+exists/{WS} {
|
|
|
|
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
|
|
|
* It needs to be handled specially
|
|
|
|
*/
|
|
|
|
yy_push_state(INCLUDE_EXISTS);
|
|
|
|
}
|
|
|
|
|
2014-02-02 19:23:10 -10:00
|
|
|
#include/.*\r?\n {
|
2014-04-23 11:16:08 -07:00
|
|
|
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
|
|
|
* It needs to be handled specially
|
2015-07-08 17:19:57 -07:00
|
|
|
*/
|
2022-07-28 15:03:39 -07:00
|
|
|
pwarn(WARN_INCLUDE, _("deprecated use of '#include'\n"));
|
2015-07-08 17:19:57 -07:00
|
|
|
yy_push_state(INCLUDE);
|
|
|
|
}
|
|
|
|
|
|
|
|
include/{WS} {
|
|
|
|
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
|
|
|
* It needs to be handled specially
|
|
|
|
*/
|
2014-02-02 19:23:10 -10:00
|
|
|
yy_push_state(INCLUDE);
|
|
|
|
}
|
2012-01-02 16:47:32 -08:00
|
|
|
|
2023-09-21 20:39:27 -07:00
|
|
|
all/({WS}|[^[:alnum:]_]) {
|
|
|
|
RETURN_TOKEN(TOK_ALL);
|
|
|
|
}
|
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
#.*\r?\n { /* normal comment */
|
|
|
|
DUMP_AND_DEBUG("comment(%d): %s\n", current_lineno, yytext);
|
|
|
|
current_lineno++;
|
|
|
|
}
|
2012-01-02 16:47:32 -08:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{CARET} { PUSH_AND_RETURN(SUB_ID, TOK_CARET); }
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2019-02-02 21:51:05 +01:00
|
|
|
{ARROW} { PUSH_AND_RETURN(SUB_ID_WS, TOK_ARROW); }
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{EQUALS} { PUSH_AND_RETURN(ASSIGN_MODE, TOK_EQUALS); }
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{ADD_ASSIGN} { PUSH_AND_RETURN(ASSIGN_MODE, TOK_ADD_ASSIGN); }
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{SET_VARIABLE} {
|
|
|
|
yylval.set_var = strdup(yytext);
|
|
|
|
RETURN_TOKEN(TOK_SET_VAR);
|
|
|
|
}
|
2007-07-27 20:48:24 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{BOOL_VARIABLE} {
|
|
|
|
yylval.bool_var = strdup(yytext);
|
|
|
|
RETURN_TOKEN(TOK_BOOL_VAR);
|
|
|
|
}
|
2012-01-02 16:48:53 -08:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{OPEN_BRACE} { RETURN_TOKEN(TOK_OPEN); }
|
2007-11-16 09:18:48 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{CLOSE_BRACE} { RETURN_TOKEN(TOK_CLOSE); }
|
2007-11-16 09:31:33 +00:00
|
|
|
|
2016-02-18 15:58:06 -06:00
|
|
|
({LABEL}|{QUOTED_LABEL}) {
|
2013-09-12 12:37:04 -07:00
|
|
|
yylval.id = processid(yytext, yyleng);
|
|
|
|
RETURN_TOKEN(TOK_ID);
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
({MODES})/([[:space:],]) {
|
|
|
|
yylval.mode = strdup(yytext);
|
|
|
|
RETURN_TOKEN(TOK_MODE);
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2013-09-12 12:37:04 -07:00
|
|
|
{HAT} { PUSH_AND_RETURN(SUB_ID, TOK_HAT); }
|
|
|
|
|
|
|
|
{PROFILE} { PUSH_AND_RETURN(SUB_ID, TOK_PROFILE); }
|
|
|
|
|
|
|
|
{COLON} { RETURN_TOKEN(TOK_COLON); }
|
|
|
|
|
|
|
|
{OPEN_PAREN} { PUSH_AND_RETURN(LIST_VAL_MODE, TOK_OPENPAREN); }
|
|
|
|
|
|
|
|
{VARIABLE_NAME} {
|
|
|
|
int token = get_keyword_token(yytext);
|
|
|
|
int state = INITIAL;
|
|
|
|
|
|
|
|
/* special cases */
|
|
|
|
switch (token) {
|
|
|
|
case -1:
|
|
|
|
/* no token found */
|
|
|
|
yylval.id = processunquoted(yytext, yyleng);
|
|
|
|
RETURN_TOKEN(TOK_ID);
|
|
|
|
break;
|
|
|
|
case TOK_RLIMIT:
|
|
|
|
state = RLIMIT_MODE;
|
|
|
|
break;
|
|
|
|
case TOK_NETWORK:
|
|
|
|
state = NETWORK_MODE;
|
|
|
|
break;
|
|
|
|
case TOK_CHANGE_PROFILE:
|
|
|
|
state = CHANGE_PROFILE_MODE;
|
|
|
|
break;
|
|
|
|
case TOK_MOUNT:
|
|
|
|
case TOK_REMOUNT:
|
|
|
|
case TOK_UMOUNT:
|
|
|
|
state = MOUNT_MODE;
|
|
|
|
break;
|
|
|
|
case TOK_DBUS:
|
|
|
|
state = DBUS_MODE;
|
|
|
|
break;
|
2014-04-23 11:35:29 -07:00
|
|
|
case TOK_SIGNAL:
|
|
|
|
state = SIGNAL_MODE;
|
|
|
|
break;
|
2014-04-23 11:38:04 -07:00
|
|
|
case TOK_PTRACE:
|
|
|
|
state = PTRACE_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
|
|
|
break;
|
|
|
|
case TOK_UNIX:
|
|
|
|
state = UNIX_MODE;
|
|
|
|
break;
|
2018-09-19 01:15:49 -07:00
|
|
|
case TOK_ABI:
|
|
|
|
state = ABI_MODE;
|
|
|
|
break;
|
2022-09-29 17:40:18 -03:00
|
|
|
case TOK_USERNS:
|
|
|
|
state = USERNS_MODE;
|
|
|
|
break;
|
2022-02-07 19:15:11 -03:00
|
|
|
case TOK_MQUEUE:
|
|
|
|
state = MQUEUE_MODE;
|
|
|
|
break;
|
2013-09-12 12:37:04 -07:00
|
|
|
default: /* nothing */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
PUSH_AND_RETURN(state, token);
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2023-03-20 12:28:53 -03:00
|
|
|
<INITIAL,NETWORK_MODE,RLIMIT_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,ABI_MODE,USERNS_MODE,MQUEUE_MODE,IOURING_MODE>{
|
2013-09-12 12:37:04 -07:00
|
|
|
{END_OF_RULE} {
|
|
|
|
if (YY_START != INITIAL)
|
2014-04-23 11:17:41 -07:00
|
|
|
POP_NODUMP();
|
2013-09-12 12:37:04 -07:00
|
|
|
RETURN_TOKEN(TOK_END_OF_RULE);
|
|
|
|
}
|
2020-06-12 02:05:35 -07:00
|
|
|
}
|
2010-06-26 13:13:52 -07:00
|
|
|
|
2023-03-20 12:28:53 -03:00
|
|
|
<INITIAL,SUB_ID_WS,INCLUDE,INCLUDE_EXISTS,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,RLIMIT_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,ABI_MODE,USERNS_MODE,MQUEUE_MODE,IOURING_MODE>{
|
2020-06-12 02:05:35 -07:00
|
|
|
\r?\n {
|
2013-09-12 12:37:04 -07:00
|
|
|
DUMP_PREPROCESS;
|
|
|
|
current_lineno++;
|
|
|
|
}
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
|
2023-03-20 12:28:53 -03:00
|
|
|
<INITIAL,SUB_ID,SUB_ID_WS,SUB_VALUE,LIST_VAL_MODE,EXTCOND_MODE,LIST_COND_VAL,LIST_COND_PAREN_VAL,LIST_COND_MODE,EXTCONDLIST_MODE,ASSIGN_MODE,NETWORK_MODE,CHANGE_PROFILE_MODE,MOUNT_MODE,DBUS_MODE,SIGNAL_MODE,PTRACE_MODE,UNIX_MODE,RLIMIT_MODE,INCLUDE,INCLUDE_EXISTS,ABI_MODE,USERNS_MODE,MQUEUE_MODE,IOURING_MODE>{
|
2020-06-12 01:10:07 -07:00
|
|
|
(.|\n) {
|
2013-09-12 12:37:04 -07:00
|
|
|
DUMP_PREPROCESS;
|
|
|
|
/* Something we didn't expect */
|
2020-06-12 01:10:07 -07:00
|
|
|
yyerror(_("Lexer found unexpected character: '%s' (0x%x) in state: %s"), yytext, yytext[0], state_names[YY_START].c_str());
|
2013-09-12 12:37:04 -07:00
|
|
|
}
|
|
|
|
}
|
2006-04-11 21:52:54 +00:00
|
|
|
%%
|
2013-09-12 12:37:04 -07:00
|
|
|
|
|
|
|
/* Create a table mapping lexer state number to the name used in the
|
|
|
|
* in the code. This allows for better debug output
|
|
|
|
*/
|
2013-11-18 16:23:23 -08:00
|
|
|
unordered_map<int, string> state_names = {
|
2013-09-12 12:37:04 -07:00
|
|
|
STATE_TABLE_ENT(INITIAL),
|
|
|
|
STATE_TABLE_ENT(SUB_ID),
|
2016-05-31 15:32:08 -05:00
|
|
|
STATE_TABLE_ENT(SUB_ID_WS),
|
2013-09-12 12:37:04 -07:00
|
|
|
STATE_TABLE_ENT(SUB_VALUE),
|
|
|
|
STATE_TABLE_ENT(EXTCOND_MODE),
|
|
|
|
STATE_TABLE_ENT(EXTCONDLIST_MODE),
|
|
|
|
STATE_TABLE_ENT(NETWORK_MODE),
|
|
|
|
STATE_TABLE_ENT(LIST_VAL_MODE),
|
2013-09-27 16:13:22 -07:00
|
|
|
STATE_TABLE_ENT(LIST_COND_MODE),
|
|
|
|
STATE_TABLE_ENT(LIST_COND_VAL),
|
|
|
|
STATE_TABLE_ENT(LIST_COND_PAREN_VAL),
|
2013-09-12 12:37:04 -07:00
|
|
|
STATE_TABLE_ENT(ASSIGN_MODE),
|
|
|
|
STATE_TABLE_ENT(RLIMIT_MODE),
|
|
|
|
STATE_TABLE_ENT(MOUNT_MODE),
|
2013-09-27 16:13:22 -07:00
|
|
|
STATE_TABLE_ENT(DBUS_MODE),
|
2014-04-23 11:35:29 -07:00
|
|
|
STATE_TABLE_ENT(SIGNAL_MODE),
|
2014-04-23 11:38:04 -07:00
|
|
|
STATE_TABLE_ENT(PTRACE_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
|
|
|
STATE_TABLE_ENT(UNIX_MODE),
|
2013-09-12 12:37:04 -07:00
|
|
|
STATE_TABLE_ENT(CHANGE_PROFILE_MODE),
|
|
|
|
STATE_TABLE_ENT(INCLUDE),
|
2018-01-07 01:06:10 -08:00
|
|
|
STATE_TABLE_ENT(INCLUDE_EXISTS),
|
2018-09-19 01:15:49 -07:00
|
|
|
STATE_TABLE_ENT(ABI_MODE),
|
2022-09-29 17:40:18 -03:00
|
|
|
STATE_TABLE_ENT(USERNS_MODE),
|
2022-02-07 19:15:11 -03:00
|
|
|
STATE_TABLE_ENT(MQUEUE_MODE),
|
2023-03-20 12:28:53 -03:00
|
|
|
STATE_TABLE_ENT(IOURING_MODE),
|
parser: add the ability to specify a priority prefix to rules
This enables adding a priority to a rules in policy, finishing out the
priority work done to plumb priority support through the internals in
the previous patch.
Rules have a default priority of 0. The priority prefix can be added
before the other currently support rule prefixes, ie.
[priority prefix][audit qualifier][rule mode][owner]
If present a numerical priority can be assigned to the rule, where the
greater the number the higher the priority. Eg.
priority=1 audit file r /etc/passwd,
priority=-1 deny file w /etc/**,
Rule priority allows the rule with the highest priority to completely
override lower priority rules where they overlap. Within a given
priority level rules will accumulate in standard apparmor fashion.
Eg. given
priority=1 w /*c,
priority=0 r /a*,
priority=-1 k /*b*,
/abc, /bc, /ac .. will have permissions of w
/ab, /abb, /aaa, .. will have permissions of r
/b, /bcb, /bab, .. will have permissions of k
User specified rule priorities are currently capped at the arbitrary
values of 1000, and -1000.
Notes:
* not all rule types support the priority prefix. Rukes like
- network
- capability
- rlimits need to be reworked
need to be reworked to properly preserve the policy rule structure.
* this patch does not support priority on rule blocks
* this patch does not support using a variable in the priority value.
Signed-off-by: John Johansen <john.johansen@canonical.com>
2024-05-11 23:33:42 -07:00
|
|
|
STATE_TABLE_ENT(INTEGER_MODE),
|
2013-09-12 12:37:04 -07:00
|
|
|
};
|