103 lines
3.3 KiB
Diff
103 lines
3.3 KiB
Diff
|
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;
|
||
|
}
|
||
|
|