audit/permtab-filter-unsupport.patch

103 lines
3.3 KiB
Diff
Raw Normal View History

diff --git a/lib/libaudit.c b/lib/libaudit.c
index 7a8c6d4b1..de34812f0 100644
--- a/lib/libaudit.c
+++ b/lib/libaudit.c
@@ -100,6 +100,7 @@ static struct libaudit_conf config;
static int audit_failure_parser(const char *val, int line);
static int audit_name_to_uid(const char *name, uid_t *auid);
static int audit_name_to_gid(const char *name, gid_t *gid);
+static char* filter_supported_syscalls(const char* syscalls, int machine) __attr_dealloc_free;
static const struct kw_pair keywords[] =
{
@@ -1524,6 +1525,50 @@ int _audit_parse_syscall(const char *optarg, struct audit_rule_data *rule)
return audit_rule_syscallbyname_data(rule, optarg);
}
+/*
+ * Filters unsupported syscalls from a comma-separated string based
+ * on the given architecture. Returns a new string with supported syscalls
+ * or NULL on error.
+ */
+static char* filter_supported_syscalls(const char* syscalls, int machine)
+{
+ if (syscalls == NULL) {
+ return NULL;
+ }
+
+ // Allocate memory for the filtered syscalls string
+ char* filtered_syscalls = malloc(strlen(syscalls) + 1);
+ if (filtered_syscalls == NULL) {
+ return NULL;
+ }
+ filtered_syscalls[0] = '\0'; // Initialize as empty string
+
+ // Tokenize the syscalls string and filter unsupported syscalls
+ const char* delimiter = ",";
+ char* syscalls_copy = strdup(syscalls);
+ if (syscalls_copy == NULL) {
+ free(filtered_syscalls);
+ return NULL;
+ }
+ char* token = strtok(syscalls_copy, delimiter);
+ while (token != NULL) {
+ if (audit_name_to_syscall(token, machine) != -1) {
+ strcat(filtered_syscalls, token);
+ strcat(filtered_syscalls, delimiter);
+ }
+ token = strtok(NULL, delimiter);
+ }
+ free(syscalls_copy);
+
+ // Remove the trailing delimiter, if present
+ size_t len = strlen(filtered_syscalls);
+ if (len > 0 && filtered_syscalls[len - 1] == ',') {
+ filtered_syscalls[len - 1] = '\0';
+ }
+
+ return filtered_syscalls;
+}
+
static int audit_add_perm_syscalls(int perm, struct audit_rule_data *rule)
{
// We only get here if syscall notation is being used in the rule.
@@ -1536,20 +1581,36 @@ static int audit_add_perm_syscalls(int perm, struct audit_rule_data *rule)
return 0;
}
+ const int machine = audit_elf_to_machine(_audit_elf);
const char *syscalls = audit_perm_to_name(perm);
- int rc = _audit_parse_syscall(syscalls, rule);
+ const char *syscalls_to_use;
+
+ // The permtab table is hardcoded, but some syscalls, like rename
+ // on arm64, are unavailable on certain architectures. To ensure compatibility,
+ // we must avoid creating rules with unsupported syscalls.
+ char* filtered_syscalls = filter_supported_syscalls(syscalls, machine);
+ if (filtered_syscalls == NULL) {
+ // use original syscalls in case we failed to parse - should not happen
+ syscalls_to_use = syscalls;
+ audit_msg(LOG_WARNING, "Filtering syscalls failed; using original syscalls.");
+ } else {
+ syscalls_to_use = filtered_syscalls;
+ }
+
+ int rc = _audit_parse_syscall(syscalls_to_use, rule);
switch (rc)
{
case 0:
_audit_syscalladded = 1;
break;
case -1: // Should never happen
- audit_msg(LOG_ERR, "Syscall name unknown: %s", syscalls);
+ audit_msg(LOG_ERR, "Syscall name unknown: %s", syscalls_to_use);
break;
default: // Error reported - do nothing here
break;
}
+ free(filtered_syscalls);
return rc;
}