summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-08-31 00:19:06 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-09-07 00:02:05 +0200
commit9cf934e1a057a8dc4f36a1ad8d2822fb116374dd (patch)
tree4f66b07f3e56787d4d44c0ba536259e94914e434 /kernel
parent71cf9b0659c55ad0e695e98190c742ae39bcee23 (diff)
downloadkernel-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.c116
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
*