aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/bpf
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/bpf')
-rw-r--r--kernel/bpf/core.c4
-rw-r--r--kernel/bpf/disasm.c65
-rw-r--r--kernel/bpf/disasm.h29
-rw-r--r--kernel/bpf/syscall.c87
-rw-r--r--kernel/bpf/verifier.c30
5 files changed, 189 insertions, 26 deletions
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 768e0a02d8c8..70a534549cd3 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -771,7 +771,9 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog)
771 771
772/* Base function for offset calculation. Needs to go into .text section, 772/* Base function for offset calculation. Needs to go into .text section,
773 * therefore keeping it non-static as well; will also be used by JITs 773 * therefore keeping it non-static as well; will also be used by JITs
774 * anyway later on, so do not let the compiler omit it. 774 * anyway later on, so do not let the compiler omit it. This also needs
775 * to go into kallsyms for correlation from e.g. bpftool, so naming
776 * must not change.
775 */ 777 */
776noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) 778noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5)
777{ 779{
diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c
index 883f88fa5bfc..8740406df2cd 100644
--- a/kernel/bpf/disasm.c
+++ b/kernel/bpf/disasm.c
@@ -21,10 +21,39 @@ static const char * const func_id_str[] = {
21}; 21};
22#undef __BPF_FUNC_STR_FN 22#undef __BPF_FUNC_STR_FN
23 23
24const char *func_id_name(int id) 24static const char *__func_get_name(const struct bpf_insn_cbs *cbs,
25 const struct bpf_insn *insn,
26 char *buff, size_t len)
25{ 27{
26 BUILD_BUG_ON(ARRAY_SIZE(func_id_str) != __BPF_FUNC_MAX_ID); 28 BUILD_BUG_ON(ARRAY_SIZE(func_id_str) != __BPF_FUNC_MAX_ID);
27 29
30 if (insn->src_reg != BPF_PSEUDO_CALL &&
31 insn->imm >= 0 && insn->imm < __BPF_FUNC_MAX_ID &&
32 func_id_str[insn->imm])
33 return func_id_str[insn->imm];
34
35 if (cbs && cbs->cb_call)
36 return cbs->cb_call(cbs->private_data, insn);
37
38 if (insn->src_reg == BPF_PSEUDO_CALL)
39 snprintf(buff, len, "%+d", insn->imm);
40
41 return buff;
42}
43
44static const char *__func_imm_name(const struct bpf_insn_cbs *cbs,
45 const struct bpf_insn *insn,
46 u64 full_imm, char *buff, size_t len)
47{
48 if (cbs && cbs->cb_imm)
49 return cbs->cb_imm(cbs->private_data, insn, full_imm);
50
51 snprintf(buff, len, "0x%llx", (unsigned long long)full_imm);
52 return buff;
53}
54
55const char *func_id_name(int id)
56{
28 if (id >= 0 && id < __BPF_FUNC_MAX_ID && func_id_str[id]) 57 if (id >= 0 && id < __BPF_FUNC_MAX_ID && func_id_str[id])
29 return func_id_str[id]; 58 return func_id_str[id];
30 else 59 else
@@ -83,7 +112,7 @@ static const char *const bpf_jmp_string[16] = {
83 [BPF_EXIT >> 4] = "exit", 112 [BPF_EXIT >> 4] = "exit",
84}; 113};
85 114
86static void print_bpf_end_insn(bpf_insn_print_cb verbose, 115static void print_bpf_end_insn(bpf_insn_print_t verbose,
87 struct bpf_verifier_env *env, 116 struct bpf_verifier_env *env,
88 const struct bpf_insn *insn) 117 const struct bpf_insn *insn)
89{ 118{
@@ -92,9 +121,12 @@ static void print_bpf_end_insn(bpf_insn_print_cb verbose,
92 insn->imm, insn->dst_reg); 121 insn->imm, insn->dst_reg);
93} 122}
94 123
95void print_bpf_insn(bpf_insn_print_cb verbose, struct bpf_verifier_env *env, 124void print_bpf_insn(const struct bpf_insn_cbs *cbs,
96 const struct bpf_insn *insn, bool allow_ptr_leaks) 125 struct bpf_verifier_env *env,
126 const struct bpf_insn *insn,
127 bool allow_ptr_leaks)
97{ 128{
129 const bpf_insn_print_t verbose = cbs->cb_print;
98 u8 class = BPF_CLASS(insn->code); 130 u8 class = BPF_CLASS(insn->code);
99 131
100 if (class == BPF_ALU || class == BPF_ALU64) { 132 if (class == BPF_ALU || class == BPF_ALU64) {
@@ -175,12 +207,15 @@ void print_bpf_insn(bpf_insn_print_cb verbose, struct bpf_verifier_env *env,
175 */ 207 */
176 u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm; 208 u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
177 bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD; 209 bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
210 char tmp[64];
178 211
179 if (map_ptr && !allow_ptr_leaks) 212 if (map_ptr && !allow_ptr_leaks)
180 imm = 0; 213 imm = 0;
181 214
182 verbose(env, "(%02x) r%d = 0x%llx\n", insn->code, 215 verbose(env, "(%02x) r%d = %s\n",
183 insn->dst_reg, (unsigned long long)imm); 216 insn->code, insn->dst_reg,
217 __func_imm_name(cbs, insn, imm,
218 tmp, sizeof(tmp)));
184 } else { 219 } else {
185 verbose(env, "BUG_ld_%02x\n", insn->code); 220 verbose(env, "BUG_ld_%02x\n", insn->code);
186 return; 221 return;
@@ -189,12 +224,20 @@ void print_bpf_insn(bpf_insn_print_cb verbose, struct bpf_verifier_env *env,
189 u8 opcode = BPF_OP(insn->code); 224 u8 opcode = BPF_OP(insn->code);
190 225
191 if (opcode == BPF_CALL) { 226 if (opcode == BPF_CALL) {
192 if (insn->src_reg == BPF_PSEUDO_CALL) 227 char tmp[64];
193 verbose(env, "(%02x) call pc%+d\n", insn->code, 228
194 insn->imm); 229 if (insn->src_reg == BPF_PSEUDO_CALL) {
195 else 230 verbose(env, "(%02x) call pc%s\n",
231 insn->code,
232 __func_get_name(cbs, insn,
233 tmp, sizeof(tmp)));
234 } else {
235 strcpy(tmp, "unknown");
196 verbose(env, "(%02x) call %s#%d\n", insn->code, 236 verbose(env, "(%02x) call %s#%d\n", insn->code,
197 func_id_name(insn->imm), insn->imm); 237 __func_get_name(cbs, insn,
238 tmp, sizeof(tmp)),
239 insn->imm);
240 }
198 } else if (insn->code == (BPF_JMP | BPF_JA)) { 241 } else if (insn->code == (BPF_JMP | BPF_JA)) {
199 verbose(env, "(%02x) goto pc%+d\n", 242 verbose(env, "(%02x) goto pc%+d\n",
200 insn->code, insn->off); 243 insn->code, insn->off);
diff --git a/kernel/bpf/disasm.h b/kernel/bpf/disasm.h
index 8de977e420b6..e0857d016f89 100644
--- a/kernel/bpf/disasm.h
+++ b/kernel/bpf/disasm.h
@@ -17,16 +17,35 @@
17#include <linux/bpf.h> 17#include <linux/bpf.h>
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/stringify.h> 19#include <linux/stringify.h>
20#ifndef __KERNEL__
21#include <stdio.h>
22#include <string.h>
23#endif
24
25struct bpf_verifier_env;
20 26
21extern const char *const bpf_alu_string[16]; 27extern const char *const bpf_alu_string[16];
22extern const char *const bpf_class_string[8]; 28extern const char *const bpf_class_string[8];
23 29
24const char *func_id_name(int id); 30const char *func_id_name(int id);
25 31
26struct bpf_verifier_env; 32typedef void (*bpf_insn_print_t)(struct bpf_verifier_env *env,
27typedef void (*bpf_insn_print_cb)(struct bpf_verifier_env *env, 33 const char *, ...);
28 const char *, ...); 34typedef const char *(*bpf_insn_revmap_call_t)(void *private_data,
29void print_bpf_insn(bpf_insn_print_cb verbose, struct bpf_verifier_env *env, 35 const struct bpf_insn *insn);
30 const struct bpf_insn *insn, bool allow_ptr_leaks); 36typedef const char *(*bpf_insn_print_imm_t)(void *private_data,
37 const struct bpf_insn *insn,
38 __u64 full_imm);
39
40struct bpf_insn_cbs {
41 bpf_insn_print_t cb_print;
42 bpf_insn_revmap_call_t cb_call;
43 bpf_insn_print_imm_t cb_imm;
44 void *private_data;
45};
31 46
47void print_bpf_insn(const struct bpf_insn_cbs *cbs,
48 struct bpf_verifier_env *env,
49 const struct bpf_insn *insn,
50 bool allow_ptr_leaks);
32#endif 51#endif
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 30e728dcd35d..007802c5ca7d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1558,6 +1558,67 @@ static int bpf_map_get_fd_by_id(const union bpf_attr *attr)
1558 return fd; 1558 return fd;
1559} 1559}
1560 1560
1561static const struct bpf_map *bpf_map_from_imm(const struct bpf_prog *prog,
1562 unsigned long addr)
1563{
1564 int i;
1565
1566 for (i = 0; i < prog->aux->used_map_cnt; i++)
1567 if (prog->aux->used_maps[i] == (void *)addr)
1568 return prog->aux->used_maps[i];
1569 return NULL;
1570}
1571
1572static struct bpf_insn *bpf_insn_prepare_dump(const struct bpf_prog *prog)
1573{
1574 const struct bpf_map *map;
1575 struct bpf_insn *insns;
1576 u64 imm;
1577 int i;
1578
1579 insns = kmemdup(prog->insnsi, bpf_prog_insn_size(prog),
1580 GFP_USER);
1581 if (!insns)
1582 return insns;
1583
1584 for (i = 0; i < prog->len; i++) {
1585 if (insns[i].code == (BPF_JMP | BPF_TAIL_CALL)) {
1586 insns[i].code = BPF_JMP | BPF_CALL;
1587 insns[i].imm = BPF_FUNC_tail_call;
1588 /* fall-through */
1589 }
1590 if (insns[i].code == (BPF_JMP | BPF_CALL) ||
1591 insns[i].code == (BPF_JMP | BPF_CALL_ARGS)) {
1592 if (insns[i].code == (BPF_JMP | BPF_CALL_ARGS))
1593 insns[i].code = BPF_JMP | BPF_CALL;
1594 if (!bpf_dump_raw_ok())
1595 insns[i].imm = 0;
1596 continue;
1597 }
1598
1599 if (insns[i].code != (BPF_LD | BPF_IMM | BPF_DW))
1600 continue;
1601
1602 imm = ((u64)insns[i + 1].imm << 32) | (u32)insns[i].imm;
1603 map = bpf_map_from_imm(prog, imm);
1604 if (map) {
1605 insns[i].src_reg = BPF_PSEUDO_MAP_FD;
1606 insns[i].imm = map->id;
1607 insns[i + 1].imm = 0;
1608 continue;
1609 }
1610
1611 if (!bpf_dump_raw_ok() &&
1612 imm == (unsigned long)prog->aux) {
1613 insns[i].imm = 0;
1614 insns[i + 1].imm = 0;
1615 continue;
1616 }
1617 }
1618
1619 return insns;
1620}
1621
1561static int bpf_prog_get_info_by_fd(struct bpf_prog *prog, 1622static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
1562 const union bpf_attr *attr, 1623 const union bpf_attr *attr,
1563 union bpf_attr __user *uattr) 1624 union bpf_attr __user *uattr)
@@ -1608,18 +1669,34 @@ static int bpf_prog_get_info_by_fd(struct bpf_prog *prog,
1608 ulen = info.jited_prog_len; 1669 ulen = info.jited_prog_len;
1609 info.jited_prog_len = prog->jited_len; 1670 info.jited_prog_len = prog->jited_len;
1610 if (info.jited_prog_len && ulen) { 1671 if (info.jited_prog_len && ulen) {
1611 uinsns = u64_to_user_ptr(info.jited_prog_insns); 1672 if (bpf_dump_raw_ok()) {
1612 ulen = min_t(u32, info.jited_prog_len, ulen); 1673 uinsns = u64_to_user_ptr(info.jited_prog_insns);
1613 if (copy_to_user(uinsns, prog->bpf_func, ulen)) 1674 ulen = min_t(u32, info.jited_prog_len, ulen);
1614 return -EFAULT; 1675 if (copy_to_user(uinsns, prog->bpf_func, ulen))
1676 return -EFAULT;
1677 } else {
1678 info.jited_prog_insns = 0;
1679 }
1615 } 1680 }
1616 1681
1617 ulen = info.xlated_prog_len; 1682 ulen = info.xlated_prog_len;
1618 info.xlated_prog_len = bpf_prog_insn_size(prog); 1683 info.xlated_prog_len = bpf_prog_insn_size(prog);
1619 if (info.xlated_prog_len && ulen) { 1684 if (info.xlated_prog_len && ulen) {
1685 struct bpf_insn *insns_sanitized;
1686 bool fault;
1687
1688 if (prog->blinded && !bpf_dump_raw_ok()) {
1689 info.xlated_prog_insns = 0;
1690 goto done;
1691 }
1692 insns_sanitized = bpf_insn_prepare_dump(prog);
1693 if (!insns_sanitized)
1694 return -ENOMEM;
1620 uinsns = u64_to_user_ptr(info.xlated_prog_insns); 1695 uinsns = u64_to_user_ptr(info.xlated_prog_insns);
1621 ulen = min_t(u32, info.xlated_prog_len, ulen); 1696 ulen = min_t(u32, info.xlated_prog_len, ulen);
1622 if (copy_to_user(uinsns, prog->insnsi, ulen)) 1697 fault = copy_to_user(uinsns, insns_sanitized, ulen);
1698 kfree(insns_sanitized);
1699 if (fault)
1623 return -EFAULT; 1700 return -EFAULT;
1624 } 1701 }
1625 1702
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 3c3eec58b3e8..4ae46b2cba88 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -4427,9 +4427,12 @@ static int do_check(struct bpf_verifier_env *env)
4427 } 4427 }
4428 4428
4429 if (env->log.level) { 4429 if (env->log.level) {
4430 const struct bpf_insn_cbs cbs = {
4431 .cb_print = verbose,
4432 };
4433
4430 verbose(env, "%d: ", insn_idx); 4434 verbose(env, "%d: ", insn_idx);
4431 print_bpf_insn(verbose, env, insn, 4435 print_bpf_insn(&cbs, env, insn, env->allow_ptr_leaks);
4432 env->allow_ptr_leaks);
4433 } 4436 }
4434 4437
4435 err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx); 4438 err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx);
@@ -5017,14 +5020,14 @@ static int jit_subprogs(struct bpf_verifier_env *env)
5017{ 5020{
5018 struct bpf_prog *prog = env->prog, **func, *tmp; 5021 struct bpf_prog *prog = env->prog, **func, *tmp;
5019 int i, j, subprog_start, subprog_end = 0, len, subprog; 5022 int i, j, subprog_start, subprog_end = 0, len, subprog;
5020 struct bpf_insn *insn = prog->insnsi; 5023 struct bpf_insn *insn;
5021 void *old_bpf_func; 5024 void *old_bpf_func;
5022 int err = -ENOMEM; 5025 int err = -ENOMEM;
5023 5026
5024 if (env->subprog_cnt == 0) 5027 if (env->subprog_cnt == 0)
5025 return 0; 5028 return 0;
5026 5029
5027 for (i = 0; i < prog->len; i++, insn++) { 5030 for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
5028 if (insn->code != (BPF_JMP | BPF_CALL) || 5031 if (insn->code != (BPF_JMP | BPF_CALL) ||
5029 insn->src_reg != BPF_PSEUDO_CALL) 5032 insn->src_reg != BPF_PSEUDO_CALL)
5030 continue; 5033 continue;
@@ -5116,6 +5119,25 @@ static int jit_subprogs(struct bpf_verifier_env *env)
5116 bpf_prog_lock_ro(func[i]); 5119 bpf_prog_lock_ro(func[i]);
5117 bpf_prog_kallsyms_add(func[i]); 5120 bpf_prog_kallsyms_add(func[i]);
5118 } 5121 }
5122
5123 /* Last step: make now unused interpreter insns from main
5124 * prog consistent for later dump requests, so they can
5125 * later look the same as if they were interpreted only.
5126 */
5127 for (i = 0, insn = prog->insnsi; i < prog->len; i++, insn++) {
5128 unsigned long addr;
5129
5130 if (insn->code != (BPF_JMP | BPF_CALL) ||
5131 insn->src_reg != BPF_PSEUDO_CALL)
5132 continue;
5133 insn->off = env->insn_aux_data[i].call_imm;
5134 subprog = find_subprog(env, i + insn->off + 1);
5135 addr = (unsigned long)func[subprog + 1]->bpf_func;
5136 addr &= PAGE_MASK;
5137 insn->imm = (u64 (*)(u64, u64, u64, u64, u64))
5138 addr - __bpf_call_base;
5139 }
5140
5119 prog->jited = 1; 5141 prog->jited = 1;
5120 prog->bpf_func = func[0]->bpf_func; 5142 prog->bpf_func = func[0]->bpf_func;
5121 prog->aux->func = func; 5143 prog->aux->func = func;