lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Mon,  2 Mar 2015 10:00:59 -0600
From:	Tom Zanussi <tom.zanussi@...ux.intel.com>
To:	rostedt@...dmis.org
Cc:	masami.hiramatsu.pt@...achi.com, namhyung@...nel.org,
	andi@...stfloor.org, ast@...mgrid.com,
	linux-kernel@...r.kernel.org,
	Tom Zanussi <tom.zanussi@...ux.intel.com>
Subject: [PATCH 06/15] bpf: Add tracing_map client ops

External users of the tracing_map API may customize their map usage
and need to be notified of certain events occuring during the lifetime
of a map.

One example would be element deletion - if private data has been
associated with an element's value, the client should be notified when
that element is being deleted in order to give it a chance to delete
the private data.

struct bpf_map_client_ops defines a set of client callbacks, a pointer
to an instance of which can be passed by the client to tracing_map_create().

Initially, the only callback defined is free_elem(), which is called
when a map element is freed and gives clients the opportunity to free
app-specific elements.  Other callbacks such as a client-defined
sort() function are anticipated, however, which is why it's not a
standalone op.

Signed-off-by: Tom Zanussi <tom.zanussi@...ux.intel.com>
---
 include/linux/bpf.h   |  8 +++++++-
 kernel/bpf/arraymap.c | 16 ++++++++++++++++
 kernel/bpf/hashtab.c  | 12 ++++++++++++
 kernel/bpf/syscall.c  |  7 +++++--
 4 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index f7f95d7..09095ec 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -27,6 +27,10 @@ struct bpf_map_ops {
 	int (*map_delete_elem)(struct bpf_map *map, void *key);
 };
 
+struct bpf_map_client_ops {
+	void (*free_elem)(void *value);
+};
+
 struct bpf_map {
 	atomic_t refcnt;
 	enum bpf_map_type map_type;
@@ -35,6 +39,7 @@ struct bpf_map {
 	u32 max_entries;
 	struct bpf_map_ops *ops;
 	struct work_struct work;
+	struct bpf_map_client_ops *client_ops;
 };
 
 struct bpf_map_type_list {
@@ -143,7 +148,8 @@ extern struct bpf_func_proto bpf_map_lookup_elem_proto;
 extern struct bpf_func_proto bpf_map_update_elem_proto;
 extern struct bpf_func_proto bpf_map_delete_elem_proto;
 
-struct bpf_map *tracing_map_create(union bpf_attr *attr);
+struct bpf_map *tracing_map_create(union bpf_attr *attr,
+				   struct bpf_map_client_ops *client_ops);
 void tracing_map_destroy(struct bpf_map *map);
 void tracing_map_clear(struct bpf_map *map);
 int tracing_map_update_elem(struct bpf_map *map, void *key, void *value,
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 9eb4d8a..333c959 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -119,6 +119,20 @@ static int array_map_delete_elem(struct bpf_map *map, void *key)
 	return -EINVAL;
 }
 
+static void free_client_elems(struct bpf_array *array)
+{
+	void *val;
+	u32 index;
+
+	if (!array->map.client_ops || !array->map.client_ops->free_elem)
+		return;
+
+	for (index = 0; index < array->map.max_entries; index++) {
+		val = array->value + array->elem_size * index;
+		array->map.client_ops->free_elem(val);
+	}
+}
+
 /* Called when map->refcnt goes to zero, either from workqueue or from syscall */
 static void array_map_free(struct bpf_map *map)
 {
@@ -131,6 +145,8 @@ static void array_map_free(struct bpf_map *map)
 	 */
 	synchronize_rcu();
 
+	free_client_elems(array);
+
 	kvfree(array);
 }
 
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index addf3a8..6f349ad 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -275,6 +275,16 @@ err:
 	return ret;
 }
 
+static void free_client_elem(struct bpf_htab *htab, struct htab_elem *l)
+{
+	void *val;
+
+	if (htab->map.client_ops && htab->map.client_ops->free_elem) {
+		val = l->key + round_up(htab->map.key_size, 8);
+		htab->map.client_ops->free_elem(val);
+	}
+}
+
 /* Called from syscall or from eBPF program */
 static int htab_map_delete_elem(struct bpf_map *map, void *key)
 {
@@ -298,6 +308,7 @@ static int htab_map_delete_elem(struct bpf_map *map, void *key)
 	l = lookup_elem_raw(head, hash, key, key_size);
 
 	if (l) {
+		free_client_elem(htab, l);
 		hlist_del_rcu(&l->hash_node);
 		htab->count--;
 		kfree_rcu(l, rcu);
@@ -318,6 +329,7 @@ static void delete_all_elements(struct bpf_htab *htab)
 		struct htab_elem *l;
 
 		hlist_for_each_entry_safe(l, n, head, hash_node) {
+			free_client_elem(htab, l);
 			hlist_del_rcu(&l->hash_node);
 			htab->count--;
 			kfree(l);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0f28904..85735e6 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -110,7 +110,8 @@ static const struct file_operations bpf_map_fops = {
  *
  * Return: the map created on success, ERR_PTR otherwise
  */
-struct bpf_map *tracing_map_create(union bpf_attr *attr)
+struct bpf_map *tracing_map_create(union bpf_attr *attr,
+				   struct bpf_map_client_ops *client_ops)
 {
 	struct bpf_map *map;
 
@@ -119,6 +120,8 @@ struct bpf_map *tracing_map_create(union bpf_attr *attr)
 	if (!IS_ERR(map))
 		atomic_set(&map->refcnt, 1);
 
+	map->client_ops = client_ops;
+
 	return map;
 }
 EXPORT_SYMBOL_GPL(tracing_map_create);
@@ -133,7 +136,7 @@ static int map_create(union bpf_attr *attr)
 	if (err)
 		return -EINVAL;
 
-	map = tracing_map_create(attr);
+	map = tracing_map_create(attr, NULL);
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
-- 
1.9.3

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ