mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
parser: and prompt-compat control flag
Allow contronling which prompt compat mode fallback is used. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
5c2bd20720
commit
1d0d1fd0c2
5 changed files with 87 additions and 9 deletions
|
@ -324,6 +324,10 @@ do { \
|
|||
/* The parser fills this variable in automatically */
|
||||
#define PROFILE_NAME_VARIABLE "profile_name"
|
||||
|
||||
#define PROMPT_COMPAT_IGNORE 0
|
||||
#define PROMPT_COMPAT_PERMSV2 1
|
||||
#define PROMPT_COMPAT_PERMSV1 2
|
||||
|
||||
/* from parser_common.c */
|
||||
extern uint32_t policy_version;
|
||||
extern uint32_t parser_abi_version;
|
||||
|
@ -361,6 +365,7 @@ extern int features_supports_flag_error;
|
|||
extern int kernel_supports_oob;
|
||||
extern int kernel_supports_permstable32;
|
||||
extern int kernel_supports_permstable32_v1;
|
||||
extern int prompt_compat_mode;
|
||||
extern int conf_verbose;
|
||||
extern int conf_quiet;
|
||||
extern int names_only;
|
||||
|
@ -376,6 +381,10 @@ extern IncludeCache_t *g_includecache;
|
|||
|
||||
extern void pwarnf(bool werr, const char *fmt, ...) __attribute__((__format__(__printf__, 2, 3)));
|
||||
extern void common_warn_once(const char *name, const char *msg, const char **warned_name);
|
||||
bool prompt_compat_mode_supported(int mode);
|
||||
int default_prompt_compat_mode();
|
||||
void print_prompt_compat_mode(FILE *f);
|
||||
|
||||
|
||||
#define pwarn(F, args...) do { if (parseopts.warn & (F)) pwarnf((parseopts.Werror & (F)), ## args); } while (0)
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ int features_supports_flag_error = 0;
|
|||
int kernel_supports_oob = 0; /* out of band transitions */
|
||||
int kernel_supports_permstable32 = 0; /* extended permissions */
|
||||
int kernel_supports_permstable32_v1 = 0; /* extended permissions */
|
||||
int prompt_compat_mode = 0;
|
||||
int conf_verbose = 0;
|
||||
int conf_quiet = 0;
|
||||
int names_only = 0;
|
||||
|
@ -168,3 +169,45 @@ void common_warn_once(const char *name, const char *msg, const char **warned_nam
|
|||
if (parseopts.Werror & WARN_RULE_NOT_ENFORCED)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bool prompt_compat_mode_supported(int mode)
|
||||
{
|
||||
if (mode == PROMPT_COMPAT_PERMSV2 &&
|
||||
(kernel_supports_permstable32 && !kernel_supports_permstable32_v1))
|
||||
return true;
|
||||
else if (mode == PROMPT_COMPAT_PERMSV1 &&
|
||||
(kernel_supports_permstable32_v1))
|
||||
return true;
|
||||
else if (mode == PROMPT_COMPAT_IGNORE)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int default_prompt_compat_mode()
|
||||
{
|
||||
if (prompt_compat_mode_supported(PROMPT_COMPAT_PERMSV2))
|
||||
return PROMPT_COMPAT_PERMSV2;
|
||||
if (prompt_compat_mode_supported(PROMPT_COMPAT_PERMSV1))
|
||||
return PROMPT_COMPAT_PERMSV1;
|
||||
if (prompt_compat_mode_supported(PROMPT_COMPAT_IGNORE))
|
||||
return PROMPT_COMPAT_IGNORE;
|
||||
return PROMPT_COMPAT_IGNORE;
|
||||
}
|
||||
|
||||
void print_prompt_compat_mode(FILE *f)
|
||||
{
|
||||
switch (prompt_compat_mode) {
|
||||
case PROMPT_COMPAT_IGNORE:
|
||||
fprintf(f, "ignore");
|
||||
break;
|
||||
case PROMPT_COMPAT_PERMSV2:
|
||||
fprintf(f, "permsv2");
|
||||
break;
|
||||
case PROMPT_COMPAT_PERMSV1:
|
||||
fprintf(f, "permsv1");
|
||||
break;
|
||||
default:
|
||||
fprintf(f, "Unknown prompt compat mode '%d'", prompt_compat_mode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -549,14 +549,14 @@ void sd_serialize_profile(std::ostringstream &buf, Profile *profile,
|
|||
// fprintf(stderr, "profile %s: policy xtable\n", profile->name);
|
||||
// TODO: this is dummy exec make dependent on V1
|
||||
sd_serialize_xtable(buf, profile->exec_table,
|
||||
kernel_supports_permstable32_v1 ?
|
||||
profile->uses_prompt_rules && prompt_compat_mode == PROMPT_COMPAT_PERMSV1 ?
|
||||
profile->policy.perms_table.size() : 0);
|
||||
}
|
||||
sd_write_structend(buf);
|
||||
}
|
||||
|
||||
/* either have a single dfa or lists of different entry types */
|
||||
if (kernel_supports_permstable32_v1) {
|
||||
if (profile->uses_prompt_rules && prompt_compat_mode == PROMPT_COMPAT_PERMSV1) {
|
||||
/* special compat mode to work around verification problem */
|
||||
sd_serialize_dfa(buf, profile->policy.dfa, profile->policy.size,
|
||||
profile->policy.perms_table);
|
||||
|
|
|
@ -137,6 +137,8 @@ static const char *config_file = "/etc/apparmor/parser.conf";
|
|||
#define EARLY_ARG_CONFIG_FILE 142
|
||||
#define ARG_WERROR 143
|
||||
#define ARG_ESTIMATED_COMPILE_SIZE 144
|
||||
#define ARG_PROMPT_COMPAT 145
|
||||
#define ARG_PRINT_PROMPT_COMPAT 146
|
||||
|
||||
/* Make sure to update BOTH the short and long_options */
|
||||
static const char *short_options = "ad::f:h::rRVvI:b:BCD:NSm:M:qQn:XKTWkL:O:po:j:";
|
||||
|
@ -192,6 +194,8 @@ struct option long_options[] = {
|
|||
{"override-policy-abi", 1, 0, ARG_OVERRIDE_POLICY_ABI}, /* no short option */
|
||||
{"config-file", 1, 0, EARLY_ARG_CONFIG_FILE}, /* early option, no short option */
|
||||
{"estimated-compile-size", 1, 0, ARG_ESTIMATED_COMPILE_SIZE}, /* no short option, not in help */
|
||||
{"prompt-compat", 1, 0, ARG_PROMPT_COMPAT}, /* no short option */
|
||||
{"print-prompt-compat", 1, 0, ARG_PRINT_PROMPT_COMPAT}, /* no short option */
|
||||
|
||||
{NULL, 0, 0, 0},
|
||||
};
|
||||
|
@ -789,6 +793,26 @@ static int process_arg(int c, char *optarg)
|
|||
estimated_job_size = tmp * mult;
|
||||
}
|
||||
break;
|
||||
case ARG_PROMPT_COMPAT:
|
||||
if (strcmp(optarg, "permsv2") == 0) {
|
||||
prompt_compat_mode = PROMPT_COMPAT_PERMSV1;
|
||||
} else if (strcmp(optarg, "permsv1") == 0) {
|
||||
prompt_compat_mode = PROMPT_COMPAT_PERMSV1;
|
||||
} else if (strcmp(optarg, "default") == 0) {
|
||||
prompt_compat_mode = default_prompt_compat_mode();
|
||||
} else if (strcmp(optarg, "ignore") == 0) {
|
||||
prompt_compat_mode = PROMPT_COMPAT_IGNORE;
|
||||
} else {
|
||||
PERROR("%s: Invalid --prompt-compat option '%s'\n",
|
||||
progname, optarg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case ARG_PRINT_PROMPT_COMPAT:
|
||||
fprintf(stderr, "Prompt compat mode: ");
|
||||
print_prompt_compat_mode(stderr);
|
||||
fprintf(stderr, "\n");
|
||||
break;
|
||||
default:
|
||||
/* 'unrecognized option' error message gets printed by getopt_long() */
|
||||
exit(1);
|
||||
|
@ -1552,6 +1576,9 @@ static bool get_kernel_features(struct aa_features **features)
|
|||
if (kernel_supports_permstable32_v1) {
|
||||
fprintf(stderr, "kernel supports prompt\n");
|
||||
}
|
||||
|
||||
/* set default prompt_compat_mode to the best that is supported */
|
||||
prompt_compat_mode = default_prompt_compat_mode();
|
||||
if (!kernel_supports_diff_encode)
|
||||
/* clear diff_encode because it is not supported */
|
||||
parseopts.control &= ~CONTROL_DFA_DIFF_ENCODE;
|
||||
|
|
|
@ -576,8 +576,7 @@ build:
|
|||
* conditional and for just MAY_EXEC can be processed as
|
||||
* none file perms
|
||||
*
|
||||
* we don't need to build xmatch for buggy permstable32_v1
|
||||
* so don't
|
||||
* we don't need to build xmatch for permstable32, so don't
|
||||
*/
|
||||
prof->xmatch = rules->create_dfablob(&prof->xmatch_size, &prof->xmatch_len, prof->xmatch_perms_table, parseopts, false, kernel_supports_permstable32 && !kernel_supports_permstable32_v1);
|
||||
delete rules;
|
||||
|
@ -780,13 +779,13 @@ int process_profile_regex(Profile *prof)
|
|||
/* under permstable32_v1 we weld file and policydb together, so
|
||||
* don't create the file blob here
|
||||
*/
|
||||
if (prof->dfa.rules->rule_count > 0 && !kernel_supports_permstable32_v1) {
|
||||
if (prof->dfa.rules->rule_count > 0 && prompt_compat_mode != PROMPT_COMPAT_PERMSV1) {
|
||||
int xmatch_len = 0;
|
||||
//fprintf(stderr, "Creating file DFA %d\n", kernel_supports_permstable32);
|
||||
prof->dfa.dfa = prof->dfa.rules->create_dfablob(&prof->dfa.size,
|
||||
&xmatch_len, prof->dfa.perms_table,
|
||||
parseopts, true,
|
||||
kernel_supports_permstable32);
|
||||
prof->uses_prompt_rules && kernel_supports_permstable32);
|
||||
delete prof->dfa.rules;
|
||||
prof->dfa.rules = NULL;
|
||||
if (!prof->dfa.dfa)
|
||||
|
@ -1131,7 +1130,7 @@ int process_profile_policydb(Profile *prof)
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (kernel_supports_permstable32_v1) {
|
||||
if (prompt_compat_mode == PROMPT_COMPAT_PERMSV1) {
|
||||
// MUST have file and policy
|
||||
// This requires file rule processing happen first
|
||||
if (!prof->dfa.rules->rule_count) {
|
||||
|
@ -1160,13 +1159,13 @@ int process_profile_policydb(Profile *prof)
|
|||
} else if (prof->policy.rules->rule_count > 0 &&
|
||||
// yes not needed as covered above, just making sure
|
||||
// this doesn't get messed up in the future
|
||||
!kernel_supports_permstable32_v1) {
|
||||
prompt_compat_mode != PROMPT_COMPAT_PERMSV1) {
|
||||
int xmatch_len = 0;
|
||||
prof->policy.dfa = prof->policy.rules->create_dfablob(&prof->policy.size,
|
||||
&xmatch_len,
|
||||
prof->policy.perms_table,
|
||||
parseopts, false,
|
||||
kernel_supports_permstable32);
|
||||
prof->uses_prompt_rules && kernel_supports_permstable32);
|
||||
delete prof->policy.rules;
|
||||
|
||||
prof->policy.rules = NULL;
|
||||
|
|
Loading…
Add table
Reference in a new issue