summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-08-02 18:11:53 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-09-07 00:02:04 +0200
commit71cf9b0659c55ad0e695e98190c742ae39bcee23 (patch)
tree25032bec598a4c1dfba8312fe44f103d7533d1ac
parentf4ab2ffed62bc7b4a536ba111e5a4aa38157ea29 (diff)
downloadkernel-crypto-71cf9b0659c55ad0e695e98190c742ae39bcee23.tar.gz
kernel-crypto-71cf9b0659c55ad0e695e98190c742ae39bcee23.tar.xz
kernel-crypto-71cf9b0659c55ad0e695e98190c742ae39bcee23.zip
Implement AUDIT_CRYPTO_USERSPACE_OP
-rw-r--r--crypto/userspace/cryptodev_main.c11
-rw-r--r--crypto/userspace/ncr-int.h2
-rw-r--r--crypto/userspace/ncr-key-wrap.c46
-rw-r--r--crypto/userspace/ncr-key.c41
-rw-r--r--crypto/userspace/ncr-sessions.c67
-rw-r--r--include/linux/audit.h35
-rw-r--r--kernel/auditfilter.c2
-rw-r--r--kernel/auditsc.c146
8 files changed, 346 insertions, 4 deletions
diff --git a/crypto/userspace/cryptodev_main.c b/crypto/userspace/cryptodev_main.c
index 7afe74c0b18..89cd15b6287 100644
--- a/crypto/userspace/cryptodev_main.c
+++ b/crypto/userspace/cryptodev_main.c
@@ -31,6 +31,7 @@
*
*/
+#include <linux/audit.h>
#include <linux/crypto.h>
#include <linux/mm.h>
#include <linux/highmem.h>
@@ -103,12 +104,20 @@ static int
cryptodev_open(struct inode *inode, struct file *filp)
{
struct ncr_lists *ncr;
+ int ret;
ncr = ncr_init_lists();
if (ncr == NULL) {
return -ENOMEM;
}
+ ret = audit_log_crypto_op(AUDIT_CRYPTO_OP_CONTEXT_NEW, ncr->id, -1,
+ NULL, NULL, -1, NULL, 0, -1, NULL, 0);
+ if (ret < 0) {
+ ncr_deinit_lists(ncr);
+ return ret;
+ }
+
filp->private_data = ncr;
return 0;
}
@@ -119,6 +128,8 @@ cryptodev_release(struct inode *inode, struct file *filp)
struct ncr_lists *ncr = filp->private_data;
if (ncr) {
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_CONTEXT_DEL, ncr->id, -1,
+ NULL, NULL, -1, NULL, 0, -1, NULL, 0);
ncr_deinit_lists(ncr);
filp->private_data = NULL;
}
diff --git a/crypto/userspace/ncr-int.h b/crypto/userspace/ncr-int.h
index 3302edf4dc6..21e782d4b5a 100644
--- a/crypto/userspace/ncr-int.h
+++ b/crypto/userspace/ncr-int.h
@@ -101,6 +101,7 @@ struct key_item_st {
uid_t uid;
pid_t pid;
+ int context_id; /* Only for auditing */
ncr_key_t desc;
};
@@ -208,6 +209,7 @@ int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_it
const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo);
const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla);
+const char *ncr_algorithm_name(const struct algo_properties_st *algo);
int _ncr_key_get_sec_level(struct key_item_st* item);
const struct algo_properties_st *_ncr_oid_to_properties(oid_st* oid);
const oid_st* _ncr_properties_to_oid(const struct algo_properties_st * prop, int key_size);
diff --git a/crypto/userspace/ncr-key-wrap.c b/crypto/userspace/ncr-key-wrap.c
index c30fa243941..ce061312dc0 100644
--- a/crypto/userspace/ncr-key-wrap.c
+++ b/crypto/userspace/ncr-key-wrap.c
@@ -22,6 +22,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <linux/audit.h>
#include <linux/ioctl.h>
#include <linux/mm.h>
#include <linux/ncr.h>
@@ -532,6 +533,26 @@ int kek_level, wkey_level;
return 0;
}
+static const char *ncr_wrap_name(struct nlattr *tb[])
+{
+ static const char *const known_algorithms[] = {
+ NCR_WALG_AES_RFC3394, NCR_WALG_AES_RFC5649
+ };
+
+ size_t i;
+ const struct nlattr *nla;
+
+ /* Only allow known algorithms to prevent log injection. Return the
+ static string, not nla_data(), which will go away before the ioctl()
+ handler returns. */
+ nla = tb[NCR_ATTR_WRAPPING_ALGORITHM];
+ for (i = 0; i < ARRAY_SIZE(known_algorithms); i++) {
+ if (nla_strcmp(nla, known_algorithms[i]) == 0)
+ return known_algorithms[i];
+ }
+ return "unknown";
+}
+
int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap,
struct nlattr *tb[])
{
@@ -633,6 +654,14 @@ int ret;
ret = data_size;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_WRAP, lst->id, -1, NULL,
+ ncr_wrap_name(tb), wrap->wrapping_key,
+ key != NULL ? key->key_id : NULL,
+ key != NULL ? key->key_id_size : 0,
+ wrap->source_key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
if (wkey != NULL) _ncr_key_item_put(wkey);
if (key != NULL) _ncr_key_item_put(key);
kfree(data);
@@ -710,6 +739,13 @@ int ret;
}
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_UNWRAP, lst->id, -1, NULL,
+ ncr_wrap_name(tb), wrap->wrapping_key,
+ key != NULL ? key->key_id : NULL,
+ key != NULL ? key->key_id_size : 0, wrap->dest_key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
if (wkey != NULL) _ncr_key_item_put(wkey);
if (key != NULL) _ncr_key_item_put(key);
if (data != NULL) kfree(data);
@@ -773,6 +809,11 @@ int ret;
ret = data_size;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_WRAP, lst->id, -1, NULL, NULL,
+ -1, NULL, 0, wrap->key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
if (wkey != NULL) _ncr_key_item_put(wkey);
if (data != NULL) kfree(data);
if (sdata != NULL) kfree(sdata);
@@ -839,6 +880,11 @@ int ret;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_UNWRAP, lst->id, -1, NULL, NULL,
+ -1, NULL, 0, wrap->key,
+ wkey != NULL ? wkey->key_id : NULL,
+ wkey != NULL ? wkey->key_id_size : 0);
+
if (wkey != NULL) _ncr_key_item_put(wkey);
if (data != NULL) kfree(data);
if (sdata != NULL) kfree(sdata);
diff --git a/crypto/userspace/ncr-key.c b/crypto/userspace/ncr-key.c
index b9aee067d3a..e614f687075 100644
--- a/crypto/userspace/ncr-key.c
+++ b/crypto/userspace/ncr-key.c
@@ -22,6 +22,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <linux/audit.h>
#include <linux/ioctl.h>
#include <linux/mm.h>
#include <linux/ncr.h>
@@ -175,6 +176,7 @@ int ncr_key_init(struct ncr_lists *lst)
atomic_set(&key->writer, 0);
key->uid = current_euid();
key->pid = task_pid_nr(current);
+ key->context_id = lst->id;
mutex_lock(&lst->key_idr_mutex);
/* idr_pre_get() should preallocate enough, and, due to key_idr_mutex,
@@ -280,6 +282,10 @@ int ret;
}
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_EXPORT, lst->id, -1, NULL,
+ ncr_algorithm_name(item->algorithm), item->desc,
+ item->key_id, item->key_id_size, -1, NULL, 0);
+
kfree(tmp);
_ncr_key_item_put(item);
return ret;
@@ -393,6 +399,10 @@ size_t tmp_size;
ret = 0;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_IMPORT, lst->id, -1, NULL,
+ ncr_algorithm_name(item->algorithm), item->desc,
+ item->key_id, item->key_id_size, -1, NULL, 0);
+
_ncr_key_item_put(item);
kfree(tmp);
@@ -401,6 +411,11 @@ fail:
void ncr_key_clear(struct key_item_st* item)
{
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_ZEROIZE, item->context_id, -1,
+ NULL, ncr_algorithm_name(item->algorithm),
+ item->desc, item->key_id, item->key_id_size, -1,
+ NULL, 0);
+
/* clears any previously allocated parameters */
if (item->type == NCR_KEY_TYPE_PRIVATE ||
item->type == NCR_KEY_TYPE_PUBLIC) {
@@ -422,7 +437,7 @@ int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen,
{
const struct nlattr *nla;
struct key_item_st* item = NULL;
-const struct algo_properties_st *algo;
+const struct algo_properties_st *algo = NULL;
int ret;
size_t size;
@@ -482,6 +497,10 @@ size_t size;
ret = 0;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_GEN, lst->id, -1, NULL,
+ ncr_algorithm_name(algo), item->desc, item->key_id,
+ item->key_id_size, -1, NULL, 0);
+
if (ret < 0) item->type = NCR_KEY_TYPE_INVALID;
_ncr_key_item_put(item);
return ret;
@@ -649,6 +668,10 @@ int ret;
}
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_GET_INFO, lst->id, -1, NULL,
+ ncr_algorithm_name(item->algorithm), item->desc,
+ item->key_id, item->key_id_size, -1, NULL, 0);
+
_ncr_key_item_put( item);
return ret;
@@ -714,6 +737,16 @@ int ret;
ret = 0;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_GEN, lst->id, -1, NULL,
+ ncr_algorithm_name(private != NULL
+ ? private->algorithm : NULL),
+ private != NULL ? private->desc : -1,
+ private != NULL ? private->key_id : NULL,
+ private != NULL ? private->key_id_size : 0,
+ public != NULL ? public->desc : -1,
+ public != NULL ? public->key_id : NULL,
+ public != NULL ? public->key_id_size : 0);
+
if (public) {
if (ret < 0) public->type = NCR_KEY_TYPE_INVALID;
_ncr_key_item_put(public);
@@ -776,6 +809,12 @@ struct key_item_st* newkey = NULL;
}
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_KEY_DERIVE, lst->id, -1, NULL,
+ ncr_algorithm_name(key->algorithm), key->desc,
+ key->key_id, key->key_id_size, data->input_key,
+ newkey != NULL ? newkey->key_id : NULL,
+ newkey != NULL ? newkey->key_id_size : 0);
+
_ncr_key_item_put(key);
if (newkey)
_ncr_key_item_put(newkey);
diff --git a/crypto/userspace/ncr-sessions.c b/crypto/userspace/ncr-sessions.c
index d22a38423fa..b344d087b47 100644
--- a/crypto/userspace/ncr-sessions.c
+++ b/crypto/userspace/ncr-sessions.c
@@ -23,6 +23,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+#include <linux/audit.h>
#include <linux/crypto.h>
#include <linux/mutex.h>
#include <linux/ncr.h>
@@ -453,6 +454,32 @@ const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla
return NULL;
}
+static const char *ncr_op_name(ncr_crypto_op_t op)
+{
+ static const char *const names[] = {
+ [NCR_OP_ENCRYPT] = "encrypt",
+ [NCR_OP_DECRYPT] = "decrypt",
+ [NCR_OP_SIGN] = "sign",
+ [NCR_OP_VERIFY] = "verify"
+ };
+
+ const char *res;
+
+ res = NULL;
+ if (op < ARRAY_SIZE(names))
+ res = names[op];
+ if (res == NULL)
+ res = "unknown";
+ return res;
+}
+
+const char *ncr_algorithm_name(const struct algo_properties_st *algo)
+{
+ if (algo != NULL && algo->kstr != NULL)
+ return algo->kstr;
+ return "unknown";
+}
+
static int key_item_get_nla_read(struct key_item_st **st,
struct ncr_lists *lists,
const struct nlattr *nla)
@@ -754,12 +781,30 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists,
goto fail;
}
+ ret = audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_INIT, lists->id,
+ ns->desc, ncr_op_name(ns->op),
+ ncr_algorithm_name(ns->algorithm),
+ ns->key != NULL ? ns->key->desc : -1,
+ ns->key != NULL ? ns->key->key_id : NULL,
+ ns->key != NULL ? ns->key->key_id_size : 0,
+ -1, NULL, 0);
+ if (ret != 0)
+ goto fail_noaudit;
+
if (old_session != NULL)
_ncr_sessions_item_put(old_session);
return ns;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_INIT, lists->id, ns->desc,
+ ncr_op_name(ns->op),
+ ncr_algorithm_name(ns->algorithm),
+ ns->key != NULL ? ns->key->desc : -1,
+ ns->key != NULL ? ns->key->key_id : NULL,
+ ns->key != NULL ? ns->key->key_id_size : 0, -1,
+ NULL, 0);
+fail_noaudit:
if (old_session != NULL)
_ncr_sessions_item_put(old_session);
_ncr_sessions_item_put(ns);
@@ -976,7 +1021,8 @@ static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[],
/* Called when userspace buffers are used.
The caller is responsible for locking of the session. */
-static int _ncr_session_update(struct session_item_st *sess,
+static int _ncr_session_update(struct ncr_lists *lists,
+ struct session_item_st *sess,
struct nlattr *tb[], int compat)
{
const struct nlattr *nla;
@@ -1104,6 +1150,11 @@ static int _ncr_session_update(struct session_item_st *sess,
ret = 0;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_OP, lists->id, sess->desc,
+ ncr_op_name(sess->op),
+ ncr_algorithm_name(sess->algorithm), -1, NULL, 0,
+ -1, NULL, 0);
+
if (sess->available_pages) {
release_user_pages(sess->pages, sess->available_pages);
sess->available_pages = 0;
@@ -1120,7 +1171,7 @@ static int try_session_update(struct ncr_lists *lists,
if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL)
return _ncr_session_update_key(lists, sess, tb);
else if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL)
- return _ncr_session_update(sess, tb, compat);
+ return _ncr_session_update(lists, sess, tb, compat);
else
return 0;
}
@@ -1283,6 +1334,11 @@ static int _ncr_session_final(struct ncr_lists *lists,
fail:
kfree(buffer);
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_FINAL, lists->id,
+ sess->desc, ncr_op_name(sess->op),
+ ncr_algorithm_name(sess->algorithm), -1, NULL, 0,
+ -1, NULL, 0);
+
return ret;
}
@@ -1344,6 +1400,11 @@ static int _ncr_session_update_key(struct ncr_lists *lists,
ret = 0;
fail:
+ audit_log_crypto_op(AUDIT_CRYPTO_OP_SESSION_OP, lists->id, sess->desc,
+ ncr_op_name(sess->op),
+ ncr_algorithm_name(sess->algorithm), key->desc,
+ key->key_id, key->key_id_size, -1, NULL, 0);
+
_ncr_key_item_put(key);
return ret;
@@ -1371,7 +1432,7 @@ int ncr_session_update(struct ncr_lists *lists,
goto end;
}
if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL)
- ret = _ncr_session_update(sess, tb, compat);
+ ret = _ncr_session_update(lists, sess, tb, compat);
else if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL)
ret = _ncr_session_update_key(lists, sess, tb);
else
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 35fa4e9c34a..54cb007e340 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -123,6 +123,7 @@
#define AUDIT_MAC_UNLBL_STCDEL 1417 /* NetLabel: del a static label */
#define AUDIT_CRYPTO_STORAGE_KEY 1600 /* Key storage key configured */
+#define AUDIT_CRYPTO_USERSPACE_OP 1601 /* User-space crypto operation */
#define AUDIT_FIRST_KERN_ANOM_MSG 1700
#define AUDIT_LAST_KERN_ANOM_MSG 1799
@@ -209,6 +210,7 @@
#define AUDIT_OBJ_TYPE 21
#define AUDIT_OBJ_LEV_LOW 22
#define AUDIT_OBJ_LEV_HIGH 23
+#define AUDIT_CRYPTO_OP 24
/* These are ONLY useful when checking
* at syscall exit time (AUDIT_AT_EXIT). */
@@ -316,6 +318,20 @@ enum {
#define AUDIT_PERM_READ 4
#define AUDIT_PERM_ATTR 8
+#define AUDIT_CRYPTO_OP_CONTEXT_NEW 1
+#define AUDIT_CRYPTO_OP_CONTEXT_DEL 2
+#define AUDIT_CRYPTO_OP_SESSION_INIT 3
+#define AUDIT_CRYPTO_OP_SESSION_OP 4
+#define AUDIT_CRYPTO_OP_SESSION_FINAL 5
+#define AUDIT_CRYPTO_OP_KEY_IMPORT 6
+#define AUDIT_CRYPTO_OP_KEY_EXPORT 7
+#define AUDIT_CRYPTO_OP_KEY_WRAP 8
+#define AUDIT_CRYPTO_OP_KEY_UNWRAP 9
+#define AUDIT_CRYPTO_OP_KEY_GEN 10
+#define AUDIT_CRYPTO_OP_KEY_DERIVE 11
+#define AUDIT_CRYPTO_OP_KEY_ZEROIZE 12
+#define AUDIT_CRYPTO_OP_KEY_GET_INFO 13
+
struct audit_status {
__u32 mask; /* Bit mask for valid entries */
__u32 enabled; /* 1 = enabled, 0 = disabled */
@@ -481,6 +497,10 @@ extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
const struct cred *new,
const struct cred *old);
extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old);
+extern int __audit_log_crypto_op(int op, int context, int session,
+ const char *operation, const char *algorithm,
+ int key1, void *key1_id, size_t key1_id_size,
+ int key2, void *key2_id, size_t key2_id_size);
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
@@ -534,6 +554,20 @@ static inline void audit_log_capset(pid_t pid, const struct cred *new,
__audit_log_capset(pid, new, old);
}
+static inline int audit_log_crypto_op(int op, int context, int session,
+ const char *operation,
+ const char *algorithm, int key1,
+ void *key1_id, size_t key1_id_size,
+ int key2, void *key2_id,
+ size_t key2_id_size)
+{
+ if (likely(audit_dummy_context()))
+ return 0;
+ return __audit_log_crypto_op(op, context, session, operation, algorithm,
+ key1, key1_id, key1_id_size, key2, key2_id,
+ key2_id_size);
+}
+
extern int audit_n_rules;
extern int audit_signals;
#else
@@ -567,6 +601,7 @@ extern int audit_signals;
#define audit_mq_getsetattr(d,s) ((void)0)
#define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; })
#define audit_log_capset(pid, ncr, ocr) ((void)0)
+#define audit_log_crypto_op(op, ctx, sess, k1, id1, size1, k2, id2, size2) (0)
#define audit_ptrace(t) ((void)0)
#define audit_n_rules 0
#define audit_signals 0
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index a70604047f3..a25a587dc87 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -363,6 +363,7 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule)
case AUDIT_DEVMINOR:
case AUDIT_EXIT:
case AUDIT_SUCCESS:
+ case AUDIT_CRYPTO_OP:
/* bit ops are only useful on syscall args */
if (f->op == Audit_bitmask || f->op == Audit_bittest)
goto exit_free;
@@ -457,6 +458,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data,
case AUDIT_ARG1:
case AUDIT_ARG2:
case AUDIT_ARG3:
+ case AUDIT_CRYPTO_OP:
break;
case AUDIT_ARCH:
entry->rule.arch_f = f;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index fc0f928167e..fcd6d2e7ab9 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -50,6 +50,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/mount.h>
+#include <linux/ncr.h>
#include <linux/socket.h>
#include <linux/mqueue.h>
#include <linux/audit.h>
@@ -157,6 +158,21 @@ struct audit_aux_data_capset {
struct audit_cap_data cap;
};
+struct audit_crypto_op {
+ struct list_head list;
+ int op;
+ int context;
+ int session;
+ const char *operation;
+ const char *algorithm;
+ int key1;
+ unsigned char key1_id[MAX_KEY_ID_SIZE];
+ size_t key1_id_size;
+ int key2;
+ unsigned char key2_id[MAX_KEY_ID_SIZE];
+ size_t key2_id_size;
+};
+
struct audit_tree_refs {
struct audit_tree_refs *next;
struct audit_chunk *c[31];
@@ -181,6 +197,7 @@ struct audit_context {
struct audit_context *previous; /* For nested syscalls */
struct audit_aux_data *aux;
struct audit_aux_data *aux_pids;
+ struct list_head crypto;
struct sockaddr_storage *sockaddr;
size_t sockaddr_len;
/* Save things to print about task_struct */
@@ -632,6 +649,19 @@ static int audit_filter_rules(struct task_struct *tsk,
case AUDIT_FILETYPE:
result = audit_match_filetype(ctx, f->val);
break;
+ case AUDIT_CRYPTO_OP: {
+ struct audit_crypto_op *ax;
+
+ if (!ctx)
+ break;
+ list_for_each_entry(ax, &ctx->crypto, list) {
+ result = audit_comparator(ax->op, f->op,
+ f->val);
+ if (result)
+ break;
+ }
+ break;
+ }
}
if (!result) {
@@ -827,6 +857,7 @@ static inline void audit_free_names(struct audit_context *context)
static inline void audit_free_aux(struct audit_context *context)
{
struct audit_aux_data *aux;
+ struct audit_crypto_op *crypto, *tmp;
while ((aux = context->aux)) {
context->aux = aux->next;
@@ -836,6 +867,10 @@ static inline void audit_free_aux(struct audit_context *context)
context->aux_pids = aux->next;
kfree(aux);
}
+ list_for_each_entry_safe(crypto, tmp, &context->crypto, list) {
+ list_del(&crypto->list);
+ kfree(crypto);
+ }
}
static inline void audit_zero_context(struct audit_context *context,
@@ -853,6 +888,7 @@ static inline struct audit_context *audit_alloc_context(enum audit_state state)
if (!(context = kmalloc(sizeof(*context), GFP_KERNEL)))
return NULL;
audit_zero_context(context, state);
+ INIT_LIST_HEAD(&context->crypto);
INIT_LIST_HEAD(&context->killed_trees);
return context;
}
@@ -1310,12 +1346,71 @@ static void show_special(struct audit_context *context, int *call_panic)
audit_log_end(ab);
}
+static void log_crypto_op(struct audit_context *context,
+ struct audit_crypto_op *crypto)
+{
+ static const char *const ops[] = {
+ [AUDIT_CRYPTO_OP_CONTEXT_NEW] = "context_new",
+ [AUDIT_CRYPTO_OP_CONTEXT_DEL] = "context_del",
+ [AUDIT_CRYPTO_OP_SESSION_INIT] = "session_init",
+ [AUDIT_CRYPTO_OP_SESSION_OP] = "session_op",
+ [AUDIT_CRYPTO_OP_SESSION_FINAL] = "session_final",
+ [AUDIT_CRYPTO_OP_KEY_IMPORT] = "key_import",
+ [AUDIT_CRYPTO_OP_KEY_EXPORT] = "key_export",
+ [AUDIT_CRYPTO_OP_KEY_WRAP] = "key_wrap",
+ [AUDIT_CRYPTO_OP_KEY_UNWRAP] = "key_unwrap",
+ [AUDIT_CRYPTO_OP_KEY_GEN] = "key_gen",
+ [AUDIT_CRYPTO_OP_KEY_DERIVE] = "key_derive",
+ [AUDIT_CRYPTO_OP_KEY_ZEROIZE] = "key_zeroize",
+ [AUDIT_CRYPTO_OP_KEY_GET_INFO] = "key_get_info",
+ };
+
+ struct audit_buffer *ab;
+
+ 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]);
+ else
+ audit_log_format(ab, "crypto_op=%d", crypto->op);
+ audit_log_format(ab, " ctx=%d", crypto->context);
+ if (crypto->session != -1)
+ audit_log_format(ab, " session=%d", crypto->session);
+ if (crypto->operation != NULL) {
+ audit_log_format(ab, " operation=");
+ audit_log_string(ab, crypto->operation);
+ }
+ if (crypto->algorithm != NULL) {
+ audit_log_format(ab, " algo=");
+ audit_log_string(ab, crypto->algorithm);
+ }
+ if (crypto->key1 != -1) {
+ audit_log_format(ab, " key1=%d", crypto->key1);
+ if (crypto->key1_id_size > 0) {
+ audit_log_format(ab, " key1_id=");
+ audit_log_n_untrustedstring(ab, crypto->key1_id,
+ crypto->key1_id_size);
+ }
+ }
+ if (crypto->key2 != -1) {
+ audit_log_format(ab, " key2=%d", crypto->key2);
+ if (crypto->key2_id_size > 0) {
+ audit_log_format(ab, " key2_id=");
+ audit_log_n_untrustedstring(ab, crypto->key2_id,
+ crypto->key2_id_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;
const char *tty;
/* tsk == current */
@@ -1442,6 +1537,9 @@ 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);
+
if (context->target_pid &&
audit_log_pid_context(context, context->target_pid,
context->target_auid, context->target_uid,
@@ -2486,6 +2584,54 @@ void __audit_log_capset(pid_t pid,
}
/**
+ * __audit_log_crypto_op - store information about an user-space crypto op
+ * @op: AUDIT_CRYPTO_OP_*
+ * @context: user-space context ID
+ * @session: session ID within @context, or -1
+ * @operation: more detailed operation description, or NULL
+ * @algorithm: algorithm (crypto API transform) name, or NULL
+ * @key1: ID of key 1 within @context, or -1
+ * @key1_id: user-space ID of key 1 set from user-space if @key1 != -1
+ * @key1_id_size: Size of @key1_id
+ * @key2: ID of key 2 within @context, or -1
+ * @key2_id: user-space ID of key 2 set from user-space if @key2 != -1
+ * @key2_id_size: Size of @key2_id
+ */
+int __audit_log_crypto_op(int op, int context, int session,
+ const char *operation, const char *algorithm,
+ int key1, void *key1_id, size_t key1_id_size,
+ int key2, void *key2_id, size_t key2_id_size)
+{
+ struct audit_crypto_op *ax;
+ struct audit_context *ctx = current->audit_context;
+
+ ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->op = op;
+ ax->context = context;
+ ax->session = session;
+ ax->operation = operation;
+ ax->algorithm = algorithm;
+ ax->key1 = key1;
+ if (key1 != -1) {
+ ax->key1_id_size = min(key1_id_size, sizeof(ax->key1_id));
+ memcpy(ax->key1_id, key1_id, ax->key1_id_size);
+ } else
+ ax->key1_id_size = 0;
+ ax->key2 = key2;
+ if (key2 != -1) {
+ ax->key2_id_size = min(key2_id_size, sizeof(ax->key2_id));
+ memcpy(ax->key2_id, key2_id, ax->key2_id_size);
+ } else
+ ax->key2_id_size = 0;
+ list_add_tail(&ax->list, &ctx->crypto);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(__audit_log_crypto_op);
+
+/**
* audit_core_dumps - record information about processes that end abnormally
* @signr: signal value
*