mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-29 05:17:59 +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(void);
|
||||||
extern void dump_policy_hats(struct codomain *cod);
|
extern void dump_policy_hats(struct codomain *cod);
|
||||||
extern void dump_policy_names(void);
|
extern void dump_policy_names(void);
|
||||||
|
extern int die_if_any_regex(void);
|
||||||
|
@ -44,7 +44,9 @@
|
|||||||
#define OLD_MODULE_NAME "subdomain"
|
#define OLD_MODULE_NAME "subdomain"
|
||||||
#define PROC_MODULES "/proc/modules"
|
#define PROC_MODULES "/proc/modules"
|
||||||
#define DEFAULT_APPARMORFS "/sys/kernel/security/" MODULE_NAME
|
#define DEFAULT_APPARMORFS "/sys/kernel/security/" MODULE_NAME
|
||||||
|
#define MATCH_STRING "/sys/kernel/security/" MODULE_NAME "/matching"
|
||||||
#define MOUNTED_FS "/proc/mounts"
|
#define MOUNTED_FS "/proc/mounts"
|
||||||
|
#define PCRE "pattern=pcre"
|
||||||
|
|
||||||
#define UNPRIVILEGED_OPS (debug || preprocess_only || option == OPTION_STDOUT || names_only || \
|
#define UNPRIVILEGED_OPS (debug || preprocess_only || option == OPTION_STDOUT || names_only || \
|
||||||
dump_vars || dump_expanded_vars)
|
dump_vars || dump_expanded_vars)
|
||||||
@ -59,6 +61,7 @@ int dump_vars = 0;
|
|||||||
int dump_expanded_vars = 0;
|
int dump_expanded_vars = 0;
|
||||||
char *subdomainbase = NULL;
|
char *subdomainbase = NULL;
|
||||||
char *profilename;
|
char *profilename;
|
||||||
|
char *match_string = NULL;
|
||||||
|
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
{"add", 0, 0, 'a'},
|
{"add", 0, 0, 'a'},
|
||||||
@ -77,6 +80,7 @@ struct option long_options[] = {
|
|||||||
{"remove", 0, 0, 'R'},
|
{"remove", 0, 0, 'R'},
|
||||||
{"names", 0, 0, 'N'}, /* undocumented only emit profilenames */
|
{"names", 0, 0, 'N'}, /* undocumented only emit profilenames */
|
||||||
{"stdout", 0, 0, 'S'},
|
{"stdout", 0, 0, 'S'},
|
||||||
|
{"match-string", 1, 0, 'm'},
|
||||||
{NULL, 0, 0, 0},
|
{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"
|
"-I n, --Include n Add n to the search path\n"
|
||||||
"-b n, --base n Set base dir and cwd\n"
|
"-b n, --base n Set base dir and cwd\n"
|
||||||
"-f n, --subdomainfs n Set location of apparmor filesystem\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[])
|
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 option = OPTION_ADD;
|
||||||
int count = 0;
|
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) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -174,6 +179,9 @@ static int process_args(int argc, char *argv[])
|
|||||||
case 'E':
|
case 'E':
|
||||||
dump_expanded_vars = 1;
|
dump_expanded_vars = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
match_string = strdup(optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
display_usage(progname);
|
display_usage(progname);
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -342,6 +350,51 @@ int have_enough_privilege(void)
|
|||||||
return 0;
|
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 process_profile(int option, char *profilename)
|
||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
@ -387,6 +440,10 @@ int process_profile(int option, char *profilename)
|
|||||||
if (!subdomainbase && !preprocess_only && !(option == OPTION_STDOUT))
|
if (!subdomainbase && !preprocess_only && !(option == OPTION_STDOUT))
|
||||||
find_subdomainfs_mountpoint();
|
find_subdomainfs_mountpoint();
|
||||||
|
|
||||||
|
if (!pcre_support()) {
|
||||||
|
die_if_any_regex();
|
||||||
|
}
|
||||||
|
|
||||||
retval = load_policy(option);
|
retval = load_policy(option);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -117,6 +117,56 @@ int merge_hat_rules(struct codomain *cod)
|
|||||||
return 0;
|
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,
|
static void __process_regex(const void *nodep, const VISIT value,
|
||||||
const int __unused depth)
|
const int __unused depth)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user