mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
A quick hack that will test if the running kernel supports PCRE or not, and bail out with a more informative error message if the policy being loaded requires additional kernel support
This commit is contained in:
parent
b04af48255
commit
eb6ca6797b
@ -213,3 +213,4 @@ extern void free_policy(struct codomain *cod);
|
||||
extern void dump_policy(void);
|
||||
extern void dump_policy_hats(struct codomain *cod);
|
||||
extern void dump_policy_names(void);
|
||||
extern int die_if_any_regex(void);
|
||||
|
@ -44,7 +44,9 @@
|
||||
#define OLD_MODULE_NAME "subdomain"
|
||||
#define PROC_MODULES "/proc/modules"
|
||||
#define DEFAULT_APPARMORFS "/sys/kernel/security/" MODULE_NAME
|
||||
#define MATCH_STRING "/sys/kernel/security/" MODULE_NAME "/matching"
|
||||
#define MOUNTED_FS "/proc/mounts"
|
||||
#define PCRE "pattern=pcre"
|
||||
|
||||
#define UNPRIVILEGED_OPS (debug || preprocess_only || option == OPTION_STDOUT || names_only || \
|
||||
dump_vars || dump_expanded_vars)
|
||||
@ -59,6 +61,7 @@ int dump_vars = 0;
|
||||
int dump_expanded_vars = 0;
|
||||
char *subdomainbase = NULL;
|
||||
char *profilename;
|
||||
char *match_string = NULL;
|
||||
|
||||
struct option long_options[] = {
|
||||
{"add", 0, 0, 'a'},
|
||||
@ -77,6 +80,7 @@ struct option long_options[] = {
|
||||
{"remove", 0, 0, 'R'},
|
||||
{"names", 0, 0, 'N'}, /* undocumented only emit profilenames */
|
||||
{"stdout", 0, 0, 'S'},
|
||||
{"match-string", 1, 0, 'm'},
|
||||
{NULL, 0, 0, 0},
|
||||
};
|
||||
|
||||
@ -105,7 +109,8 @@ static void display_usage(char *command)
|
||||
"-I n, --Include n Add n to the search path\n"
|
||||
"-b n, --base n Set base dir and cwd\n"
|
||||
"-f n, --subdomainfs n Set location of apparmor filesystem\n"
|
||||
"-S, --stdout Write output to stdout\n", command);
|
||||
"-S, --stdout Write output to stdout\n"
|
||||
"-m n, --match-string n Use only match features n\n", command);
|
||||
}
|
||||
|
||||
static int process_args(int argc, char *argv[])
|
||||
@ -114,7 +119,7 @@ static int process_args(int argc, char *argv[])
|
||||
int option = OPTION_ADD;
|
||||
int count = 0;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "adf:hrRvpI:b:CNS", long_options, &o)) != -1)
|
||||
while ((c = getopt_long(argc, argv, "adf:hrRvpI:b:CNSm:", long_options, &o)) != -1)
|
||||
{
|
||||
switch (c) {
|
||||
case 0:
|
||||
@ -174,6 +179,9 @@ static int process_args(int argc, char *argv[])
|
||||
case 'E':
|
||||
dump_expanded_vars = 1;
|
||||
break;
|
||||
case 'm':
|
||||
match_string = strdup(optarg);
|
||||
break;
|
||||
default:
|
||||
display_usage(progname);
|
||||
exit(0);
|
||||
@ -342,6 +350,51 @@ int have_enough_privilege(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* match_string == NULL --> no match_string available
|
||||
match_string != NULL --> either a matching string specified on the
|
||||
command line, or the kernel supplied a match string */
|
||||
static void get_match_string(void) {
|
||||
|
||||
/* has process_args() already assigned a match string? */
|
||||
if (match_string)
|
||||
return;
|
||||
|
||||
FILE *ms = fopen(MATCH_STRING, "r");
|
||||
if (!ms)
|
||||
return;
|
||||
|
||||
match_string = malloc(1000);
|
||||
if (!match_string) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fgets(match_string, 1000, ms)) {
|
||||
free(match_string);
|
||||
match_string = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
fclose(ms);
|
||||
return;
|
||||
}
|
||||
|
||||
/* return 1 --> PCRE should work fine
|
||||
return 0 --> no PCRE support */
|
||||
static int pcre_support(void) {
|
||||
|
||||
get_match_string();
|
||||
|
||||
/* no match string, predates (or postdates?) the split matching
|
||||
module design */
|
||||
if (!match_string)
|
||||
return 1;
|
||||
|
||||
if (strstr(match_string, PCRE))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int process_profile(int option, char *profilename)
|
||||
{
|
||||
int retval = 0;
|
||||
@ -387,6 +440,10 @@ int process_profile(int option, char *profilename)
|
||||
if (!subdomainbase && !preprocess_only && !(option == OPTION_STDOUT))
|
||||
find_subdomainfs_mountpoint();
|
||||
|
||||
if (!pcre_support()) {
|
||||
die_if_any_regex();
|
||||
}
|
||||
|
||||
retval = load_policy(option);
|
||||
|
||||
out:
|
||||
|
@ -117,6 +117,56 @@ int merge_hat_rules(struct codomain *cod)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int die_if_any_regex(void);
|
||||
static int die_if_any_hat_regex(struct codomain *cod);
|
||||
static int any_regex_entries(struct cod_entry *entry_list);
|
||||
|
||||
/* only call if regex is not allowed */
|
||||
static void __any_regex(const void *nodep, const VISIT value,
|
||||
const int __unused depth)
|
||||
{
|
||||
struct codomain **t = (struct codomain **) nodep;
|
||||
|
||||
if (value == preorder || value == endorder)
|
||||
return;
|
||||
|
||||
if (any_regex_entries(*t)) {
|
||||
PERROR(_("ERROR profile %s contains policy elements not usable with this kernel:\n"
|
||||
"\t'*', '?', character ranges, and alternations are not allowed.\n"
|
||||
"\t'**' may only be used at the end of a rule.\n"),
|
||||
(*t)->name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
die_if_any_hat_regex(*t);
|
||||
}
|
||||
|
||||
/* only call if regex is not allowed */
|
||||
int die_if_any_regex(void)
|
||||
{
|
||||
twalk(policy_list, __any_regex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* only call if regex is not allowed */
|
||||
static int die_if_any_hat_regex(struct codomain *cod)
|
||||
{
|
||||
twalk(cod->hat_table, __any_regex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int any_regex_entries(struct cod_entry *entry_list)
|
||||
{
|
||||
struct cod_entry *entry;
|
||||
|
||||
for (entry = entry_list; entry; entry = entry->next) {
|
||||
if (entry->pattern_type == ePatternRegex)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void __process_regex(const void *nodep, const VISIT value,
|
||||
const int __unused depth)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user