/* * Copyright (c) 2010 - 2012 * Canonical Ltd. (All rights reserved) * * 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 * along with this program; if not, contact Novell, Inc. or Canonical, * Ltd. */ #include #include #include #include "parser.h" #include "file_cache.h" /* Policy versioning is determined by a combination of 3 values: * policy_version: version of txt policy * parser_abi_version: version of abi revision of policy generated by parser * kernel_abi_version: version of abi revision for the kernel * * The version info is stored in a single 32 bit version field in the * header portion of each binary policy file. * * policy_version: * a gross revision number indicating what features and semantics are * expected by the text policy. This does not necessarily map directly * to a feature set as a kernel may not have all the supported features * patched/builtin. * * policy_version is not supported by kernels that only support v5 * kernel abi, so it will not be written when creating policy for * those kernels. * * kernel_abi_version: * should be set to the highest version supported by both the parser and * the kernel. * This allows new kernels to detect old userspaces, and new parsers * to support old kernels and policies semantics. * * parser_abi_version: * should be bumped when a compiler error or some other event happens * and policy cache needs to be forced to be recomputed, when the * policy_version or kernel version has not changed. * * parser_abi_version is not supported by kernels that only support * v5 kernel abi so it will not be written when creating policy for those * kernels. * * Default values set to v5 kernel abi before the different versioning * numbers where supported. */ uint32_t policy_version = 2; uint32_t parser_abi_version = 2; uint32_t kernel_abi_version = 5; int force_complain = 0; int perms_create = 0; /* perms contain create flag */ int net_af_max_override = -1; /* use kernel to determine af_max */ int kernel_load = 1; int kernel_supports_setload = 0; /* kernel supports atomic set loads */ int features_supports_network = 0; /* kernel supports network rules */ int features_supports_networkv8 = 0; /* kernel supports 4.17 network rules */ int features_supports_inet = 0; /* kernel supports inet network rules */ int features_supports_unix = 0; /* kernel supports unix socket rules */ int kernel_supports_policydb = 0; /* kernel supports new policydb */ int features_supports_mount = 0; /* kernel supports mount rules */ int features_supports_dbus = 0; /* kernel supports dbus rules */ int kernel_supports_diff_encode = 0; /* kernel supports diff_encode */ int features_supports_signal = 0; /* kernel supports signal rules */ int features_supports_ptrace = 0; /* kernel supports ptrace rules */ int features_supports_stacking = 0; /* kernel supports stacking */ int features_supports_domain_xattr = 0; /* x attachment cond */ int features_supports_userns = 0; /* kernel supports user namespace */ int features_supports_posix_mqueue = 0; /* kernel supports mqueue rules */ int features_supports_sysv_mqueue = 0; /* kernel supports mqueue rules */ int features_supports_io_uring = 0; /* kernel supports io_uring rules */ int features_supports_flag_interruptible = 0; int features_supports_flag_signal = 0; int features_supports_flag_error = 0; int kernel_supports_oob = 0; /* out of band transitions */ int kernel_supports_promptdev = 0; /* prompt via audit perms */ int kernel_supports_permstable32 = 0; /* extended permissions */ int kernel_supports_permstable32_v1 = 0; /* extended permissions */ int prompt_compat_mode = PROMPT_COMPAT_UNKNOWN; int kernel_supports_state32 = 0; /* 32 bit state table entries */ int kernel_supports_flags_table = 0; /* state flags stored in table */ int conf_verbose = 0; int conf_quiet = 0; int names_only = 0; int current_lineno = 1; int option = OPTION_ADD; const char *progname = __FILE__; char *profile_ns = NULL; char *profilename = NULL; char *current_filename = NULL; FILE *ofile = NULL; IncludeCache_t *g_includecache; optflags parseopts = { .control = (optflags_t)(CONTROL_DFA_TREE_NORMAL | CONTROL_DFA_TREE_SIMPLE | CONTROL_DFA_MINIMIZE | CONTROL_DFA_DIFF_ENCODE | CONTROL_RULE_MERGE | /* TODO: remove when we have better auto * selection on when/which explicit denies * to remove */ CONTROL_DFA_FILTER_DENY), .dump = 0, .warn = DEFAULT_WARNINGS, .Werror = 0 }; #ifdef FORCE_READ_IMPLIES_EXEC int read_implies_exec = 1; #else int read_implies_exec = 0; #endif void pwarnf(bool werr, const char *fmt, ...) { va_list arg; char *newfmt; if (conf_quiet || names_only || option == OPTION_REMOVE) return; if (asprintf(&newfmt, _("%s from %s (%s%sline %d): %s"), werr ? _("Warning converted to Error") : _("Warning"), profilename ? profilename : "stdin", current_filename ? current_filename : "", current_filename ? " " : "", current_lineno, fmt) == -1) return; va_start(arg, fmt); vfprintf(stderr, newfmt, arg); va_end(arg); free(newfmt); if (werr) { fflush(stderr); exit(1); } } /* do we want to warn once/profile or just once per compile?? */ void common_warn_once(const char *name, const char *msg, const char **warned_name) { if ((parseopts.warn & WARN_RULE_NOT_ENFORCED) && *warned_name != name) { if (parseopts.Werror & WARN_RULE_NOT_ENFORCED) cerr << "Warning converted to Error"; else cerr << "Warning"; cerr << " from profile " << name << " ("; if (current_filename) cerr << current_filename; else cerr << "stdin"; cerr << "): " << msg << "\n"; *warned_name = name; } 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_DEV && kernel_supports_promptdev) return true; */ else if (mode == PROMPT_COMPAT_FLAG && kernel_supports_permstable32) 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_DEV)) return PROMPT_COMPAT_DEV; if (prompt_compat_mode_supported(PROMPT_COMPAT_FLAG)) return PROMPT_COMPAT_FLAG; 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_FLAG: fprintf(f, "flag"); break; case PROMPT_COMPAT_PERMSV2: fprintf(f, "permsv2"); break; case PROMPT_COMPAT_PERMSV1: fprintf(f, "permsv1"); break; case PROMPT_COMPAT_DEV: fprintf(stderr, "dev"); break; default: fprintf(f, "Unknown prompt compat mode '%d'", prompt_compat_mode); } }