arraymap.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
  2. *
  3. * This program is free software; you can redistribute it and/or
  4. * modify it under the terms of version 2 of the GNU General Public
  5. * License as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful, but
  8. * WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  10. * General Public License for more details.
  11. */
  12. #include <linux/bpf.h>
  13. #include <linux/err.h>
  14. #include <linux/vmalloc.h>
  15. #include <linux/slab.h>
  16. #include <linux/mm.h>
  17. #include <linux/filter.h>
  18. #include <linux/perf_event.h>
  19. /* Called from syscall */
  20. static struct bpf_map *array_map_alloc(union bpf_attr *attr)
  21. {
  22. struct bpf_array *array;
  23. u32 elem_size, array_size;
  24. /* check sanity of attributes */
  25. if (attr->max_entries == 0 || attr->key_size != 4 ||
  26. attr->value_size == 0)
  27. return ERR_PTR(-EINVAL);
  28. if (attr->value_size >= 1 << (KMALLOC_SHIFT_MAX - 1))
  29. /* if value_size is bigger, the user space won't be able to
  30. * access the elements.
  31. */
  32. return ERR_PTR(-E2BIG);
  33. elem_size = round_up(attr->value_size, 8);
  34. /* check round_up into zero and u32 overflow */
  35. if (elem_size == 0 ||
  36. attr->max_entries > (U32_MAX - PAGE_SIZE - sizeof(*array)) / elem_size)
  37. return ERR_PTR(-ENOMEM);
  38. array_size = sizeof(*array) + attr->max_entries * elem_size;
  39. /* allocate all map elements and zero-initialize them */
  40. array = kzalloc(array_size, GFP_USER | __GFP_NOWARN);
  41. if (!array) {
  42. array = vzalloc(array_size);
  43. if (!array)
  44. return ERR_PTR(-ENOMEM);
  45. }
  46. /* copy mandatory map attributes */
  47. array->map.key_size = attr->key_size;
  48. array->map.value_size = attr->value_size;
  49. array->map.max_entries = attr->max_entries;
  50. array->map.pages = round_up(array_size, PAGE_SIZE) >> PAGE_SHIFT;
  51. array->elem_size = elem_size;
  52. return &array->map;
  53. }
  54. /* Called from syscall or from eBPF program */
  55. static void *array_map_lookup_elem(struct bpf_map *map, void *key)
  56. {
  57. struct bpf_array *array = container_of(map, struct bpf_array, map);
  58. u32 index = *(u32 *)key;
  59. if (index >= array->map.max_entries)
  60. return NULL;
  61. return array->value + array->elem_size * index;
  62. }
  63. /* Called from syscall */
  64. static int array_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
  65. {
  66. struct bpf_array *array = container_of(map, struct bpf_array, map);
  67. u32 index = *(u32 *)key;
  68. u32 *next = (u32 *)next_key;
  69. if (index >= array->map.max_entries) {
  70. *next = 0;
  71. return 0;
  72. }
  73. if (index == array->map.max_entries - 1)
  74. return -ENOENT;
  75. *next = index + 1;
  76. return 0;
  77. }
  78. /* Called from syscall or from eBPF program */
  79. static int array_map_update_elem(struct bpf_map *map, void *key, void *value,
  80. u64 map_flags)
  81. {
  82. struct bpf_array *array = container_of(map, struct bpf_array, map);
  83. u32 index = *(u32 *)key;
  84. if (map_flags > BPF_EXIST)
  85. /* unknown flags */
  86. return -EINVAL;
  87. if (index >= array->map.max_entries)
  88. /* all elements were pre-allocated, cannot insert a new one */
  89. return -E2BIG;
  90. if (map_flags == BPF_NOEXIST)
  91. /* all elements already exist */
  92. return -EEXIST;
  93. memcpy(array->value + array->elem_size * index, value, map->value_size);
  94. return 0;
  95. }
  96. /* Called from syscall or from eBPF program */
  97. static int array_map_delete_elem(struct bpf_map *map, void *key)
  98. {
  99. return -EINVAL;
  100. }
  101. /* Called when map->refcnt goes to zero, either from workqueue or from syscall */
  102. static void array_map_free(struct bpf_map *map)
  103. {
  104. struct bpf_array *array = container_of(map, struct bpf_array, map);
  105. /* at this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
  106. * so the programs (can be more than one that used this map) were
  107. * disconnected from events. Wait for outstanding programs to complete
  108. * and free the array
  109. */
  110. synchronize_rcu();
  111. kvfree(array);
  112. }
  113. static const struct bpf_map_ops array_ops = {
  114. .map_alloc = array_map_alloc,
  115. .map_free = array_map_free,
  116. .map_get_next_key = array_map_get_next_key,
  117. .map_lookup_elem = array_map_lookup_elem,
  118. .map_update_elem = array_map_update_elem,
  119. .map_delete_elem = array_map_delete_elem,
  120. };
  121. static struct bpf_map_type_list array_type __read_mostly = {
  122. .ops = &array_ops,
  123. .type = BPF_MAP_TYPE_ARRAY,
  124. };
  125. static int __init register_array_map(void)
  126. {
  127. bpf_register_map_type(&array_type);
  128. return 0;
  129. }
  130. late_initcall(register_array_map);
  131. static struct bpf_map *fd_array_map_alloc(union bpf_attr *attr)
  132. {
  133. /* only file descriptors can be stored in this type of map */
  134. if (attr->value_size != sizeof(u32))
  135. return ERR_PTR(-EINVAL);
  136. return array_map_alloc(attr);
  137. }
  138. static void fd_array_map_free(struct bpf_map *map)
  139. {
  140. struct bpf_array *array = container_of(map, struct bpf_array, map);
  141. int i;
  142. synchronize_rcu();
  143. /* make sure it's empty */
  144. for (i = 0; i < array->map.max_entries; i++)
  145. BUG_ON(array->ptrs[i] != NULL);
  146. kvfree(array);
  147. }
  148. static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
  149. {
  150. return NULL;
  151. }
  152. /* only called from syscall */
  153. static int fd_array_map_update_elem(struct bpf_map *map, void *key,
  154. void *value, u64 map_flags)
  155. {
  156. struct bpf_array *array = container_of(map, struct bpf_array, map);
  157. void *new_ptr, *old_ptr;
  158. u32 index = *(u32 *)key, ufd;
  159. if (map_flags != BPF_ANY)
  160. return -EINVAL;
  161. if (index >= array->map.max_entries)
  162. return -E2BIG;
  163. ufd = *(u32 *)value;
  164. new_ptr = map->ops->map_fd_get_ptr(map, ufd);
  165. if (IS_ERR(new_ptr))
  166. return PTR_ERR(new_ptr);
  167. old_ptr = xchg(array->ptrs + index, new_ptr);
  168. if (old_ptr)
  169. map->ops->map_fd_put_ptr(old_ptr);
  170. return 0;
  171. }
  172. static int fd_array_map_delete_elem(struct bpf_map *map, void *key)
  173. {
  174. struct bpf_array *array = container_of(map, struct bpf_array, map);
  175. void *old_ptr;
  176. u32 index = *(u32 *)key;
  177. if (index >= array->map.max_entries)
  178. return -E2BIG;
  179. old_ptr = xchg(array->ptrs + index, NULL);
  180. if (old_ptr) {
  181. map->ops->map_fd_put_ptr(old_ptr);
  182. return 0;
  183. } else {
  184. return -ENOENT;
  185. }
  186. }
  187. static void *prog_fd_array_get_ptr(struct bpf_map *map, int fd)
  188. {
  189. struct bpf_array *array = container_of(map, struct bpf_array, map);
  190. struct bpf_prog *prog = bpf_prog_get(fd);
  191. if (IS_ERR(prog))
  192. return prog;
  193. if (!bpf_prog_array_compatible(array, prog)) {
  194. bpf_prog_put(prog);
  195. return ERR_PTR(-EINVAL);
  196. }
  197. return prog;
  198. }
  199. static void prog_fd_array_put_ptr(void *ptr)
  200. {
  201. struct bpf_prog *prog = ptr;
  202. bpf_prog_put_rcu(prog);
  203. }
  204. /* decrement refcnt of all bpf_progs that are stored in this map */
  205. void bpf_fd_array_map_clear(struct bpf_map *map)
  206. {
  207. struct bpf_array *array = container_of(map, struct bpf_array, map);
  208. int i;
  209. for (i = 0; i < array->map.max_entries; i++)
  210. fd_array_map_delete_elem(map, &i);
  211. }
  212. static const struct bpf_map_ops prog_array_ops = {
  213. .map_alloc = fd_array_map_alloc,
  214. .map_free = fd_array_map_free,
  215. .map_get_next_key = array_map_get_next_key,
  216. .map_lookup_elem = fd_array_map_lookup_elem,
  217. .map_update_elem = fd_array_map_update_elem,
  218. .map_delete_elem = fd_array_map_delete_elem,
  219. .map_fd_get_ptr = prog_fd_array_get_ptr,
  220. .map_fd_put_ptr = prog_fd_array_put_ptr,
  221. };
  222. static struct bpf_map_type_list prog_array_type __read_mostly = {
  223. .ops = &prog_array_ops,
  224. .type = BPF_MAP_TYPE_PROG_ARRAY,
  225. };
  226. static int __init register_prog_array_map(void)
  227. {
  228. bpf_register_map_type(&prog_array_type);
  229. return 0;
  230. }
  231. late_initcall(register_prog_array_map);
  232. static void perf_event_array_map_free(struct bpf_map *map)
  233. {
  234. bpf_fd_array_map_clear(map);
  235. fd_array_map_free(map);
  236. }
  237. static void *perf_event_fd_array_get_ptr(struct bpf_map *map, int fd)
  238. {
  239. struct perf_event *event;
  240. const struct perf_event_attr *attr;
  241. event = perf_event_get(fd);
  242. if (IS_ERR(event))
  243. return event;
  244. attr = perf_event_attrs(event);
  245. if (IS_ERR(attr))
  246. goto err;
  247. if (attr->inherit)
  248. goto err;
  249. if (attr->type == PERF_TYPE_RAW)
  250. return event;
  251. if (attr->type == PERF_TYPE_HARDWARE)
  252. return event;
  253. if (attr->type == PERF_TYPE_SOFTWARE &&
  254. attr->config == PERF_COUNT_SW_BPF_OUTPUT)
  255. return event;
  256. err:
  257. perf_event_release_kernel(event);
  258. return ERR_PTR(-EINVAL);
  259. }
  260. static void perf_event_fd_array_put_ptr(void *ptr)
  261. {
  262. struct perf_event *event = ptr;
  263. perf_event_release_kernel(event);
  264. }
  265. static const struct bpf_map_ops perf_event_array_ops = {
  266. .map_alloc = fd_array_map_alloc,
  267. .map_free = perf_event_array_map_free,
  268. .map_get_next_key = array_map_get_next_key,
  269. .map_lookup_elem = fd_array_map_lookup_elem,
  270. .map_update_elem = fd_array_map_update_elem,
  271. .map_delete_elem = fd_array_map_delete_elem,
  272. .map_fd_get_ptr = perf_event_fd_array_get_ptr,
  273. .map_fd_put_ptr = perf_event_fd_array_put_ptr,
  274. };
  275. static struct bpf_map_type_list perf_event_array_type __read_mostly = {
  276. .ops = &perf_event_array_ops,
  277. .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
  278. };
  279. static int __init register_perf_event_array_map(void)
  280. {
  281. bpf_register_map_type(&perf_event_array_type);
  282. return 0;
  283. }
  284. late_initcall(register_perf_event_array_map);