diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-08-31 00:19:06 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-09-07 00:02:05 +0200 |
commit | 9cf934e1a057a8dc4f36a1ad8d2822fb116374dd (patch) | |
tree | 4f66b07f3e56787d4d44c0ba536259e94914e434 /kernel | |
parent | 71cf9b0659c55ad0e695e98190c742ae39bcee23 (diff) | |
download | kernel-crypto-9cf934e1a057a8dc4f36a1ad8d2822fb116374dd.tar.gz kernel-crypto-9cf934e1a057a8dc4f36a1ad8d2822fb116374dd.tar.xz kernel-crypto-9cf934e1a057a8dc4f36a1ad8d2822fb116374dd.zip |
Implement AUDIT_CRYPTO_KEY_VALUEncr-audit
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/auditsc.c | 116 |
1 files changed, 102 insertions, 14 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index fcd6d2e7ab9..30853986ab9 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -81,6 +81,9 @@ /* no execve audit message should be longer than this (userspace limits) */ #define MAX_EXECVE_AUDIT_LEN 7500 +/* Number of public key values that can be audited */ +#define AUDIT_MAX_CRYPTO_KEY_VALUES 4 + /* number of audit rules */ int audit_n_rules; @@ -158,9 +161,14 @@ struct audit_aux_data_capset { struct audit_cap_data cap; }; -struct audit_crypto_op { +#define AUDIT_CRYPTO_OP_KEY_VALUE -1 +struct audit_crypto_header { struct list_head list; - int op; + int op; /* AUDIT_CRYPTO_OP_KEY_VALUE for key values */ +}; + +struct audit_crypto_op { + struct audit_crypto_header hdr; int context; int session; const char *operation; @@ -173,6 +181,12 @@ struct audit_crypto_op { size_t key2_id_size; }; +struct audit_crypto_values { + struct audit_crypto_header hdr; + size_t num_values; + struct audit_crypto_value values[AUDIT_MAX_CRYPTO_KEY_VALUES]; +}; + struct audit_tree_refs { struct audit_tree_refs *next; struct audit_chunk *c[31]; @@ -650,11 +664,13 @@ static int audit_filter_rules(struct task_struct *tsk, result = audit_match_filetype(ctx, f->val); break; case AUDIT_CRYPTO_OP: { - struct audit_crypto_op *ax; + struct audit_crypto_header *ax; if (!ctx) break; list_for_each_entry(ax, &ctx->crypto, list) { + if (ax->op == AUDIT_CRYPTO_OP_KEY_VALUE) + continue; result = audit_comparator(ax->op, f->op, f->val); if (result) @@ -854,10 +870,23 @@ static inline void audit_free_names(struct audit_context *context) context->pwd.mnt = NULL; } +static void audit_free_crypto_op(struct audit_crypto_header *crypto) +{ + if (crypto->op == AUDIT_CRYPTO_OP_KEY_VALUE) { + struct audit_crypto_values *val; + size_t i; + + val = (struct audit_crypto_values *)crypto; + for (i = 0; i < val->num_values; i++) + kfree(val->values[i].value); + } + kfree(crypto); +} + static inline void audit_free_aux(struct audit_context *context) { struct audit_aux_data *aux; - struct audit_crypto_op *crypto, *tmp; + struct audit_crypto_header *crypto, *tmp; while ((aux = context->aux)) { context->aux = aux->next; @@ -869,7 +898,7 @@ static inline void audit_free_aux(struct audit_context *context) } list_for_each_entry_safe(crypto, tmp, &context->crypto, list) { list_del(&crypto->list); - kfree(crypto); + audit_free_crypto_op(crypto); } } @@ -1347,7 +1376,7 @@ static void show_special(struct audit_context *context, int *call_panic) } static void log_crypto_op(struct audit_context *context, - struct audit_crypto_op *crypto) + const struct audit_crypto_header *header) { static const char *const ops[] = { [AUDIT_CRYPTO_OP_CONTEXT_NEW] = "context_new", @@ -1365,15 +1394,17 @@ static void log_crypto_op(struct audit_context *context, [AUDIT_CRYPTO_OP_KEY_GET_INFO] = "key_get_info", }; + const struct audit_crypto_op *crypto; struct audit_buffer *ab; + crypto = (struct audit_crypto_op *)header; ab = audit_log_start(context, GFP_KERNEL, AUDIT_CRYPTO_USERSPACE_OP); if (!ab) return; - if (crypto->op < ARRAY_SIZE(ops) && ops[crypto->op] != NULL) - audit_log_format(ab, "crypto_op=%s", ops[crypto->op]); + if (header->op < ARRAY_SIZE(ops) && ops[header->op] != NULL) + audit_log_format(ab, "crypto_op=%s", ops[header->op]); else - audit_log_format(ab, "crypto_op=%d", crypto->op); + audit_log_format(ab, "crypto_op=%d", header->op); audit_log_format(ab, " ctx=%d", crypto->context); if (crypto->session != -1) audit_log_format(ab, " session=%d", crypto->session); @@ -1404,13 +1435,31 @@ static void log_crypto_op(struct audit_context *context, audit_log_end(ab); } +static void log_crypto_values(struct audit_context *context, + const struct audit_crypto_header *header) +{ + struct audit_buffer *ab; + const struct audit_crypto_values *crypto; + const struct audit_crypto_value *v; + + crypto = (struct audit_crypto_values *)header; + ab = audit_log_start(context, GFP_KERNEL, AUDIT_CRYPTO_KEY_VALUE); + if (!ab) + return; + for (v = crypto->values; v < crypto->values + crypto->num_values; v++) { + audit_log_format(ab, " key_value_%c=", v->name); + audit_log_n_hex(ab, v->value, v->value_size); + } + audit_log_end(ab); +} + static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) { const struct cred *cred; int i, call_panic = 0; struct audit_buffer *ab; struct audit_aux_data *aux; - struct audit_crypto_op *crypto; + struct audit_crypto_header *crypto; const char *tty; /* tsk == current */ @@ -1537,8 +1586,12 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts call_panic = 1; } - list_for_each_entry(crypto, &context->crypto, list) - log_crypto_op(context, crypto); + list_for_each_entry(crypto, &context->crypto, list) { + if (crypto->op != AUDIT_CRYPTO_OP_KEY_VALUE) + log_crypto_op(context, crypto); + else + log_crypto_values(context, crypto); + } if (context->target_pid && audit_log_pid_context(context, context->target_pid, @@ -2609,7 +2662,7 @@ int __audit_log_crypto_op(int op, int context, int session, if (!ax) return -ENOMEM; - ax->op = op; + ax->hdr.op = op; ax->context = context; ax->session = session; ax->operation = operation; @@ -2626,12 +2679,47 @@ int __audit_log_crypto_op(int op, int context, int session, memcpy(ax->key2_id, key2_id, ax->key2_id_size); } else ax->key2_id_size = 0; - list_add_tail(&ax->list, &ctx->crypto); + list_add_tail(&ax->hdr.list, &ctx->crypto); return 0; } EXPORT_SYMBOL_GPL(__audit_log_crypto_op); /** + * __audit_log_crypto_op - store information about values of crypto keys + * @values: individual byte arrays describing the key. The "value" members + * must be allocated using kmalloc(), this function will take care of freeing + * them. + * @num_values: number of elements in @values + */ +void __audit_log_crypto_values(const struct audit_crypto_value *values, + size_t num_values) +{ + struct audit_crypto_values *ax; + struct audit_context *ctx = current->audit_context; + size_t i; + + ax = kmalloc(sizeof(*ax), GFP_KERNEL); + if (!ax) + goto free_values; + + ax->hdr.op = AUDIT_CRYPTO_OP_KEY_VALUE; + BUG_ON(num_values > ARRAY_SIZE(ax->values)); + ax->num_values = num_values; + for (i = 0; i < num_values; i++) { + ax->values[i].name = values[i].name; + ax->values[i].value = values[i].value; + ax->values[i].value_size = values[i].value_size; + } + list_add_tail(&ax->hdr.list, &ctx->crypto); + return; + +free_values: + for (i = 0; i < num_values; i++) + kfree(values[i].value); +} +EXPORT_SYMBOL_GPL(__audit_log_crypto_values); + +/** * audit_core_dumps - record information about processes that end abnormally * @signr: signal value * |