aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf/verifier.c
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@plumgrid.com>2014-09-29 21:50:01 -0400
committerDavid S. Miller <davem@davemloft.net>2014-10-01 21:30:33 -0400
commitf1bca824dabba4ffe8582f87ca587780befce7ad (patch)
treef1fe8c1ea1a5a3bc3ecd97fc07cee7009750dddd /kernel/bpf/verifier.c
parent1b7bde6d659d30f171259cc2dfba8e5dab34e735 (diff)
bpf: add search pruning optimization to verifier
consider C program represented in eBPF: int filter(int arg) { int a, b, c, *ptr; if (arg == 1) ptr = &a; else if (arg == 2) ptr = &b; else ptr = &c; *ptr = 0; return 0; } eBPF verifier has to follow all possible paths through the program to recognize that '*ptr = 0' instruction would be safe to execute in all situations. It's doing it by picking a path towards the end and observes changes to registers and stack at every insn until it reaches bpf_exit. Then it comes back to one of the previous branches and goes towards the end again with potentially different values in registers. When program has a lot of branches, the number of possible combinations of branches is huge, so verifer has a hard limit of walking no more than 32k instructions. This limit can be reached and complex (but valid) programs could be rejected. Therefore it's important to recognize equivalent verifier states to prune this depth first search. Basic idea can be illustrated by the program (where .. are some eBPF insns): 1: .. 2: if (rX == rY) goto 4 3: .. 4: .. 5: .. 6: bpf_exit In the first pass towards bpf_exit the verifier will walk insns: 1, 2, 3, 4, 5, 6 Since insn#2 is a branch the verifier will remember its state in verifier stack to come back to it later. Since insn#4 is marked as 'branch target', the verifier will remember its state in explored_states[4] linked list. Once it reaches insn#6 successfully it will pop the state recorded at insn#2 and will continue. Without search pruning optimization verifier would have to walk 4, 5, 6 again, effectively simulating execution of insns 1, 2, 4, 5, 6 With search pruning it will check whether state at #4 after jumping from #2 is equivalent to one recorded in explored_states[4] during first pass. If there is an equivalent state, verifier can prune the search at #4 and declare this path to be safe as well. In other words two states at #4 are equivalent if execution of 1, 2, 3, 4 insns and 1, 2, 4 insns produces equivalent registers and stack. Signed-off-by: Alexei Starovoitov <ast@plumgrid.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/bpf/verifier.c')
-rw-r--r--kernel/bpf/verifier.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a086dd3210a8..801f5f3b9307 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -199,6 +199,7 @@ struct verifier_env {
199 struct verifier_stack_elem *head; /* stack of verifier states to be processed */ 199 struct verifier_stack_elem *head; /* stack of verifier states to be processed */
200 int stack_size; /* number of states to be processed */ 200 int stack_size; /* number of states to be processed */
201 struct verifier_state cur_state; /* current verifier state */ 201 struct verifier_state cur_state; /* current verifier state */
202 struct verifier_state_list **explored_states; /* search pruning optimization */
202 struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */ 203 struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */
203 u32 used_map_cnt; /* number of used maps */ 204 u32 used_map_cnt; /* number of used maps */
204}; 205};
@@ -1219,6 +1220,8 @@ enum {
1219 BRANCH = 2, 1220 BRANCH = 2,
1220}; 1221};
1221 1222
1223#define STATE_LIST_MARK ((struct verifier_state_list *) -1L)
1224
1222static int *insn_stack; /* stack of insns to process */ 1225static int *insn_stack; /* stack of insns to process */
1223static int cur_stack; /* current stack index */ 1226static int cur_stack; /* current stack index */
1224static int *insn_state; 1227static int *insn_state;
@@ -1241,6 +1244,10 @@ static int push_insn(int t, int w, int e, struct verifier_env *env)
1241 return -EINVAL; 1244 return -EINVAL;
1242 } 1245 }
1243 1246
1247 if (e == BRANCH)
1248 /* mark branch target for state pruning */
1249 env->explored_states[w] = STATE_LIST_MARK;
1250
1244 if (insn_state[w] == 0) { 1251 if (insn_state[w] == 0) {
1245 /* tree-edge */ 1252 /* tree-edge */
1246 insn_state[t] = DISCOVERED | e; 1253 insn_state[t] = DISCOVERED | e;
@@ -1314,6 +1321,10 @@ peek_stack:
1314 goto peek_stack; 1321 goto peek_stack;
1315 else if (ret < 0) 1322 else if (ret < 0)
1316 goto err_free; 1323 goto err_free;
1324 /* tell verifier to check for equivalent states
1325 * after every call and jump
1326 */
1327 env->explored_states[t + 1] = STATE_LIST_MARK;
1317 } else { 1328 } else {
1318 /* conditional jump with two edges */ 1329 /* conditional jump with two edges */
1319 ret = push_insn(t, t + 1, FALLTHROUGH, env); 1330 ret = push_insn(t, t + 1, FALLTHROUGH, env);
@@ -1364,6 +1375,95 @@ err_free:
1364 return ret; 1375 return ret;
1365} 1376}
1366 1377
1378/* compare two verifier states
1379 *
1380 * all states stored in state_list are known to be valid, since
1381 * verifier reached 'bpf_exit' instruction through them
1382 *
1383 * this function is called when verifier exploring different branches of
1384 * execution popped from the state stack. If it sees an old state that has
1385 * more strict register state and more strict stack state then this execution
1386 * branch doesn't need to be explored further, since verifier already
1387 * concluded that more strict state leads to valid finish.
1388 *
1389 * Therefore two states are equivalent if register state is more conservative
1390 * and explored stack state is more conservative than the current one.
1391 * Example:
1392 * explored current
1393 * (slot1=INV slot2=MISC) == (slot1=MISC slot2=MISC)
1394 * (slot1=MISC slot2=MISC) != (slot1=INV slot2=MISC)
1395 *
1396 * In other words if current stack state (one being explored) has more
1397 * valid slots than old one that already passed validation, it means
1398 * the verifier can stop exploring and conclude that current state is valid too
1399 *
1400 * Similarly with registers. If explored state has register type as invalid
1401 * whereas register type in current state is meaningful, it means that
1402 * the current state will reach 'bpf_exit' instruction safely
1403 */
1404static bool states_equal(struct verifier_state *old, struct verifier_state *cur)
1405{
1406 int i;
1407
1408 for (i = 0; i < MAX_BPF_REG; i++) {
1409 if (memcmp(&old->regs[i], &cur->regs[i],
1410 sizeof(old->regs[0])) != 0) {
1411 if (old->regs[i].type == NOT_INIT ||
1412 old->regs[i].type == UNKNOWN_VALUE)
1413 continue;
1414 return false;
1415 }
1416 }
1417
1418 for (i = 0; i < MAX_BPF_STACK; i++) {
1419 if (memcmp(&old->stack[i], &cur->stack[i],
1420 sizeof(old->stack[0])) != 0) {
1421 if (old->stack[i].stype == STACK_INVALID)
1422 continue;
1423 return false;
1424 }
1425 }
1426 return true;
1427}
1428
1429static int is_state_visited(struct verifier_env *env, int insn_idx)
1430{
1431 struct verifier_state_list *new_sl;
1432 struct verifier_state_list *sl;
1433
1434 sl = env->explored_states[insn_idx];
1435 if (!sl)
1436 /* this 'insn_idx' instruction wasn't marked, so we will not
1437 * be doing state search here
1438 */
1439 return 0;
1440
1441 while (sl != STATE_LIST_MARK) {
1442 if (states_equal(&sl->state, &env->cur_state))
1443 /* reached equivalent register/stack state,
1444 * prune the search
1445 */
1446 return 1;
1447 sl = sl->next;
1448 }
1449
1450 /* there were no equivalent states, remember current one.
1451 * technically the current state is not proven to be safe yet,
1452 * but it will either reach bpf_exit (which means it's safe) or
1453 * it will be rejected. Since there are no loops, we won't be
1454 * seeing this 'insn_idx' instruction again on the way to bpf_exit
1455 */
1456 new_sl = kmalloc(sizeof(struct verifier_state_list), GFP_USER);
1457 if (!new_sl)
1458 return -ENOMEM;
1459
1460 /* add new state to the head of linked list */
1461 memcpy(&new_sl->state, &env->cur_state, sizeof(env->cur_state));
1462 new_sl->next = env->explored_states[insn_idx];
1463 env->explored_states[insn_idx] = new_sl;
1464 return 0;
1465}
1466
1367static int do_check(struct verifier_env *env) 1467static int do_check(struct verifier_env *env)
1368{ 1468{
1369 struct verifier_state *state = &env->cur_state; 1469 struct verifier_state *state = &env->cur_state;
@@ -1396,6 +1496,21 @@ static int do_check(struct verifier_env *env)
1396 return -E2BIG; 1496 return -E2BIG;
1397 } 1497 }
1398 1498
1499 err = is_state_visited(env, insn_idx);
1500 if (err < 0)
1501 return err;
1502 if (err == 1) {
1503 /* found equivalent state, can prune the search */
1504 if (log_level) {
1505 if (do_print_state)
1506 verbose("\nfrom %d to %d: safe\n",
1507 prev_insn_idx, insn_idx);
1508 else
1509 verbose("%d: safe\n", insn_idx);
1510 }
1511 goto process_bpf_exit;
1512 }
1513
1399 if (log_level && do_print_state) { 1514 if (log_level && do_print_state) {
1400 verbose("\nfrom %d to %d:", prev_insn_idx, insn_idx); 1515 verbose("\nfrom %d to %d:", prev_insn_idx, insn_idx);
1401 print_verifier_state(env); 1516 print_verifier_state(env);
@@ -1531,6 +1646,7 @@ static int do_check(struct verifier_env *env)
1531 if (err) 1646 if (err)
1532 return err; 1647 return err;
1533 1648
1649process_bpf_exit:
1534 insn_idx = pop_stack(env, &prev_insn_idx); 1650 insn_idx = pop_stack(env, &prev_insn_idx);
1535 if (insn_idx < 0) { 1651 if (insn_idx < 0) {
1536 break; 1652 break;
@@ -1671,6 +1787,28 @@ static void convert_pseudo_ld_imm64(struct verifier_env *env)
1671 insn->src_reg = 0; 1787 insn->src_reg = 0;
1672} 1788}
1673 1789
1790static void free_states(struct verifier_env *env)
1791{
1792 struct verifier_state_list *sl, *sln;
1793 int i;
1794
1795 if (!env->explored_states)
1796 return;
1797
1798 for (i = 0; i < env->prog->len; i++) {
1799 sl = env->explored_states[i];
1800
1801 if (sl)
1802 while (sl != STATE_LIST_MARK) {
1803 sln = sl->next;
1804 kfree(sl);
1805 sl = sln;
1806 }
1807 }
1808
1809 kfree(env->explored_states);
1810}
1811
1674int bpf_check(struct bpf_prog *prog, union bpf_attr *attr) 1812int bpf_check(struct bpf_prog *prog, union bpf_attr *attr)
1675{ 1813{
1676 char __user *log_ubuf = NULL; 1814 char __user *log_ubuf = NULL;
@@ -1719,6 +1857,13 @@ int bpf_check(struct bpf_prog *prog, union bpf_attr *attr)
1719 if (ret < 0) 1857 if (ret < 0)
1720 goto skip_full_check; 1858 goto skip_full_check;
1721 1859
1860 env->explored_states = kcalloc(prog->len,
1861 sizeof(struct verifier_state_list *),
1862 GFP_USER);
1863 ret = -ENOMEM;
1864 if (!env->explored_states)
1865 goto skip_full_check;
1866
1722 ret = check_cfg(env); 1867 ret = check_cfg(env);
1723 if (ret < 0) 1868 if (ret < 0)
1724 goto skip_full_check; 1869 goto skip_full_check;
@@ -1727,6 +1872,7 @@ int bpf_check(struct bpf_prog *prog, union bpf_attr *attr)
1727 1872
1728skip_full_check: 1873skip_full_check:
1729 while (pop_stack(env, NULL) >= 0); 1874 while (pop_stack(env, NULL) >= 0);
1875 free_states(env);
1730 1876
1731 if (log_level && log_len >= log_size - 1) { 1877 if (log_level && log_len >= log_size - 1) {
1732 BUG_ON(log_len >= log_size); 1878 BUG_ON(log_len >= log_size);