diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/bpf/verifier.c | 146 |
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 | |||
1222 | static int *insn_stack; /* stack of insns to process */ | 1225 | static int *insn_stack; /* stack of insns to process */ |
1223 | static int cur_stack; /* current stack index */ | 1226 | static int cur_stack; /* current stack index */ |
1224 | static int *insn_state; | 1227 | static 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 | */ | ||
1404 | static 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 | |||
1429 | static 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 | |||
1367 | static int do_check(struct verifier_env *env) | 1467 | static 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 | ||
1649 | process_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 | ||
1790 | static 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 | |||
1674 | int bpf_check(struct bpf_prog *prog, union bpf_attr *attr) | 1812 | int 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 | ||
1728 | skip_full_check: | 1873 | skip_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); |