diff --git a/include/linux/audit.h b/include/linux/audit.h index dcd5395b400d8212451b8726bb4acf5708916650..63c3bb98558f6b3e2d07cd9040621273966c1eec 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -209,6 +209,7 @@ #define AUDIT_WATCH 105 #define AUDIT_PERM 106 #define AUDIT_DIR 107 +#define AUDIT_FILETYPE 108 #define AUDIT_ARG0 200 #define AUDIT_ARG1 (AUDIT_ARG0+1) diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 7c3450d063fe9556c6b1fd299ee442a3d48938c3..9435d9392df58231216f49430a44f49aa5a53966 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -478,6 +478,10 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) if (f->val & ~15) goto exit_free; break; + case AUDIT_FILETYPE: + if ((f->val & ~S_IFMT) > S_IFMT) + goto exit_free; + break; case AUDIT_INODE: err = audit_to_inode(&entry->rule, f); if (err) @@ -649,6 +653,10 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, if (f->val & ~15) goto exit_free; break; + case AUDIT_FILETYPE: + if ((f->val & ~S_IFMT) > S_IFMT) + goto exit_free; + break; default: goto exit_free; } diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 091409996577dac43506aadef870ead32e88397c..c10e7aae04d795714fb8cf4ee9326eff4bf6c472 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -280,6 +280,19 @@ static int audit_match_perm(struct audit_context *ctx, int mask) } } +static int audit_match_filetype(struct audit_context *ctx, int which) +{ + unsigned index = which & ~S_IFMT; + mode_t mode = which & S_IFMT; + if (index >= ctx->name_count) + return 0; + if (ctx->names[index].ino == -1) + return 0; + if ((ctx->names[index].mode ^ mode) & S_IFMT) + return 0; + return 1; +} + /* * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *; * ->first_trees points to its beginning, ->trees - to the current end of data. @@ -589,6 +602,9 @@ static int audit_filter_rules(struct task_struct *tsk, case AUDIT_PERM: result = audit_match_perm(ctx, f->val); break; + case AUDIT_FILETYPE: + result = audit_match_filetype(ctx, f->val); + break; } if (!result)