|
@@ -405,6 +405,12 @@ static int audit_field_valid(struct audit_entry *entry, struct audit_field *f)
|
|
if (f->val > AUDIT_MAX_FIELD_COMPARE)
|
|
if (f->val > AUDIT_MAX_FIELD_COMPARE)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
break;
|
|
break;
|
|
|
|
+ case AUDIT_EXE:
|
|
|
|
+ if (f->op != Audit_equal)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ if (entry->rule.listnr != AUDIT_FILTER_EXIT)
|
|
|
|
+ return -EINVAL;
|
|
|
|
+ break;
|
|
};
|
|
};
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -419,6 +425,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
|
size_t remain = datasz - sizeof(struct audit_rule_data);
|
|
size_t remain = datasz - sizeof(struct audit_rule_data);
|
|
int i;
|
|
int i;
|
|
char *str;
|
|
char *str;
|
|
|
|
+ struct audit_fsnotify_mark *audit_mark;
|
|
|
|
|
|
entry = audit_to_entry_common(data);
|
|
entry = audit_to_entry_common(data);
|
|
if (IS_ERR(entry))
|
|
if (IS_ERR(entry))
|
|
@@ -539,6 +546,24 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
|
|
entry->rule.buflen += f->val;
|
|
entry->rule.buflen += f->val;
|
|
entry->rule.filterkey = str;
|
|
entry->rule.filterkey = str;
|
|
break;
|
|
break;
|
|
|
|
+ case AUDIT_EXE:
|
|
|
|
+ if (entry->rule.exe || f->val > PATH_MAX)
|
|
|
|
+ goto exit_free;
|
|
|
|
+ str = audit_unpack_string(&bufp, &remain, f->val);
|
|
|
|
+ if (IS_ERR(str)) {
|
|
|
|
+ err = PTR_ERR(str);
|
|
|
|
+ goto exit_free;
|
|
|
|
+ }
|
|
|
|
+ entry->rule.buflen += f->val;
|
|
|
|
+
|
|
|
|
+ audit_mark = audit_alloc_mark(&entry->rule, str, f->val);
|
|
|
|
+ if (IS_ERR(audit_mark)) {
|
|
|
|
+ kfree(str);
|
|
|
|
+ err = PTR_ERR(audit_mark);
|
|
|
|
+ goto exit_free;
|
|
|
|
+ }
|
|
|
|
+ entry->rule.exe = audit_mark;
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -551,6 +576,8 @@ exit_nofree:
|
|
exit_free:
|
|
exit_free:
|
|
if (entry->rule.tree)
|
|
if (entry->rule.tree)
|
|
audit_put_tree(entry->rule.tree); /* that's the temporary one */
|
|
audit_put_tree(entry->rule.tree); /* that's the temporary one */
|
|
|
|
+ if (entry->rule.exe)
|
|
|
|
+ audit_remove_mark(entry->rule.exe); /* that's the template one */
|
|
audit_free_rule(entry);
|
|
audit_free_rule(entry);
|
|
return ERR_PTR(err);
|
|
return ERR_PTR(err);
|
|
}
|
|
}
|
|
@@ -615,6 +642,10 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule)
|
|
data->buflen += data->values[i] =
|
|
data->buflen += data->values[i] =
|
|
audit_pack_string(&bufp, krule->filterkey);
|
|
audit_pack_string(&bufp, krule->filterkey);
|
|
break;
|
|
break;
|
|
|
|
+ case AUDIT_EXE:
|
|
|
|
+ data->buflen += data->values[i] =
|
|
|
|
+ audit_pack_string(&bufp, audit_mark_path(krule->exe));
|
|
|
|
+ break;
|
|
case AUDIT_LOGINUID_SET:
|
|
case AUDIT_LOGINUID_SET:
|
|
if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
|
|
if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
|
|
data->fields[i] = AUDIT_LOGINUID;
|
|
data->fields[i] = AUDIT_LOGINUID;
|
|
@@ -678,6 +709,12 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b)
|
|
if (strcmp(a->filterkey, b->filterkey))
|
|
if (strcmp(a->filterkey, b->filterkey))
|
|
return 1;
|
|
return 1;
|
|
break;
|
|
break;
|
|
|
|
+ case AUDIT_EXE:
|
|
|
|
+ /* both paths exist based on above type compare */
|
|
|
|
+ if (strcmp(audit_mark_path(a->exe),
|
|
|
|
+ audit_mark_path(b->exe)))
|
|
|
|
+ return 1;
|
|
|
|
+ break;
|
|
case AUDIT_UID:
|
|
case AUDIT_UID:
|
|
case AUDIT_EUID:
|
|
case AUDIT_EUID:
|
|
case AUDIT_SUID:
|
|
case AUDIT_SUID:
|
|
@@ -799,8 +836,14 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old)
|
|
err = -ENOMEM;
|
|
err = -ENOMEM;
|
|
else
|
|
else
|
|
new->filterkey = fk;
|
|
new->filterkey = fk;
|
|
|
|
+ break;
|
|
|
|
+ case AUDIT_EXE:
|
|
|
|
+ err = audit_dupe_exe(new, old);
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
if (err) {
|
|
if (err) {
|
|
|
|
+ if (new->exe)
|
|
|
|
+ audit_remove_mark(new->exe);
|
|
audit_free_rule(entry);
|
|
audit_free_rule(entry);
|
|
return ERR_PTR(err);
|
|
return ERR_PTR(err);
|
|
}
|
|
}
|
|
@@ -963,6 +1006,9 @@ int audit_del_rule(struct audit_entry *entry)
|
|
if (e->rule.tree)
|
|
if (e->rule.tree)
|
|
audit_remove_tree_rule(&e->rule);
|
|
audit_remove_tree_rule(&e->rule);
|
|
|
|
|
|
|
|
+ if (e->rule.exe)
|
|
|
|
+ audit_remove_mark_rule(&e->rule);
|
|
|
|
+
|
|
#ifdef CONFIG_AUDITSYSCALL
|
|
#ifdef CONFIG_AUDITSYSCALL
|
|
if (!dont_count)
|
|
if (!dont_count)
|
|
audit_n_rules--;
|
|
audit_n_rules--;
|
|
@@ -1067,8 +1113,11 @@ int audit_rule_change(int type, __u32 portid, int seq, void *data,
|
|
WARN_ON(1);
|
|
WARN_ON(1);
|
|
}
|
|
}
|
|
|
|
|
|
- if (err || type == AUDIT_DEL_RULE)
|
|
|
|
|
|
+ if (err || type == AUDIT_DEL_RULE) {
|
|
|
|
+ if (entry->rule.exe)
|
|
|
|
+ audit_remove_mark(entry->rule.exe);
|
|
audit_free_rule(entry);
|
|
audit_free_rule(entry);
|
|
|
|
+ }
|
|
|
|
|
|
return err;
|
|
return err;
|
|
}
|
|
}
|
|
@@ -1360,6 +1409,8 @@ static int update_lsm_rule(struct audit_krule *r)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
nentry = audit_dupe_rule(r);
|
|
nentry = audit_dupe_rule(r);
|
|
|
|
+ if (entry->rule.exe)
|
|
|
|
+ audit_remove_mark(entry->rule.exe);
|
|
if (IS_ERR(nentry)) {
|
|
if (IS_ERR(nentry)) {
|
|
/* save the first error encountered for the
|
|
/* save the first error encountered for the
|
|
* return value */
|
|
* return value */
|