aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-05-04 00:52:29 -0400
committerDavid S. Miller <davem@davemloft.net>2016-05-04 00:52:29 -0400
commitcba653210056cf47cc1969f831f05ddfb99ee2bd (patch)
tree92d93a3eee5b12d77af3696b9da8026e71df5752 /kernel/bpf
parent26879da58711aa604a1b866cbeedd7e0f78f90ad (diff)
parent7391daf2ffc780679d6ab3fad1db2619e5dd2c2a (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: net/ipv4/ip_gre.c Minor conflicts between tunnel bug fixes in net and ipv6 tunnel cleanups in net-next. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/inode.c7
-rw-r--r--kernel/bpf/syscall.c24
-rw-r--r--kernel/bpf/verifier.c76
3 files changed, 71 insertions, 36 deletions
diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c
index f2ece3c174a5..8f94ca1860cf 100644
--- a/kernel/bpf/inode.c
+++ b/kernel/bpf/inode.c
@@ -31,10 +31,10 @@ static void *bpf_any_get(void *raw, enum bpf_type type)
31{ 31{
32 switch (type) { 32 switch (type) {
33 case BPF_TYPE_PROG: 33 case BPF_TYPE_PROG:
34 atomic_inc(&((struct bpf_prog *)raw)->aux->refcnt); 34 raw = bpf_prog_inc(raw);
35 break; 35 break;
36 case BPF_TYPE_MAP: 36 case BPF_TYPE_MAP:
37 bpf_map_inc(raw, true); 37 raw = bpf_map_inc(raw, true);
38 break; 38 break;
39 default: 39 default:
40 WARN_ON_ONCE(1); 40 WARN_ON_ONCE(1);
@@ -297,7 +297,8 @@ static void *bpf_obj_do_get(const struct filename *pathname,
297 goto out; 297 goto out;
298 298
299 raw = bpf_any_get(inode->i_private, *type); 299 raw = bpf_any_get(inode->i_private, *type);
300 touch_atime(&path); 300 if (!IS_ERR(raw))
301 touch_atime(&path);
301 302
302 path_put(&path); 303 path_put(&path);
303 return raw; 304 return raw;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index adc5e4bd74f8..cf5e9f7ad13a 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -218,11 +218,18 @@ struct bpf_map *__bpf_map_get(struct fd f)
218 return f.file->private_data; 218 return f.file->private_data;
219} 219}
220 220
221void bpf_map_inc(struct bpf_map *map, bool uref) 221/* prog's and map's refcnt limit */
222#define BPF_MAX_REFCNT 32768
223
224struct bpf_map *bpf_map_inc(struct bpf_map *map, bool uref)
222{ 225{
223 atomic_inc(&map->refcnt); 226 if (atomic_inc_return(&map->refcnt) > BPF_MAX_REFCNT) {
227 atomic_dec(&map->refcnt);
228 return ERR_PTR(-EBUSY);
229 }
224 if (uref) 230 if (uref)
225 atomic_inc(&map->usercnt); 231 atomic_inc(&map->usercnt);
232 return map;
226} 233}
227 234
228struct bpf_map *bpf_map_get_with_uref(u32 ufd) 235struct bpf_map *bpf_map_get_with_uref(u32 ufd)
@@ -234,7 +241,7 @@ struct bpf_map *bpf_map_get_with_uref(u32 ufd)
234 if (IS_ERR(map)) 241 if (IS_ERR(map))
235 return map; 242 return map;
236 243
237 bpf_map_inc(map, true); 244 map = bpf_map_inc(map, true);
238 fdput(f); 245 fdput(f);
239 246
240 return map; 247 return map;
@@ -658,6 +665,15 @@ static struct bpf_prog *__bpf_prog_get(struct fd f)
658 return f.file->private_data; 665 return f.file->private_data;
659} 666}
660 667
668struct bpf_prog *bpf_prog_inc(struct bpf_prog *prog)
669{
670 if (atomic_inc_return(&prog->aux->refcnt) > BPF_MAX_REFCNT) {
671 atomic_dec(&prog->aux->refcnt);
672 return ERR_PTR(-EBUSY);
673 }
674 return prog;
675}
676
661/* called by sockets/tracing/seccomp before attaching program to an event 677/* called by sockets/tracing/seccomp before attaching program to an event
662 * pairs with bpf_prog_put() 678 * pairs with bpf_prog_put()
663 */ 679 */
@@ -670,7 +686,7 @@ struct bpf_prog *bpf_prog_get(u32 ufd)
670 if (IS_ERR(prog)) 686 if (IS_ERR(prog))
671 return prog; 687 return prog;
672 688
673 atomic_inc(&prog->aux->refcnt); 689 prog = bpf_prog_inc(prog);
674 fdput(f); 690 fdput(f);
675 691
676 return prog; 692 return prog;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 56f18068b52b..63554b6d4e25 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -249,16 +249,6 @@ static const char * const reg_type_str[] = {
249 [CONST_IMM] = "imm", 249 [CONST_IMM] = "imm",
250}; 250};
251 251
252static const struct {
253 int map_type;
254 int func_id;
255} func_limit[] = {
256 {BPF_MAP_TYPE_PROG_ARRAY, BPF_FUNC_tail_call},
257 {BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_read},
258 {BPF_MAP_TYPE_PERF_EVENT_ARRAY, BPF_FUNC_perf_event_output},
259 {BPF_MAP_TYPE_STACK_TRACE, BPF_FUNC_get_stackid},
260};
261
262static void print_verifier_state(struct verifier_env *env) 252static void print_verifier_state(struct verifier_env *env)
263{ 253{
264 enum bpf_reg_type t; 254 enum bpf_reg_type t;
@@ -943,27 +933,52 @@ static int check_func_arg(struct verifier_env *env, u32 regno,
943 933
944static int check_map_func_compatibility(struct bpf_map *map, int func_id) 934static int check_map_func_compatibility(struct bpf_map *map, int func_id)
945{ 935{
946 bool bool_map, bool_func;
947 int i;
948
949 if (!map) 936 if (!map)
950 return 0; 937 return 0;
951 938
952 for (i = 0; i < ARRAY_SIZE(func_limit); i++) { 939 /* We need a two way check, first is from map perspective ... */
953 bool_map = (map->map_type == func_limit[i].map_type); 940 switch (map->map_type) {
954 bool_func = (func_id == func_limit[i].func_id); 941 case BPF_MAP_TYPE_PROG_ARRAY:
955 /* only when map & func pair match it can continue. 942 if (func_id != BPF_FUNC_tail_call)
956 * don't allow any other map type to be passed into 943 goto error;
957 * the special func; 944 break;
958 */ 945 case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
959 if (bool_func && bool_map != bool_func) { 946 if (func_id != BPF_FUNC_perf_event_read &&
960 verbose("cannot pass map_type %d into func %d\n", 947 func_id != BPF_FUNC_perf_event_output)
961 map->map_type, func_id); 948 goto error;
962 return -EINVAL; 949 break;
963 } 950 case BPF_MAP_TYPE_STACK_TRACE:
951 if (func_id != BPF_FUNC_get_stackid)
952 goto error;
953 break;
954 default:
955 break;
956 }
957
958 /* ... and second from the function itself. */
959 switch (func_id) {
960 case BPF_FUNC_tail_call:
961 if (map->map_type != BPF_MAP_TYPE_PROG_ARRAY)
962 goto error;
963 break;
964 case BPF_FUNC_perf_event_read:
965 case BPF_FUNC_perf_event_output:
966 if (map->map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY)
967 goto error;
968 break;
969 case BPF_FUNC_get_stackid:
970 if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
971 goto error;
972 break;
973 default:
974 break;
964 } 975 }
965 976
966 return 0; 977 return 0;
978error:
979 verbose("cannot pass map_type %d into func %d\n",
980 map->map_type, func_id);
981 return -EINVAL;
967} 982}
968 983
969static int check_raw_mode(const struct bpf_func_proto *fn) 984static int check_raw_mode(const struct bpf_func_proto *fn)
@@ -2111,15 +2126,18 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env)
2111 return -E2BIG; 2126 return -E2BIG;
2112 } 2127 }
2113 2128
2114 /* remember this map */
2115 env->used_maps[env->used_map_cnt++] = map;
2116
2117 /* hold the map. If the program is rejected by verifier, 2129 /* hold the map. If the program is rejected by verifier,
2118 * the map will be released by release_maps() or it 2130 * the map will be released by release_maps() or it
2119 * will be used by the valid program until it's unloaded 2131 * will be used by the valid program until it's unloaded
2120 * and all maps are released in free_bpf_prog_info() 2132 * and all maps are released in free_bpf_prog_info()
2121 */ 2133 */
2122 bpf_map_inc(map, false); 2134 map = bpf_map_inc(map, false);
2135 if (IS_ERR(map)) {
2136 fdput(f);
2137 return PTR_ERR(map);
2138 }
2139 env->used_maps[env->used_map_cnt++] = map;
2140
2123 fdput(f); 2141 fdput(f);
2124next_insn: 2142next_insn:
2125 insn++; 2143 insn++;