gen_loader.c 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253
  1. // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
  2. /* Copyright (c) 2021 Facebook */
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <errno.h>
  7. #include <asm/byteorder.h>
  8. #include <linux/filter.h>
  9. #include <sys/param.h>
  10. #include "btf.h"
  11. #include "bpf.h"
  12. #include "libbpf.h"
  13. #include "libbpf_internal.h"
  14. #include "hashmap.h"
  15. #include "bpf_gen_internal.h"
  16. #include "skel_internal.h"
  17. #define MAX_USED_MAPS 64
  18. #define MAX_USED_PROGS 32
  19. #define MAX_KFUNC_DESCS 256
  20. #define MAX_FD_ARRAY_SZ (MAX_USED_MAPS + MAX_KFUNC_DESCS)
  21. /* The following structure describes the stack layout of the loader program.
  22. * In addition R6 contains the pointer to context.
  23. * R7 contains the result of the last sys_bpf command (typically error or FD).
  24. * R9 contains the result of the last sys_close command.
  25. *
  26. * Naming convention:
  27. * ctx - bpf program context
  28. * stack - bpf program stack
  29. * blob - bpf_attr-s, strings, insns, map data.
  30. * All the bytes that loader prog will use for read/write.
  31. */
  32. struct loader_stack {
  33. __u32 btf_fd;
  34. __u32 inner_map_fd;
  35. __u32 prog_fd[MAX_USED_PROGS];
  36. };
  37. #define stack_off(field) \
  38. (__s16)(-sizeof(struct loader_stack) + offsetof(struct loader_stack, field))
  39. #define attr_field(attr, field) (attr + offsetof(union bpf_attr, field))
  40. static int blob_fd_array_off(struct bpf_gen *gen, int index)
  41. {
  42. return gen->fd_array + index * sizeof(int);
  43. }
  44. static int realloc_insn_buf(struct bpf_gen *gen, __u32 size)
  45. {
  46. size_t off = gen->insn_cur - gen->insn_start;
  47. void *insn_start;
  48. if (gen->error)
  49. return gen->error;
  50. if (size > INT32_MAX || off + size > INT32_MAX) {
  51. gen->error = -ERANGE;
  52. return -ERANGE;
  53. }
  54. insn_start = realloc(gen->insn_start, off + size);
  55. if (!insn_start) {
  56. gen->error = -ENOMEM;
  57. free(gen->insn_start);
  58. gen->insn_start = NULL;
  59. return -ENOMEM;
  60. }
  61. gen->insn_start = insn_start;
  62. gen->insn_cur = insn_start + off;
  63. return 0;
  64. }
  65. static int realloc_data_buf(struct bpf_gen *gen, __u32 size)
  66. {
  67. size_t off = gen->data_cur - gen->data_start;
  68. void *data_start;
  69. if (gen->error)
  70. return gen->error;
  71. if (size > INT32_MAX || off + size > INT32_MAX) {
  72. gen->error = -ERANGE;
  73. return -ERANGE;
  74. }
  75. data_start = realloc(gen->data_start, off + size);
  76. if (!data_start) {
  77. gen->error = -ENOMEM;
  78. free(gen->data_start);
  79. gen->data_start = NULL;
  80. return -ENOMEM;
  81. }
  82. gen->data_start = data_start;
  83. gen->data_cur = data_start + off;
  84. return 0;
  85. }
  86. static void emit(struct bpf_gen *gen, struct bpf_insn insn)
  87. {
  88. if (realloc_insn_buf(gen, sizeof(insn)))
  89. return;
  90. memcpy(gen->insn_cur, &insn, sizeof(insn));
  91. gen->insn_cur += sizeof(insn);
  92. }
  93. static void emit2(struct bpf_gen *gen, struct bpf_insn insn1, struct bpf_insn insn2)
  94. {
  95. emit(gen, insn1);
  96. emit(gen, insn2);
  97. }
  98. static int add_data(struct bpf_gen *gen, const void *data, __u32 size);
  99. static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off);
  100. static void emit_signature_match(struct bpf_gen *gen);
  101. void bpf_gen__init(struct bpf_gen *gen, int log_level, int nr_progs, int nr_maps)
  102. {
  103. size_t stack_sz = sizeof(struct loader_stack), nr_progs_sz;
  104. int i;
  105. gen->fd_array = add_data(gen, NULL, MAX_FD_ARRAY_SZ * sizeof(int));
  106. gen->log_level = log_level;
  107. /* save ctx pointer into R6 */
  108. emit(gen, BPF_MOV64_REG(BPF_REG_6, BPF_REG_1));
  109. /* bzero stack */
  110. emit(gen, BPF_MOV64_REG(BPF_REG_1, BPF_REG_10));
  111. emit(gen, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, -stack_sz));
  112. emit(gen, BPF_MOV64_IMM(BPF_REG_2, stack_sz));
  113. emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));
  114. emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
  115. /* amount of stack actually used, only used to calculate iterations, not stack offset */
  116. nr_progs_sz = offsetof(struct loader_stack, prog_fd[nr_progs]);
  117. /* jump over cleanup code */
  118. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0,
  119. /* size of cleanup code below (including map fd cleanup) */
  120. (nr_progs_sz / 4) * 3 + 2 +
  121. /* 6 insns for emit_sys_close_blob,
  122. * 6 insns for debug_regs in emit_sys_close_blob
  123. */
  124. nr_maps * (6 + (gen->log_level ? 6 : 0))));
  125. /* remember the label where all error branches will jump to */
  126. gen->cleanup_label = gen->insn_cur - gen->insn_start;
  127. /* emit cleanup code: close all temp FDs */
  128. for (i = 0; i < nr_progs_sz; i += 4) {
  129. emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, -stack_sz + i));
  130. emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0, 1));
  131. emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
  132. }
  133. for (i = 0; i < nr_maps; i++)
  134. emit_sys_close_blob(gen, blob_fd_array_off(gen, i));
  135. /* R7 contains the error code from sys_bpf. Copy it into R0 and exit. */
  136. emit(gen, BPF_MOV64_REG(BPF_REG_0, BPF_REG_7));
  137. emit(gen, BPF_EXIT_INSN());
  138. if (OPTS_GET(gen->opts, gen_hash, false))
  139. emit_signature_match(gen);
  140. }
  141. static int add_data(struct bpf_gen *gen, const void *data, __u32 size)
  142. {
  143. __u32 size8 = roundup(size, 8);
  144. __u64 zero = 0;
  145. void *prev;
  146. if (realloc_data_buf(gen, size8))
  147. return 0;
  148. prev = gen->data_cur;
  149. if (data) {
  150. memcpy(gen->data_cur, data, size);
  151. memcpy(gen->data_cur + size, &zero, size8 - size);
  152. } else {
  153. memset(gen->data_cur, 0, size8);
  154. }
  155. gen->data_cur += size8;
  156. return prev - gen->data_start;
  157. }
  158. /* Get index for map_fd/btf_fd slot in reserved fd_array, or in data relative
  159. * to start of fd_array. Caller can decide if it is usable or not.
  160. */
  161. static int add_map_fd(struct bpf_gen *gen)
  162. {
  163. if (gen->nr_maps == MAX_USED_MAPS) {
  164. pr_warn("Total maps exceeds %d\n", MAX_USED_MAPS);
  165. gen->error = -E2BIG;
  166. return 0;
  167. }
  168. return gen->nr_maps++;
  169. }
  170. static int add_kfunc_btf_fd(struct bpf_gen *gen)
  171. {
  172. int cur;
  173. if (gen->nr_fd_array == MAX_KFUNC_DESCS) {
  174. cur = add_data(gen, NULL, sizeof(int));
  175. return (cur - gen->fd_array) / sizeof(int);
  176. }
  177. return MAX_USED_MAPS + gen->nr_fd_array++;
  178. }
  179. static int insn_bytes_to_bpf_size(__u32 sz)
  180. {
  181. switch (sz) {
  182. case 8: return BPF_DW;
  183. case 4: return BPF_W;
  184. case 2: return BPF_H;
  185. case 1: return BPF_B;
  186. default: return -1;
  187. }
  188. }
  189. /* *(u64 *)(blob + off) = (u64)(void *)(blob + data) */
  190. static void emit_rel_store(struct bpf_gen *gen, int off, int data)
  191. {
  192. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
  193. 0, 0, 0, data));
  194. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  195. 0, 0, 0, off));
  196. emit(gen, BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, 0));
  197. }
  198. static void move_blob2blob(struct bpf_gen *gen, int off, int size, int blob_off)
  199. {
  200. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_2, BPF_PSEUDO_MAP_IDX_VALUE,
  201. 0, 0, 0, blob_off));
  202. emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_2, 0));
  203. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  204. 0, 0, 0, off));
  205. emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
  206. }
  207. static void move_blob2ctx(struct bpf_gen *gen, int ctx_off, int size, int blob_off)
  208. {
  209. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  210. 0, 0, 0, blob_off));
  211. emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_1, 0));
  212. emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_6, BPF_REG_0, ctx_off));
  213. }
  214. static void move_ctx2blob(struct bpf_gen *gen, int off, int size, int ctx_off,
  215. bool check_non_zero)
  216. {
  217. emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_6, ctx_off));
  218. if (check_non_zero)
  219. /* If value in ctx is zero don't update the blob.
  220. * For example: when ctx->map.max_entries == 0, keep default max_entries from bpf.c
  221. */
  222. emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 0, 3));
  223. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  224. 0, 0, 0, off));
  225. emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
  226. }
  227. static void move_stack2blob(struct bpf_gen *gen, int off, int size, int stack_off)
  228. {
  229. emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_10, stack_off));
  230. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  231. 0, 0, 0, off));
  232. emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_1, BPF_REG_0, 0));
  233. }
  234. static void move_stack2ctx(struct bpf_gen *gen, int ctx_off, int size, int stack_off)
  235. {
  236. emit(gen, BPF_LDX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_0, BPF_REG_10, stack_off));
  237. emit(gen, BPF_STX_MEM(insn_bytes_to_bpf_size(size), BPF_REG_6, BPF_REG_0, ctx_off));
  238. }
  239. static void emit_sys_bpf(struct bpf_gen *gen, int cmd, int attr, int attr_size)
  240. {
  241. emit(gen, BPF_MOV64_IMM(BPF_REG_1, cmd));
  242. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_2, BPF_PSEUDO_MAP_IDX_VALUE,
  243. 0, 0, 0, attr));
  244. emit(gen, BPF_MOV64_IMM(BPF_REG_3, attr_size));
  245. emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_bpf));
  246. /* remember the result in R7 */
  247. emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
  248. }
  249. static bool is_simm16(__s64 value)
  250. {
  251. return value == (__s64)(__s16)value;
  252. }
  253. static void emit_check_err(struct bpf_gen *gen)
  254. {
  255. __s64 off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1;
  256. /* R7 contains result of last sys_bpf command.
  257. * if (R7 < 0) goto cleanup;
  258. */
  259. if (is_simm16(off)) {
  260. emit(gen, BPF_JMP_IMM(BPF_JSLT, BPF_REG_7, 0, off));
  261. } else {
  262. gen->error = -ERANGE;
  263. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
  264. }
  265. }
  266. /* reg1 and reg2 should not be R1 - R5. They can be R0, R6 - R10 */
  267. static void emit_debug(struct bpf_gen *gen, int reg1, int reg2,
  268. const char *fmt, va_list args)
  269. {
  270. char buf[1024];
  271. int addr, len, ret;
  272. if (!gen->log_level)
  273. return;
  274. ret = vsnprintf(buf, sizeof(buf), fmt, args);
  275. if (ret < 1024 - 7 && reg1 >= 0 && reg2 < 0)
  276. /* The special case to accommodate common debug_ret():
  277. * to avoid specifying BPF_REG_7 and adding " r=%%d" to
  278. * prints explicitly.
  279. */
  280. strcat(buf, " r=%d");
  281. len = strlen(buf) + 1;
  282. addr = add_data(gen, buf, len);
  283. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  284. 0, 0, 0, addr));
  285. emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
  286. if (reg1 >= 0)
  287. emit(gen, BPF_MOV64_REG(BPF_REG_3, reg1));
  288. if (reg2 >= 0)
  289. emit(gen, BPF_MOV64_REG(BPF_REG_4, reg2));
  290. emit(gen, BPF_EMIT_CALL(BPF_FUNC_trace_printk));
  291. }
  292. static void debug_regs(struct bpf_gen *gen, int reg1, int reg2, const char *fmt, ...)
  293. {
  294. va_list args;
  295. va_start(args, fmt);
  296. emit_debug(gen, reg1, reg2, fmt, args);
  297. va_end(args);
  298. }
  299. static void debug_ret(struct bpf_gen *gen, const char *fmt, ...)
  300. {
  301. va_list args;
  302. va_start(args, fmt);
  303. emit_debug(gen, BPF_REG_7, -1, fmt, args);
  304. va_end(args);
  305. }
  306. static void __emit_sys_close(struct bpf_gen *gen)
  307. {
  308. emit(gen, BPF_JMP_IMM(BPF_JSLE, BPF_REG_1, 0,
  309. /* 2 is the number of the following insns
  310. * * 6 is additional insns in debug_regs
  311. */
  312. 2 + (gen->log_level ? 6 : 0)));
  313. emit(gen, BPF_MOV64_REG(BPF_REG_9, BPF_REG_1));
  314. emit(gen, BPF_EMIT_CALL(BPF_FUNC_sys_close));
  315. debug_regs(gen, BPF_REG_9, BPF_REG_0, "close(%%d) = %%d");
  316. }
  317. static void emit_sys_close_stack(struct bpf_gen *gen, int stack_off)
  318. {
  319. emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_10, stack_off));
  320. __emit_sys_close(gen);
  321. }
  322. static void emit_sys_close_blob(struct bpf_gen *gen, int blob_off)
  323. {
  324. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
  325. 0, 0, 0, blob_off));
  326. emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_1, BPF_REG_0, 0));
  327. __emit_sys_close(gen);
  328. }
  329. static void compute_sha_update_offsets(struct bpf_gen *gen);
  330. int bpf_gen__finish(struct bpf_gen *gen, int nr_progs, int nr_maps)
  331. {
  332. int i;
  333. if (nr_progs < gen->nr_progs || nr_maps != gen->nr_maps) {
  334. pr_warn("nr_progs %d/%d nr_maps %d/%d mismatch\n",
  335. nr_progs, gen->nr_progs, nr_maps, gen->nr_maps);
  336. gen->error = -EFAULT;
  337. return gen->error;
  338. }
  339. emit_sys_close_stack(gen, stack_off(btf_fd));
  340. for (i = 0; i < gen->nr_progs; i++)
  341. move_stack2ctx(gen,
  342. sizeof(struct bpf_loader_ctx) +
  343. sizeof(struct bpf_map_desc) * gen->nr_maps +
  344. sizeof(struct bpf_prog_desc) * i +
  345. offsetof(struct bpf_prog_desc, prog_fd), 4,
  346. stack_off(prog_fd[i]));
  347. for (i = 0; i < gen->nr_maps; i++)
  348. move_blob2ctx(gen,
  349. sizeof(struct bpf_loader_ctx) +
  350. sizeof(struct bpf_map_desc) * i +
  351. offsetof(struct bpf_map_desc, map_fd), 4,
  352. blob_fd_array_off(gen, i));
  353. emit(gen, BPF_MOV64_IMM(BPF_REG_0, 0));
  354. emit(gen, BPF_EXIT_INSN());
  355. if (OPTS_GET(gen->opts, gen_hash, false))
  356. compute_sha_update_offsets(gen);
  357. pr_debug("gen: finish %s\n", errstr(gen->error));
  358. if (!gen->error) {
  359. struct gen_loader_opts *opts = gen->opts;
  360. opts->insns = gen->insn_start;
  361. opts->insns_sz = gen->insn_cur - gen->insn_start;
  362. opts->data = gen->data_start;
  363. opts->data_sz = gen->data_cur - gen->data_start;
  364. /* use target endianness for embedded loader */
  365. if (gen->swapped_endian) {
  366. struct bpf_insn *insn = (struct bpf_insn *)opts->insns;
  367. int insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
  368. for (i = 0; i < insn_cnt; i++)
  369. bpf_insn_bswap(insn++);
  370. }
  371. }
  372. return gen->error;
  373. }
  374. void bpf_gen__free(struct bpf_gen *gen)
  375. {
  376. if (!gen)
  377. return;
  378. free(gen->data_start);
  379. free(gen->insn_start);
  380. free(gen);
  381. }
  382. /*
  383. * Fields of bpf_attr are set to values in native byte-order before being
  384. * written to the target-bound data blob, and may need endian conversion.
  385. * This macro allows providing the correct value in situ more simply than
  386. * writing a separate converter for *all fields* of *all records* included
  387. * in union bpf_attr. Note that sizeof(rval) should match the assignment
  388. * target to avoid runtime problems.
  389. */
  390. #define tgt_endian(rval) ({ \
  391. typeof(rval) _val = (rval); \
  392. if (gen->swapped_endian) { \
  393. switch (sizeof(_val)) { \
  394. case 1: break; \
  395. case 2: _val = bswap_16(_val); break; \
  396. case 4: _val = bswap_32(_val); break; \
  397. case 8: _val = bswap_64(_val); break; \
  398. default: pr_warn("unsupported bswap size!\n"); \
  399. } \
  400. } \
  401. _val; \
  402. })
  403. static void compute_sha_update_offsets(struct bpf_gen *gen)
  404. {
  405. __u64 sha[SHA256_DWORD_SIZE];
  406. __u64 sha_dw;
  407. int i;
  408. libbpf_sha256(gen->data_start, gen->data_cur - gen->data_start, (__u8 *)sha);
  409. for (i = 0; i < SHA256_DWORD_SIZE; i++) {
  410. struct bpf_insn *insn =
  411. (struct bpf_insn *)(gen->insn_start + gen->hash_insn_offset[i]);
  412. sha_dw = tgt_endian(sha[i]);
  413. insn[0].imm = (__u32)sha_dw;
  414. insn[1].imm = sha_dw >> 32;
  415. }
  416. }
  417. void bpf_gen__load_btf(struct bpf_gen *gen, const void *btf_raw_data,
  418. __u32 btf_raw_size)
  419. {
  420. int attr_size = offsetofend(union bpf_attr, btf_log_level);
  421. int btf_data, btf_load_attr;
  422. union bpf_attr attr;
  423. memset(&attr, 0, attr_size);
  424. btf_data = add_data(gen, btf_raw_data, btf_raw_size);
  425. attr.btf_size = tgt_endian(btf_raw_size);
  426. btf_load_attr = add_data(gen, &attr, attr_size);
  427. pr_debug("gen: load_btf: off %d size %d, attr: off %d size %d\n",
  428. btf_data, btf_raw_size, btf_load_attr, attr_size);
  429. /* populate union bpf_attr with user provided log details */
  430. move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_level), 4,
  431. offsetof(struct bpf_loader_ctx, log_level), false);
  432. move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_size), 4,
  433. offsetof(struct bpf_loader_ctx, log_size), false);
  434. move_ctx2blob(gen, attr_field(btf_load_attr, btf_log_buf), 8,
  435. offsetof(struct bpf_loader_ctx, log_buf), false);
  436. /* populate union bpf_attr with a pointer to the BTF data */
  437. emit_rel_store(gen, attr_field(btf_load_attr, btf), btf_data);
  438. /* emit BTF_LOAD command */
  439. emit_sys_bpf(gen, BPF_BTF_LOAD, btf_load_attr, attr_size);
  440. debug_ret(gen, "btf_load size %d", btf_raw_size);
  441. emit_check_err(gen);
  442. /* remember btf_fd in the stack, if successful */
  443. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7, stack_off(btf_fd)));
  444. }
  445. void bpf_gen__map_create(struct bpf_gen *gen,
  446. enum bpf_map_type map_type,
  447. const char *map_name,
  448. __u32 key_size, __u32 value_size, __u32 max_entries,
  449. struct bpf_map_create_opts *map_attr, int map_idx)
  450. {
  451. int attr_size = offsetofend(union bpf_attr, map_extra);
  452. bool close_inner_map_fd = false;
  453. int map_create_attr, idx;
  454. union bpf_attr attr;
  455. memset(&attr, 0, attr_size);
  456. attr.map_type = tgt_endian(map_type);
  457. attr.key_size = tgt_endian(key_size);
  458. attr.value_size = tgt_endian(value_size);
  459. attr.map_flags = tgt_endian(map_attr->map_flags);
  460. attr.map_extra = tgt_endian(map_attr->map_extra);
  461. if (map_name)
  462. libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
  463. attr.numa_node = tgt_endian(map_attr->numa_node);
  464. attr.map_ifindex = tgt_endian(map_attr->map_ifindex);
  465. attr.max_entries = tgt_endian(max_entries);
  466. attr.btf_key_type_id = tgt_endian(map_attr->btf_key_type_id);
  467. attr.btf_value_type_id = tgt_endian(map_attr->btf_value_type_id);
  468. map_create_attr = add_data(gen, &attr, attr_size);
  469. pr_debug("gen: map_create: %s idx %d type %d value_type_id %d, attr: off %d size %d\n",
  470. map_name, map_idx, map_type, map_attr->btf_value_type_id,
  471. map_create_attr, attr_size);
  472. if (map_attr->btf_value_type_id)
  473. /* populate union bpf_attr with btf_fd saved in the stack earlier */
  474. move_stack2blob(gen, attr_field(map_create_attr, btf_fd), 4,
  475. stack_off(btf_fd));
  476. switch (map_type) {
  477. case BPF_MAP_TYPE_ARRAY_OF_MAPS:
  478. case BPF_MAP_TYPE_HASH_OF_MAPS:
  479. move_stack2blob(gen, attr_field(map_create_attr, inner_map_fd), 4,
  480. stack_off(inner_map_fd));
  481. close_inner_map_fd = true;
  482. break;
  483. default:
  484. break;
  485. }
  486. /* conditionally update max_entries */
  487. if (map_idx >= 0)
  488. move_ctx2blob(gen, attr_field(map_create_attr, max_entries), 4,
  489. sizeof(struct bpf_loader_ctx) +
  490. sizeof(struct bpf_map_desc) * map_idx +
  491. offsetof(struct bpf_map_desc, max_entries),
  492. true /* check that max_entries != 0 */);
  493. /* emit MAP_CREATE command */
  494. emit_sys_bpf(gen, BPF_MAP_CREATE, map_create_attr, attr_size);
  495. debug_ret(gen, "map_create %s idx %d type %d value_size %d value_btf_id %d",
  496. map_name, map_idx, map_type, value_size,
  497. map_attr->btf_value_type_id);
  498. emit_check_err(gen);
  499. /* remember map_fd in the stack, if successful */
  500. if (map_idx < 0) {
  501. /* This bpf_gen__map_create() function is called with map_idx >= 0
  502. * for all maps that libbpf loading logic tracks.
  503. * It's called with -1 to create an inner map.
  504. */
  505. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
  506. stack_off(inner_map_fd)));
  507. } else if (map_idx != gen->nr_maps) {
  508. gen->error = -EDOM; /* internal bug */
  509. return;
  510. } else {
  511. /* add_map_fd does gen->nr_maps++ */
  512. idx = add_map_fd(gen);
  513. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  514. 0, 0, 0, blob_fd_array_off(gen, idx)));
  515. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_1, BPF_REG_7, 0));
  516. }
  517. if (close_inner_map_fd)
  518. emit_sys_close_stack(gen, stack_off(inner_map_fd));
  519. }
  520. static void emit_signature_match(struct bpf_gen *gen)
  521. {
  522. __s64 off;
  523. int i;
  524. for (i = 0; i < SHA256_DWORD_SIZE; i++) {
  525. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX,
  526. 0, 0, 0, 0));
  527. emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_1, i * sizeof(__u64)));
  528. gen->hash_insn_offset[i] = gen->insn_cur - gen->insn_start;
  529. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_3, 0, 0, 0, 0, 0));
  530. off = -(gen->insn_cur - gen->insn_start - gen->cleanup_label) / 8 - 1;
  531. if (is_simm16(off)) {
  532. emit(gen, BPF_MOV64_IMM(BPF_REG_7, -EINVAL));
  533. emit(gen, BPF_JMP_REG(BPF_JNE, BPF_REG_2, BPF_REG_3, off));
  534. } else {
  535. gen->error = -ERANGE;
  536. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, -1));
  537. }
  538. }
  539. }
  540. void bpf_gen__record_attach_target(struct bpf_gen *gen, const char *attach_name,
  541. enum bpf_attach_type type)
  542. {
  543. const char *prefix;
  544. int kind, ret;
  545. btf_get_kernel_prefix_kind(type, &prefix, &kind);
  546. gen->attach_kind = kind;
  547. ret = snprintf(gen->attach_target, sizeof(gen->attach_target), "%s%s",
  548. prefix, attach_name);
  549. if (ret >= sizeof(gen->attach_target))
  550. gen->error = -ENOSPC;
  551. }
  552. static void emit_find_attach_target(struct bpf_gen *gen)
  553. {
  554. int name, len = strlen(gen->attach_target) + 1;
  555. pr_debug("gen: find_attach_tgt %s %d\n", gen->attach_target, gen->attach_kind);
  556. name = add_data(gen, gen->attach_target, len);
  557. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  558. 0, 0, 0, name));
  559. emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
  560. emit(gen, BPF_MOV64_IMM(BPF_REG_3, gen->attach_kind));
  561. emit(gen, BPF_MOV64_IMM(BPF_REG_4, 0));
  562. emit(gen, BPF_EMIT_CALL(BPF_FUNC_btf_find_by_name_kind));
  563. emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
  564. debug_ret(gen, "find_by_name_kind(%s,%d)",
  565. gen->attach_target, gen->attach_kind);
  566. emit_check_err(gen);
  567. /* if successful, btf_id is in lower 32-bit of R7 and
  568. * btf_obj_fd is in upper 32-bit
  569. */
  570. }
  571. void bpf_gen__record_extern(struct bpf_gen *gen, const char *name, bool is_weak,
  572. bool is_typeless, bool is_ld64, int kind, int insn_idx)
  573. {
  574. struct ksym_relo_desc *relo;
  575. relo = libbpf_reallocarray(gen->relos, gen->relo_cnt + 1, sizeof(*relo));
  576. if (!relo) {
  577. gen->error = -ENOMEM;
  578. return;
  579. }
  580. gen->relos = relo;
  581. relo += gen->relo_cnt;
  582. relo->name = name;
  583. relo->is_weak = is_weak;
  584. relo->is_typeless = is_typeless;
  585. relo->is_ld64 = is_ld64;
  586. relo->kind = kind;
  587. relo->insn_idx = insn_idx;
  588. gen->relo_cnt++;
  589. }
  590. /* returns existing ksym_desc with ref incremented, or inserts a new one */
  591. static struct ksym_desc *get_ksym_desc(struct bpf_gen *gen, struct ksym_relo_desc *relo)
  592. {
  593. struct ksym_desc *kdesc;
  594. int i;
  595. for (i = 0; i < gen->nr_ksyms; i++) {
  596. kdesc = &gen->ksyms[i];
  597. if (kdesc->kind == relo->kind && kdesc->is_ld64 == relo->is_ld64 &&
  598. !strcmp(kdesc->name, relo->name)) {
  599. kdesc->ref++;
  600. return kdesc;
  601. }
  602. }
  603. kdesc = libbpf_reallocarray(gen->ksyms, gen->nr_ksyms + 1, sizeof(*kdesc));
  604. if (!kdesc) {
  605. gen->error = -ENOMEM;
  606. return NULL;
  607. }
  608. gen->ksyms = kdesc;
  609. kdesc = &gen->ksyms[gen->nr_ksyms++];
  610. kdesc->name = relo->name;
  611. kdesc->kind = relo->kind;
  612. kdesc->ref = 1;
  613. kdesc->off = 0;
  614. kdesc->insn = 0;
  615. kdesc->is_ld64 = relo->is_ld64;
  616. return kdesc;
  617. }
  618. /* Overwrites BPF_REG_{0, 1, 2, 3, 4, 7}
  619. * Returns result in BPF_REG_7
  620. */
  621. static void emit_bpf_find_by_name_kind(struct bpf_gen *gen, struct ksym_relo_desc *relo)
  622. {
  623. int name_off, len = strlen(relo->name) + 1;
  624. name_off = add_data(gen, relo->name, len);
  625. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  626. 0, 0, 0, name_off));
  627. emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
  628. emit(gen, BPF_MOV64_IMM(BPF_REG_3, relo->kind));
  629. emit(gen, BPF_MOV64_IMM(BPF_REG_4, 0));
  630. emit(gen, BPF_EMIT_CALL(BPF_FUNC_btf_find_by_name_kind));
  631. emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
  632. debug_ret(gen, "find_by_name_kind(%s,%d)", relo->name, relo->kind);
  633. }
  634. /* Overwrites BPF_REG_{0, 1, 2, 3, 4, 7}
  635. * Returns result in BPF_REG_7
  636. * Returns u64 symbol addr in BPF_REG_9
  637. */
  638. static void emit_bpf_kallsyms_lookup_name(struct bpf_gen *gen, struct ksym_relo_desc *relo)
  639. {
  640. int name_off, len = strlen(relo->name) + 1, res_off;
  641. name_off = add_data(gen, relo->name, len);
  642. res_off = add_data(gen, NULL, 8); /* res is u64 */
  643. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  644. 0, 0, 0, name_off));
  645. emit(gen, BPF_MOV64_IMM(BPF_REG_2, len));
  646. emit(gen, BPF_MOV64_IMM(BPF_REG_3, 0));
  647. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_4, BPF_PSEUDO_MAP_IDX_VALUE,
  648. 0, 0, 0, res_off));
  649. emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_4));
  650. emit(gen, BPF_EMIT_CALL(BPF_FUNC_kallsyms_lookup_name));
  651. emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_9, BPF_REG_7, 0));
  652. emit(gen, BPF_MOV64_REG(BPF_REG_7, BPF_REG_0));
  653. debug_ret(gen, "kallsyms_lookup_name(%s,%d)", relo->name, relo->kind);
  654. }
  655. /* Expects:
  656. * BPF_REG_8 - pointer to instruction
  657. *
  658. * We need to reuse BTF fd for same symbol otherwise each relocation takes a new
  659. * index, while kernel limits total kfunc BTFs to 256. For duplicate symbols,
  660. * this would mean a new BTF fd index for each entry. By pairing symbol name
  661. * with index, we get the insn->imm, insn->off pairing that kernel uses for
  662. * kfunc_tab, which becomes the effective limit even though all of them may
  663. * share same index in fd_array (such that kfunc_btf_tab has 1 element).
  664. */
  665. static void emit_relo_kfunc_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insn)
  666. {
  667. struct ksym_desc *kdesc;
  668. int btf_fd_idx;
  669. kdesc = get_ksym_desc(gen, relo);
  670. if (!kdesc)
  671. return;
  672. /* try to copy from existing bpf_insn */
  673. if (kdesc->ref > 1) {
  674. move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
  675. kdesc->insn + offsetof(struct bpf_insn, imm));
  676. move_blob2blob(gen, insn + offsetof(struct bpf_insn, off), 2,
  677. kdesc->insn + offsetof(struct bpf_insn, off));
  678. goto log;
  679. }
  680. /* remember insn offset, so we can copy BTF ID and FD later */
  681. kdesc->insn = insn;
  682. emit_bpf_find_by_name_kind(gen, relo);
  683. if (!relo->is_weak)
  684. emit_check_err(gen);
  685. /* get index in fd_array to store BTF FD at */
  686. btf_fd_idx = add_kfunc_btf_fd(gen);
  687. if (btf_fd_idx > INT16_MAX) {
  688. pr_warn("BTF fd off %d for kfunc %s exceeds INT16_MAX, cannot process relocation\n",
  689. btf_fd_idx, relo->name);
  690. gen->error = -E2BIG;
  691. return;
  692. }
  693. kdesc->off = btf_fd_idx;
  694. /* jump to success case */
  695. emit(gen, BPF_JMP_IMM(BPF_JSGE, BPF_REG_7, 0, 3));
  696. /* set value for imm, off as 0 */
  697. emit(gen, BPF_ST_MEM(BPF_W, BPF_REG_8, offsetof(struct bpf_insn, imm), 0));
  698. emit(gen, BPF_ST_MEM(BPF_H, BPF_REG_8, offsetof(struct bpf_insn, off), 0));
  699. /* skip success case for ret < 0 */
  700. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 10));
  701. /* store btf_id into insn[insn_idx].imm */
  702. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7, offsetof(struct bpf_insn, imm)));
  703. /* obtain fd in BPF_REG_9 */
  704. emit(gen, BPF_MOV64_REG(BPF_REG_9, BPF_REG_7));
  705. emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_9, 32));
  706. /* load fd_array slot pointer */
  707. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
  708. 0, 0, 0, blob_fd_array_off(gen, btf_fd_idx)));
  709. /* store BTF fd in slot, 0 for vmlinux */
  710. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_9, 0));
  711. /* jump to insn[insn_idx].off store if fd denotes module BTF */
  712. emit(gen, BPF_JMP_IMM(BPF_JNE, BPF_REG_9, 0, 2));
  713. /* set the default value for off */
  714. emit(gen, BPF_ST_MEM(BPF_H, BPF_REG_8, offsetof(struct bpf_insn, off), 0));
  715. /* skip BTF fd store for vmlinux BTF */
  716. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 1));
  717. /* store index into insn[insn_idx].off */
  718. emit(gen, BPF_ST_MEM(BPF_H, BPF_REG_8, offsetof(struct bpf_insn, off), btf_fd_idx));
  719. log:
  720. if (!gen->log_level)
  721. return;
  722. emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_8,
  723. offsetof(struct bpf_insn, imm)));
  724. emit(gen, BPF_LDX_MEM(BPF_H, BPF_REG_9, BPF_REG_8,
  725. offsetof(struct bpf_insn, off)));
  726. debug_regs(gen, BPF_REG_7, BPF_REG_9, " func (%s:count=%d): imm: %%d, off: %%d",
  727. relo->name, kdesc->ref);
  728. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
  729. 0, 0, 0, blob_fd_array_off(gen, kdesc->off)));
  730. emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_9, BPF_REG_0, 0));
  731. debug_regs(gen, BPF_REG_9, -1, " func (%s:count=%d): btf_fd",
  732. relo->name, kdesc->ref);
  733. }
  734. static void emit_ksym_relo_log(struct bpf_gen *gen, struct ksym_relo_desc *relo,
  735. int ref)
  736. {
  737. if (!gen->log_level)
  738. return;
  739. emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_7, BPF_REG_8,
  740. offsetof(struct bpf_insn, imm)));
  741. emit(gen, BPF_LDX_MEM(BPF_H, BPF_REG_9, BPF_REG_8, sizeof(struct bpf_insn) +
  742. offsetof(struct bpf_insn, imm)));
  743. debug_regs(gen, BPF_REG_7, BPF_REG_9, " var t=%d w=%d (%s:count=%d): imm[0]: %%d, imm[1]: %%d",
  744. relo->is_typeless, relo->is_weak, relo->name, ref);
  745. emit(gen, BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_8, offsetofend(struct bpf_insn, code)));
  746. debug_regs(gen, BPF_REG_9, -1, " var t=%d w=%d (%s:count=%d): insn.reg",
  747. relo->is_typeless, relo->is_weak, relo->name, ref);
  748. }
  749. /* Expects:
  750. * BPF_REG_8 - pointer to instruction
  751. */
  752. static void emit_relo_ksym_typeless(struct bpf_gen *gen,
  753. struct ksym_relo_desc *relo, int insn)
  754. {
  755. struct ksym_desc *kdesc;
  756. kdesc = get_ksym_desc(gen, relo);
  757. if (!kdesc)
  758. return;
  759. /* try to copy from existing ldimm64 insn */
  760. if (kdesc->ref > 1) {
  761. move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
  762. kdesc->insn + offsetof(struct bpf_insn, imm));
  763. move_blob2blob(gen, insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm), 4,
  764. kdesc->insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm));
  765. goto log;
  766. }
  767. /* remember insn offset, so we can copy ksym addr later */
  768. kdesc->insn = insn;
  769. /* skip typeless ksym_desc in fd closing loop in cleanup_relos */
  770. kdesc->typeless = true;
  771. emit_bpf_kallsyms_lookup_name(gen, relo);
  772. emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_7, -ENOENT, 1));
  773. emit_check_err(gen);
  774. /* store lower half of addr into insn[insn_idx].imm */
  775. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_9, offsetof(struct bpf_insn, imm)));
  776. /* store upper half of addr into insn[insn_idx + 1].imm */
  777. emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_9, 32));
  778. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_9,
  779. sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm)));
  780. log:
  781. emit_ksym_relo_log(gen, relo, kdesc->ref);
  782. }
  783. static __u32 src_reg_mask(struct bpf_gen *gen)
  784. {
  785. #if defined(__LITTLE_ENDIAN_BITFIELD) /* src_reg,dst_reg,... */
  786. return gen->swapped_endian ? 0xf0 : 0x0f;
  787. #elif defined(__BIG_ENDIAN_BITFIELD) /* dst_reg,src_reg,... */
  788. return gen->swapped_endian ? 0x0f : 0xf0;
  789. #else
  790. #error "Unsupported bit endianness, cannot proceed"
  791. #endif
  792. }
  793. /* Expects:
  794. * BPF_REG_8 - pointer to instruction
  795. */
  796. static void emit_relo_ksym_btf(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insn)
  797. {
  798. struct ksym_desc *kdesc;
  799. __u32 reg_mask;
  800. kdesc = get_ksym_desc(gen, relo);
  801. if (!kdesc)
  802. return;
  803. /* try to copy from existing ldimm64 insn */
  804. if (kdesc->ref > 1) {
  805. move_blob2blob(gen, insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm), 4,
  806. kdesc->insn + sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm));
  807. move_blob2blob(gen, insn + offsetof(struct bpf_insn, imm), 4,
  808. kdesc->insn + offsetof(struct bpf_insn, imm));
  809. /* jump over src_reg adjustment if imm (btf_id) is not 0, reuse BPF_REG_0 from move_blob2blob
  810. * If btf_id is zero, clear BPF_PSEUDO_BTF_ID flag in src_reg of ld_imm64 insn
  811. */
  812. emit(gen, BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 3));
  813. goto clear_src_reg;
  814. }
  815. /* remember insn offset, so we can copy BTF ID and FD later */
  816. kdesc->insn = insn;
  817. emit_bpf_find_by_name_kind(gen, relo);
  818. if (!relo->is_weak)
  819. emit_check_err(gen);
  820. /* jump to success case */
  821. emit(gen, BPF_JMP_IMM(BPF_JSGE, BPF_REG_7, 0, 3));
  822. /* set values for insn[insn_idx].imm, insn[insn_idx + 1].imm as 0 */
  823. emit(gen, BPF_ST_MEM(BPF_W, BPF_REG_8, offsetof(struct bpf_insn, imm), 0));
  824. emit(gen, BPF_ST_MEM(BPF_W, BPF_REG_8, sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm), 0));
  825. /* skip success case for ret < 0 */
  826. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 4));
  827. /* store btf_id into insn[insn_idx].imm */
  828. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7, offsetof(struct bpf_insn, imm)));
  829. /* store btf_obj_fd into insn[insn_idx + 1].imm */
  830. emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 32));
  831. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_8, BPF_REG_7,
  832. sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm)));
  833. /* skip src_reg adjustment */
  834. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 3));
  835. clear_src_reg:
  836. /* clear bpf_object__relocate_data's src_reg assignment, otherwise we get a verifier failure */
  837. reg_mask = src_reg_mask(gen);
  838. emit(gen, BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_8, offsetofend(struct bpf_insn, code)));
  839. emit(gen, BPF_ALU32_IMM(BPF_AND, BPF_REG_9, reg_mask));
  840. emit(gen, BPF_STX_MEM(BPF_B, BPF_REG_8, BPF_REG_9, offsetofend(struct bpf_insn, code)));
  841. emit_ksym_relo_log(gen, relo, kdesc->ref);
  842. }
  843. void bpf_gen__record_relo_core(struct bpf_gen *gen,
  844. const struct bpf_core_relo *core_relo)
  845. {
  846. struct bpf_core_relo *relos;
  847. relos = libbpf_reallocarray(gen->core_relos, gen->core_relo_cnt + 1, sizeof(*relos));
  848. if (!relos) {
  849. gen->error = -ENOMEM;
  850. return;
  851. }
  852. gen->core_relos = relos;
  853. relos += gen->core_relo_cnt;
  854. memcpy(relos, core_relo, sizeof(*relos));
  855. gen->core_relo_cnt++;
  856. }
  857. static void emit_relo(struct bpf_gen *gen, struct ksym_relo_desc *relo, int insns)
  858. {
  859. int insn;
  860. pr_debug("gen: emit_relo (%d): %s at %d %s\n",
  861. relo->kind, relo->name, relo->insn_idx, relo->is_ld64 ? "ld64" : "call");
  862. insn = insns + sizeof(struct bpf_insn) * relo->insn_idx;
  863. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_8, BPF_PSEUDO_MAP_IDX_VALUE, 0, 0, 0, insn));
  864. if (relo->is_ld64) {
  865. if (relo->is_typeless)
  866. emit_relo_ksym_typeless(gen, relo, insn);
  867. else
  868. emit_relo_ksym_btf(gen, relo, insn);
  869. } else {
  870. emit_relo_kfunc_btf(gen, relo, insn);
  871. }
  872. }
  873. static void emit_relos(struct bpf_gen *gen, int insns)
  874. {
  875. int i;
  876. for (i = 0; i < gen->relo_cnt; i++)
  877. emit_relo(gen, gen->relos + i, insns);
  878. }
  879. static void cleanup_core_relo(struct bpf_gen *gen)
  880. {
  881. if (!gen->core_relo_cnt)
  882. return;
  883. free(gen->core_relos);
  884. gen->core_relo_cnt = 0;
  885. gen->core_relos = NULL;
  886. }
  887. static void cleanup_relos(struct bpf_gen *gen, int insns)
  888. {
  889. struct ksym_desc *kdesc;
  890. int i, insn;
  891. for (i = 0; i < gen->nr_ksyms; i++) {
  892. kdesc = &gen->ksyms[i];
  893. /* only close fds for typed ksyms and kfuncs */
  894. if (kdesc->is_ld64 && !kdesc->typeless) {
  895. /* close fd recorded in insn[insn_idx + 1].imm */
  896. insn = kdesc->insn;
  897. insn += sizeof(struct bpf_insn) + offsetof(struct bpf_insn, imm);
  898. emit_sys_close_blob(gen, insn);
  899. } else if (!kdesc->is_ld64) {
  900. emit_sys_close_blob(gen, blob_fd_array_off(gen, kdesc->off));
  901. if (kdesc->off < MAX_FD_ARRAY_SZ)
  902. gen->nr_fd_array--;
  903. }
  904. }
  905. if (gen->nr_ksyms) {
  906. free(gen->ksyms);
  907. gen->nr_ksyms = 0;
  908. gen->ksyms = NULL;
  909. }
  910. if (gen->relo_cnt) {
  911. free(gen->relos);
  912. gen->relo_cnt = 0;
  913. gen->relos = NULL;
  914. }
  915. cleanup_core_relo(gen);
  916. }
  917. /* Convert func, line, and core relo info blobs to target endianness */
  918. static void info_blob_bswap(struct bpf_gen *gen, int func_info, int line_info,
  919. int core_relos, struct bpf_prog_load_opts *load_attr)
  920. {
  921. struct bpf_func_info *fi = gen->data_start + func_info;
  922. struct bpf_line_info *li = gen->data_start + line_info;
  923. struct bpf_core_relo *cr = gen->data_start + core_relos;
  924. int i;
  925. for (i = 0; i < load_attr->func_info_cnt; i++)
  926. bpf_func_info_bswap(fi++);
  927. for (i = 0; i < load_attr->line_info_cnt; i++)
  928. bpf_line_info_bswap(li++);
  929. for (i = 0; i < gen->core_relo_cnt; i++)
  930. bpf_core_relo_bswap(cr++);
  931. }
  932. void bpf_gen__prog_load(struct bpf_gen *gen,
  933. enum bpf_prog_type prog_type, const char *prog_name,
  934. const char *license, struct bpf_insn *insns, size_t insn_cnt,
  935. struct bpf_prog_load_opts *load_attr, int prog_idx)
  936. {
  937. int func_info_tot_sz = load_attr->func_info_cnt *
  938. load_attr->func_info_rec_size;
  939. int line_info_tot_sz = load_attr->line_info_cnt *
  940. load_attr->line_info_rec_size;
  941. int core_relo_tot_sz = gen->core_relo_cnt *
  942. sizeof(struct bpf_core_relo);
  943. int prog_load_attr, license_off, insns_off, func_info, line_info, core_relos;
  944. int attr_size = offsetofend(union bpf_attr, core_relo_rec_size);
  945. union bpf_attr attr;
  946. memset(&attr, 0, attr_size);
  947. /* add license string to blob of bytes */
  948. license_off = add_data(gen, license, strlen(license) + 1);
  949. /* add insns to blob of bytes */
  950. insns_off = add_data(gen, insns, insn_cnt * sizeof(struct bpf_insn));
  951. pr_debug("gen: prog_load: prog_idx %d type %d insn off %d insns_cnt %zd license off %d\n",
  952. prog_idx, prog_type, insns_off, insn_cnt, license_off);
  953. /* convert blob insns to target endianness */
  954. if (gen->swapped_endian) {
  955. struct bpf_insn *insn = gen->data_start + insns_off;
  956. int i;
  957. for (i = 0; i < insn_cnt; i++, insn++)
  958. bpf_insn_bswap(insn);
  959. }
  960. attr.prog_type = tgt_endian(prog_type);
  961. attr.expected_attach_type = tgt_endian(load_attr->expected_attach_type);
  962. attr.attach_btf_id = tgt_endian(load_attr->attach_btf_id);
  963. attr.prog_ifindex = tgt_endian(load_attr->prog_ifindex);
  964. attr.kern_version = 0;
  965. attr.insn_cnt = tgt_endian((__u32)insn_cnt);
  966. attr.prog_flags = tgt_endian(load_attr->prog_flags);
  967. attr.func_info_rec_size = tgt_endian(load_attr->func_info_rec_size);
  968. attr.func_info_cnt = tgt_endian(load_attr->func_info_cnt);
  969. func_info = add_data(gen, load_attr->func_info, func_info_tot_sz);
  970. pr_debug("gen: prog_load: func_info: off %d cnt %d rec size %d\n",
  971. func_info, load_attr->func_info_cnt,
  972. load_attr->func_info_rec_size);
  973. attr.line_info_rec_size = tgt_endian(load_attr->line_info_rec_size);
  974. attr.line_info_cnt = tgt_endian(load_attr->line_info_cnt);
  975. line_info = add_data(gen, load_attr->line_info, line_info_tot_sz);
  976. pr_debug("gen: prog_load: line_info: off %d cnt %d rec size %d\n",
  977. line_info, load_attr->line_info_cnt,
  978. load_attr->line_info_rec_size);
  979. attr.core_relo_rec_size = tgt_endian((__u32)sizeof(struct bpf_core_relo));
  980. attr.core_relo_cnt = tgt_endian(gen->core_relo_cnt);
  981. core_relos = add_data(gen, gen->core_relos, core_relo_tot_sz);
  982. pr_debug("gen: prog_load: core_relos: off %d cnt %d rec size %zd\n",
  983. core_relos, gen->core_relo_cnt,
  984. sizeof(struct bpf_core_relo));
  985. /* convert all info blobs to target endianness */
  986. if (gen->swapped_endian)
  987. info_blob_bswap(gen, func_info, line_info, core_relos, load_attr);
  988. libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
  989. prog_load_attr = add_data(gen, &attr, attr_size);
  990. pr_debug("gen: prog_load: attr: off %d size %d\n",
  991. prog_load_attr, attr_size);
  992. /* populate union bpf_attr with a pointer to license */
  993. emit_rel_store(gen, attr_field(prog_load_attr, license), license_off);
  994. /* populate union bpf_attr with a pointer to instructions */
  995. emit_rel_store(gen, attr_field(prog_load_attr, insns), insns_off);
  996. /* populate union bpf_attr with a pointer to func_info */
  997. emit_rel_store(gen, attr_field(prog_load_attr, func_info), func_info);
  998. /* populate union bpf_attr with a pointer to line_info */
  999. emit_rel_store(gen, attr_field(prog_load_attr, line_info), line_info);
  1000. /* populate union bpf_attr with a pointer to core_relos */
  1001. emit_rel_store(gen, attr_field(prog_load_attr, core_relos), core_relos);
  1002. /* populate union bpf_attr fd_array with a pointer to data where map_fds are saved */
  1003. emit_rel_store(gen, attr_field(prog_load_attr, fd_array), gen->fd_array);
  1004. /* populate union bpf_attr with user provided log details */
  1005. move_ctx2blob(gen, attr_field(prog_load_attr, log_level), 4,
  1006. offsetof(struct bpf_loader_ctx, log_level), false);
  1007. move_ctx2blob(gen, attr_field(prog_load_attr, log_size), 4,
  1008. offsetof(struct bpf_loader_ctx, log_size), false);
  1009. move_ctx2blob(gen, attr_field(prog_load_attr, log_buf), 8,
  1010. offsetof(struct bpf_loader_ctx, log_buf), false);
  1011. /* populate union bpf_attr with btf_fd saved in the stack earlier */
  1012. move_stack2blob(gen, attr_field(prog_load_attr, prog_btf_fd), 4,
  1013. stack_off(btf_fd));
  1014. if (gen->attach_kind) {
  1015. emit_find_attach_target(gen);
  1016. /* populate union bpf_attr with btf_id and btf_obj_fd found by helper */
  1017. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_0, BPF_PSEUDO_MAP_IDX_VALUE,
  1018. 0, 0, 0, prog_load_attr));
  1019. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
  1020. offsetof(union bpf_attr, attach_btf_id)));
  1021. emit(gen, BPF_ALU64_IMM(BPF_RSH, BPF_REG_7, 32));
  1022. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_0, BPF_REG_7,
  1023. offsetof(union bpf_attr, attach_btf_obj_fd)));
  1024. }
  1025. emit_relos(gen, insns_off);
  1026. /* emit PROG_LOAD command */
  1027. emit_sys_bpf(gen, BPF_PROG_LOAD, prog_load_attr, attr_size);
  1028. debug_ret(gen, "prog_load %s insn_cnt %d", attr.prog_name, attr.insn_cnt);
  1029. /* successful or not, close btf module FDs used in extern ksyms and attach_btf_obj_fd */
  1030. cleanup_relos(gen, insns_off);
  1031. if (gen->attach_kind) {
  1032. emit_sys_close_blob(gen,
  1033. attr_field(prog_load_attr, attach_btf_obj_fd));
  1034. gen->attach_kind = 0;
  1035. }
  1036. emit_check_err(gen);
  1037. /* remember prog_fd in the stack, if successful */
  1038. emit(gen, BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_7,
  1039. stack_off(prog_fd[gen->nr_progs])));
  1040. gen->nr_progs++;
  1041. }
  1042. void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *pvalue,
  1043. __u32 value_size)
  1044. {
  1045. int attr_size = offsetofend(union bpf_attr, flags);
  1046. int map_update_attr, value, key;
  1047. union bpf_attr attr;
  1048. int zero = 0;
  1049. memset(&attr, 0, attr_size);
  1050. value = add_data(gen, pvalue, value_size);
  1051. key = add_data(gen, &zero, sizeof(zero));
  1052. /* if (map_desc[map_idx].initial_value) {
  1053. * if (ctx->flags & BPF_SKEL_KERNEL)
  1054. * bpf_probe_read_kernel(value, value_size, initial_value);
  1055. * else
  1056. * bpf_copy_from_user(value, value_size, initial_value);
  1057. * }
  1058. */
  1059. emit(gen, BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_6,
  1060. sizeof(struct bpf_loader_ctx) +
  1061. sizeof(struct bpf_map_desc) * map_idx +
  1062. offsetof(struct bpf_map_desc, initial_value)));
  1063. emit(gen, BPF_JMP_IMM(BPF_JEQ, BPF_REG_3, 0, 8));
  1064. emit2(gen, BPF_LD_IMM64_RAW_FULL(BPF_REG_1, BPF_PSEUDO_MAP_IDX_VALUE,
  1065. 0, 0, 0, value));
  1066. emit(gen, BPF_MOV64_IMM(BPF_REG_2, value_size));
  1067. emit(gen, BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_6,
  1068. offsetof(struct bpf_loader_ctx, flags)));
  1069. emit(gen, BPF_JMP_IMM(BPF_JSET, BPF_REG_0, BPF_SKEL_KERNEL, 2));
  1070. emit(gen, BPF_EMIT_CALL(BPF_FUNC_copy_from_user));
  1071. emit(gen, BPF_JMP_IMM(BPF_JA, 0, 0, 1));
  1072. emit(gen, BPF_EMIT_CALL(BPF_FUNC_probe_read_kernel));
  1073. map_update_attr = add_data(gen, &attr, attr_size);
  1074. pr_debug("gen: map_update_elem: idx %d, value: off %d size %d, attr: off %d size %d\n",
  1075. map_idx, value, value_size, map_update_attr, attr_size);
  1076. move_blob2blob(gen, attr_field(map_update_attr, map_fd), 4,
  1077. blob_fd_array_off(gen, map_idx));
  1078. emit_rel_store(gen, attr_field(map_update_attr, key), key);
  1079. emit_rel_store(gen, attr_field(map_update_attr, value), value);
  1080. /* emit MAP_UPDATE_ELEM command */
  1081. emit_sys_bpf(gen, BPF_MAP_UPDATE_ELEM, map_update_attr, attr_size);
  1082. debug_ret(gen, "update_elem idx %d value_size %d", map_idx, value_size);
  1083. emit_check_err(gen);
  1084. }
  1085. void bpf_gen__populate_outer_map(struct bpf_gen *gen, int outer_map_idx, int slot,
  1086. int inner_map_idx)
  1087. {
  1088. int attr_size = offsetofend(union bpf_attr, flags);
  1089. int map_update_attr, key;
  1090. union bpf_attr attr;
  1091. int tgt_slot;
  1092. memset(&attr, 0, attr_size);
  1093. tgt_slot = tgt_endian(slot);
  1094. key = add_data(gen, &tgt_slot, sizeof(tgt_slot));
  1095. map_update_attr = add_data(gen, &attr, attr_size);
  1096. pr_debug("gen: populate_outer_map: outer %d key %d inner %d, attr: off %d size %d\n",
  1097. outer_map_idx, slot, inner_map_idx, map_update_attr, attr_size);
  1098. move_blob2blob(gen, attr_field(map_update_attr, map_fd), 4,
  1099. blob_fd_array_off(gen, outer_map_idx));
  1100. emit_rel_store(gen, attr_field(map_update_attr, key), key);
  1101. emit_rel_store(gen, attr_field(map_update_attr, value),
  1102. blob_fd_array_off(gen, inner_map_idx));
  1103. /* emit MAP_UPDATE_ELEM command */
  1104. emit_sys_bpf(gen, BPF_MAP_UPDATE_ELEM, map_update_attr, attr_size);
  1105. debug_ret(gen, "populate_outer_map outer %d key %d inner %d",
  1106. outer_map_idx, slot, inner_map_idx);
  1107. emit_check_err(gen);
  1108. }
  1109. void bpf_gen__map_freeze(struct bpf_gen *gen, int map_idx)
  1110. {
  1111. int attr_size = offsetofend(union bpf_attr, map_fd);
  1112. int map_freeze_attr;
  1113. union bpf_attr attr;
  1114. memset(&attr, 0, attr_size);
  1115. map_freeze_attr = add_data(gen, &attr, attr_size);
  1116. pr_debug("gen: map_freeze: idx %d, attr: off %d size %d\n",
  1117. map_idx, map_freeze_attr, attr_size);
  1118. move_blob2blob(gen, attr_field(map_freeze_attr, map_fd), 4,
  1119. blob_fd_array_off(gen, map_idx));
  1120. /* emit MAP_FREEZE command */
  1121. emit_sys_bpf(gen, BPF_MAP_FREEZE, map_freeze_attr, attr_size);
  1122. debug_ret(gen, "map_freeze");
  1123. emit_check_err(gen);
  1124. }