cgroup.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. /*
  2. * Functions to manage eBPF programs attached to cgroups
  3. *
  4. * Copyright (c) 2016 Daniel Mack
  5. *
  6. * This file is subject to the terms and conditions of version 2 of the GNU
  7. * General Public License. See the file COPYING in the main directory of the
  8. * Linux distribution for more details.
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/atomic.h>
  12. #include <linux/cgroup.h>
  13. #include <linux/slab.h>
  14. #include <linux/bpf.h>
  15. #include <linux/bpf-cgroup.h>
  16. #include <net/sock.h>
  17. DEFINE_STATIC_KEY_FALSE(cgroup_bpf_enabled_key);
  18. EXPORT_SYMBOL(cgroup_bpf_enabled_key);
  19. /**
  20. * cgroup_bpf_put() - put references of all bpf programs
  21. * @cgrp: the cgroup to modify
  22. */
  23. void cgroup_bpf_put(struct cgroup *cgrp)
  24. {
  25. unsigned int type;
  26. for (type = 0; type < ARRAY_SIZE(cgrp->bpf.progs); type++) {
  27. struct list_head *progs = &cgrp->bpf.progs[type];
  28. struct bpf_prog_list *pl, *tmp;
  29. list_for_each_entry_safe(pl, tmp, progs, node) {
  30. list_del(&pl->node);
  31. bpf_prog_put(pl->prog);
  32. kfree(pl);
  33. static_branch_dec(&cgroup_bpf_enabled_key);
  34. }
  35. bpf_prog_array_free(cgrp->bpf.effective[type]);
  36. }
  37. }
  38. /* count number of elements in the list.
  39. * it's slow but the list cannot be long
  40. */
  41. static u32 prog_list_length(struct list_head *head)
  42. {
  43. struct bpf_prog_list *pl;
  44. u32 cnt = 0;
  45. list_for_each_entry(pl, head, node) {
  46. if (!pl->prog)
  47. continue;
  48. cnt++;
  49. }
  50. return cnt;
  51. }
  52. /* if parent has non-overridable prog attached,
  53. * disallow attaching new programs to the descendent cgroup.
  54. * if parent has overridable or multi-prog, allow attaching
  55. */
  56. static bool hierarchy_allows_attach(struct cgroup *cgrp,
  57. enum bpf_attach_type type,
  58. u32 new_flags)
  59. {
  60. struct cgroup *p;
  61. p = cgroup_parent(cgrp);
  62. if (!p)
  63. return true;
  64. do {
  65. u32 flags = p->bpf.flags[type];
  66. u32 cnt;
  67. if (flags & BPF_F_ALLOW_MULTI)
  68. return true;
  69. cnt = prog_list_length(&p->bpf.progs[type]);
  70. WARN_ON_ONCE(cnt > 1);
  71. if (cnt == 1)
  72. return !!(flags & BPF_F_ALLOW_OVERRIDE);
  73. p = cgroup_parent(p);
  74. } while (p);
  75. return true;
  76. }
  77. /* compute a chain of effective programs for a given cgroup:
  78. * start from the list of programs in this cgroup and add
  79. * all parent programs.
  80. * Note that parent's F_ALLOW_OVERRIDE-type program is yielding
  81. * to programs in this cgroup
  82. */
  83. static int compute_effective_progs(struct cgroup *cgrp,
  84. enum bpf_attach_type type,
  85. struct bpf_prog_array __rcu **array)
  86. {
  87. struct bpf_prog_array *progs;
  88. struct bpf_prog_list *pl;
  89. struct cgroup *p = cgrp;
  90. int cnt = 0;
  91. /* count number of effective programs by walking parents */
  92. do {
  93. if (cnt == 0 || (p->bpf.flags[type] & BPF_F_ALLOW_MULTI))
  94. cnt += prog_list_length(&p->bpf.progs[type]);
  95. p = cgroup_parent(p);
  96. } while (p);
  97. progs = bpf_prog_array_alloc(cnt, GFP_KERNEL);
  98. if (!progs)
  99. return -ENOMEM;
  100. /* populate the array with effective progs */
  101. cnt = 0;
  102. p = cgrp;
  103. do {
  104. if (cnt == 0 || (p->bpf.flags[type] & BPF_F_ALLOW_MULTI))
  105. list_for_each_entry(pl,
  106. &p->bpf.progs[type], node) {
  107. if (!pl->prog)
  108. continue;
  109. progs->progs[cnt++] = pl->prog;
  110. }
  111. p = cgroup_parent(p);
  112. } while (p);
  113. rcu_assign_pointer(*array, progs);
  114. return 0;
  115. }
  116. static void activate_effective_progs(struct cgroup *cgrp,
  117. enum bpf_attach_type type,
  118. struct bpf_prog_array __rcu *array)
  119. {
  120. struct bpf_prog_array __rcu *old_array;
  121. old_array = xchg(&cgrp->bpf.effective[type], array);
  122. /* free prog array after grace period, since __cgroup_bpf_run_*()
  123. * might be still walking the array
  124. */
  125. bpf_prog_array_free(old_array);
  126. }
  127. /**
  128. * cgroup_bpf_inherit() - inherit effective programs from parent
  129. * @cgrp: the cgroup to modify
  130. */
  131. int cgroup_bpf_inherit(struct cgroup *cgrp)
  132. {
  133. /* has to use marco instead of const int, since compiler thinks
  134. * that array below is variable length
  135. */
  136. #define NR ARRAY_SIZE(cgrp->bpf.effective)
  137. struct bpf_prog_array __rcu *arrays[NR] = {};
  138. int i;
  139. for (i = 0; i < NR; i++)
  140. INIT_LIST_HEAD(&cgrp->bpf.progs[i]);
  141. for (i = 0; i < NR; i++)
  142. if (compute_effective_progs(cgrp, i, &arrays[i]))
  143. goto cleanup;
  144. for (i = 0; i < NR; i++)
  145. activate_effective_progs(cgrp, i, arrays[i]);
  146. return 0;
  147. cleanup:
  148. for (i = 0; i < NR; i++)
  149. bpf_prog_array_free(arrays[i]);
  150. return -ENOMEM;
  151. }
  152. #define BPF_CGROUP_MAX_PROGS 64
  153. /**
  154. * __cgroup_bpf_attach() - Attach the program to a cgroup, and
  155. * propagate the change to descendants
  156. * @cgrp: The cgroup which descendants to traverse
  157. * @prog: A program to attach
  158. * @type: Type of attach operation
  159. *
  160. * Must be called with cgroup_mutex held.
  161. */
  162. int __cgroup_bpf_attach(struct cgroup *cgrp, struct bpf_prog *prog,
  163. enum bpf_attach_type type, u32 flags)
  164. {
  165. struct list_head *progs = &cgrp->bpf.progs[type];
  166. struct bpf_prog *old_prog = NULL;
  167. struct cgroup_subsys_state *css;
  168. struct bpf_prog_list *pl;
  169. bool pl_was_allocated;
  170. int err;
  171. if ((flags & BPF_F_ALLOW_OVERRIDE) && (flags & BPF_F_ALLOW_MULTI))
  172. /* invalid combination */
  173. return -EINVAL;
  174. if (!hierarchy_allows_attach(cgrp, type, flags))
  175. return -EPERM;
  176. if (!list_empty(progs) && cgrp->bpf.flags[type] != flags)
  177. /* Disallow attaching non-overridable on top
  178. * of existing overridable in this cgroup.
  179. * Disallow attaching multi-prog if overridable or none
  180. */
  181. return -EPERM;
  182. if (prog_list_length(progs) >= BPF_CGROUP_MAX_PROGS)
  183. return -E2BIG;
  184. if (flags & BPF_F_ALLOW_MULTI) {
  185. list_for_each_entry(pl, progs, node)
  186. if (pl->prog == prog)
  187. /* disallow attaching the same prog twice */
  188. return -EINVAL;
  189. pl = kmalloc(sizeof(*pl), GFP_KERNEL);
  190. if (!pl)
  191. return -ENOMEM;
  192. pl_was_allocated = true;
  193. pl->prog = prog;
  194. list_add_tail(&pl->node, progs);
  195. } else {
  196. if (list_empty(progs)) {
  197. pl = kmalloc(sizeof(*pl), GFP_KERNEL);
  198. if (!pl)
  199. return -ENOMEM;
  200. pl_was_allocated = true;
  201. list_add_tail(&pl->node, progs);
  202. } else {
  203. pl = list_first_entry(progs, typeof(*pl), node);
  204. old_prog = pl->prog;
  205. pl_was_allocated = false;
  206. }
  207. pl->prog = prog;
  208. }
  209. cgrp->bpf.flags[type] = flags;
  210. /* allocate and recompute effective prog arrays */
  211. css_for_each_descendant_pre(css, &cgrp->self) {
  212. struct cgroup *desc = container_of(css, struct cgroup, self);
  213. err = compute_effective_progs(desc, type, &desc->bpf.inactive);
  214. if (err)
  215. goto cleanup;
  216. }
  217. /* all allocations were successful. Activate all prog arrays */
  218. css_for_each_descendant_pre(css, &cgrp->self) {
  219. struct cgroup *desc = container_of(css, struct cgroup, self);
  220. activate_effective_progs(desc, type, desc->bpf.inactive);
  221. desc->bpf.inactive = NULL;
  222. }
  223. static_branch_inc(&cgroup_bpf_enabled_key);
  224. if (old_prog) {
  225. bpf_prog_put(old_prog);
  226. static_branch_dec(&cgroup_bpf_enabled_key);
  227. }
  228. return 0;
  229. cleanup:
  230. /* oom while computing effective. Free all computed effective arrays
  231. * since they were not activated
  232. */
  233. css_for_each_descendant_pre(css, &cgrp->self) {
  234. struct cgroup *desc = container_of(css, struct cgroup, self);
  235. bpf_prog_array_free(desc->bpf.inactive);
  236. desc->bpf.inactive = NULL;
  237. }
  238. /* and cleanup the prog list */
  239. pl->prog = old_prog;
  240. if (pl_was_allocated) {
  241. list_del(&pl->node);
  242. kfree(pl);
  243. }
  244. return err;
  245. }
  246. /**
  247. * __cgroup_bpf_detach() - Detach the program from a cgroup, and
  248. * propagate the change to descendants
  249. * @cgrp: The cgroup which descendants to traverse
  250. * @prog: A program to detach or NULL
  251. * @type: Type of detach operation
  252. *
  253. * Must be called with cgroup_mutex held.
  254. */
  255. int __cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,
  256. enum bpf_attach_type type, u32 unused_flags)
  257. {
  258. struct list_head *progs = &cgrp->bpf.progs[type];
  259. u32 flags = cgrp->bpf.flags[type];
  260. struct bpf_prog *old_prog = NULL;
  261. struct cgroup_subsys_state *css;
  262. struct bpf_prog_list *pl;
  263. int err;
  264. if (flags & BPF_F_ALLOW_MULTI) {
  265. if (!prog)
  266. /* to detach MULTI prog the user has to specify valid FD
  267. * of the program to be detached
  268. */
  269. return -EINVAL;
  270. } else {
  271. if (list_empty(progs))
  272. /* report error when trying to detach and nothing is attached */
  273. return -ENOENT;
  274. }
  275. if (flags & BPF_F_ALLOW_MULTI) {
  276. /* find the prog and detach it */
  277. list_for_each_entry(pl, progs, node) {
  278. if (pl->prog != prog)
  279. continue;
  280. old_prog = prog;
  281. /* mark it deleted, so it's ignored while
  282. * recomputing effective
  283. */
  284. pl->prog = NULL;
  285. break;
  286. }
  287. if (!old_prog)
  288. return -ENOENT;
  289. } else {
  290. /* to maintain backward compatibility NONE and OVERRIDE cgroups
  291. * allow detaching with invalid FD (prog==NULL)
  292. */
  293. pl = list_first_entry(progs, typeof(*pl), node);
  294. old_prog = pl->prog;
  295. pl->prog = NULL;
  296. }
  297. /* allocate and recompute effective prog arrays */
  298. css_for_each_descendant_pre(css, &cgrp->self) {
  299. struct cgroup *desc = container_of(css, struct cgroup, self);
  300. err = compute_effective_progs(desc, type, &desc->bpf.inactive);
  301. if (err)
  302. goto cleanup;
  303. }
  304. /* all allocations were successful. Activate all prog arrays */
  305. css_for_each_descendant_pre(css, &cgrp->self) {
  306. struct cgroup *desc = container_of(css, struct cgroup, self);
  307. activate_effective_progs(desc, type, desc->bpf.inactive);
  308. desc->bpf.inactive = NULL;
  309. }
  310. /* now can actually delete it from this cgroup list */
  311. list_del(&pl->node);
  312. kfree(pl);
  313. if (list_empty(progs))
  314. /* last program was detached, reset flags to zero */
  315. cgrp->bpf.flags[type] = 0;
  316. bpf_prog_put(old_prog);
  317. static_branch_dec(&cgroup_bpf_enabled_key);
  318. return 0;
  319. cleanup:
  320. /* oom while computing effective. Free all computed effective arrays
  321. * since they were not activated
  322. */
  323. css_for_each_descendant_pre(css, &cgrp->self) {
  324. struct cgroup *desc = container_of(css, struct cgroup, self);
  325. bpf_prog_array_free(desc->bpf.inactive);
  326. desc->bpf.inactive = NULL;
  327. }
  328. /* and restore back old_prog */
  329. pl->prog = old_prog;
  330. return err;
  331. }
  332. /* Must be called with cgroup_mutex held to avoid races. */
  333. int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,
  334. union bpf_attr __user *uattr)
  335. {
  336. __u32 __user *prog_ids = u64_to_user_ptr(attr->query.prog_ids);
  337. enum bpf_attach_type type = attr->query.attach_type;
  338. struct list_head *progs = &cgrp->bpf.progs[type];
  339. u32 flags = cgrp->bpf.flags[type];
  340. int cnt, ret = 0, i;
  341. if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE)
  342. cnt = bpf_prog_array_length(cgrp->bpf.effective[type]);
  343. else
  344. cnt = prog_list_length(progs);
  345. if (copy_to_user(&uattr->query.attach_flags, &flags, sizeof(flags)))
  346. return -EFAULT;
  347. if (copy_to_user(&uattr->query.prog_cnt, &cnt, sizeof(cnt)))
  348. return -EFAULT;
  349. if (attr->query.prog_cnt == 0 || !prog_ids || !cnt)
  350. /* return early if user requested only program count + flags */
  351. return 0;
  352. if (attr->query.prog_cnt < cnt) {
  353. cnt = attr->query.prog_cnt;
  354. ret = -ENOSPC;
  355. }
  356. if (attr->query.query_flags & BPF_F_QUERY_EFFECTIVE) {
  357. return bpf_prog_array_copy_to_user(cgrp->bpf.effective[type],
  358. prog_ids, cnt);
  359. } else {
  360. struct bpf_prog_list *pl;
  361. u32 id;
  362. i = 0;
  363. list_for_each_entry(pl, progs, node) {
  364. id = pl->prog->aux->id;
  365. if (copy_to_user(prog_ids + i, &id, sizeof(id)))
  366. return -EFAULT;
  367. if (++i == cnt)
  368. break;
  369. }
  370. }
  371. return ret;
  372. }
  373. int cgroup_bpf_prog_attach(const union bpf_attr *attr,
  374. enum bpf_prog_type ptype, struct bpf_prog *prog)
  375. {
  376. struct cgroup *cgrp;
  377. int ret;
  378. cgrp = cgroup_get_from_fd(attr->target_fd);
  379. if (IS_ERR(cgrp))
  380. return PTR_ERR(cgrp);
  381. ret = cgroup_bpf_attach(cgrp, prog, attr->attach_type,
  382. attr->attach_flags);
  383. cgroup_put(cgrp);
  384. return ret;
  385. }
  386. int cgroup_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype)
  387. {
  388. struct bpf_prog *prog;
  389. struct cgroup *cgrp;
  390. int ret;
  391. cgrp = cgroup_get_from_fd(attr->target_fd);
  392. if (IS_ERR(cgrp))
  393. return PTR_ERR(cgrp);
  394. prog = bpf_prog_get_type(attr->attach_bpf_fd, ptype);
  395. if (IS_ERR(prog))
  396. prog = NULL;
  397. ret = cgroup_bpf_detach(cgrp, prog, attr->attach_type, 0);
  398. if (prog)
  399. bpf_prog_put(prog);
  400. cgroup_put(cgrp);
  401. return ret;
  402. }
  403. int cgroup_bpf_prog_query(const union bpf_attr *attr,
  404. union bpf_attr __user *uattr)
  405. {
  406. struct cgroup *cgrp;
  407. int ret;
  408. cgrp = cgroup_get_from_fd(attr->query.target_fd);
  409. if (IS_ERR(cgrp))
  410. return PTR_ERR(cgrp);
  411. ret = cgroup_bpf_query(cgrp, attr, uattr);
  412. cgroup_put(cgrp);
  413. return ret;
  414. }
  415. /**
  416. * __cgroup_bpf_run_filter_skb() - Run a program for packet filtering
  417. * @sk: The socket sending or receiving traffic
  418. * @skb: The skb that is being sent or received
  419. * @type: The type of program to be exectuted
  420. *
  421. * If no socket is passed, or the socket is not of type INET or INET6,
  422. * this function does nothing and returns 0.
  423. *
  424. * The program type passed in via @type must be suitable for network
  425. * filtering. No further check is performed to assert that.
  426. *
  427. * This function will return %-EPERM if any if an attached program was found
  428. * and if it returned != 1 during execution. In all other cases, 0 is returned.
  429. */
  430. int __cgroup_bpf_run_filter_skb(struct sock *sk,
  431. struct sk_buff *skb,
  432. enum bpf_attach_type type)
  433. {
  434. unsigned int offset = skb->data - skb_network_header(skb);
  435. struct sock *save_sk;
  436. struct cgroup *cgrp;
  437. int ret;
  438. if (!sk || !sk_fullsock(sk))
  439. return 0;
  440. if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
  441. return 0;
  442. cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
  443. save_sk = skb->sk;
  444. skb->sk = sk;
  445. __skb_push(skb, offset);
  446. ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], skb,
  447. bpf_prog_run_save_cb);
  448. __skb_pull(skb, offset);
  449. skb->sk = save_sk;
  450. return ret == 1 ? 0 : -EPERM;
  451. }
  452. EXPORT_SYMBOL(__cgroup_bpf_run_filter_skb);
  453. /**
  454. * __cgroup_bpf_run_filter_sk() - Run a program on a sock
  455. * @sk: sock structure to manipulate
  456. * @type: The type of program to be exectuted
  457. *
  458. * socket is passed is expected to be of type INET or INET6.
  459. *
  460. * The program type passed in via @type must be suitable for sock
  461. * filtering. No further check is performed to assert that.
  462. *
  463. * This function will return %-EPERM if any if an attached program was found
  464. * and if it returned != 1 during execution. In all other cases, 0 is returned.
  465. */
  466. int __cgroup_bpf_run_filter_sk(struct sock *sk,
  467. enum bpf_attach_type type)
  468. {
  469. struct cgroup *cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
  470. int ret;
  471. ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], sk, BPF_PROG_RUN);
  472. return ret == 1 ? 0 : -EPERM;
  473. }
  474. EXPORT_SYMBOL(__cgroup_bpf_run_filter_sk);
  475. /**
  476. * __cgroup_bpf_run_filter_sock_addr() - Run a program on a sock and
  477. * provided by user sockaddr
  478. * @sk: sock struct that will use sockaddr
  479. * @uaddr: sockaddr struct provided by user
  480. * @type: The type of program to be exectuted
  481. * @t_ctx: Pointer to attach type specific context
  482. *
  483. * socket is expected to be of type INET or INET6.
  484. *
  485. * This function will return %-EPERM if an attached program is found and
  486. * returned value != 1 during execution. In all other cases, 0 is returned.
  487. */
  488. int __cgroup_bpf_run_filter_sock_addr(struct sock *sk,
  489. struct sockaddr *uaddr,
  490. enum bpf_attach_type type,
  491. void *t_ctx)
  492. {
  493. struct bpf_sock_addr_kern ctx = {
  494. .sk = sk,
  495. .uaddr = uaddr,
  496. .t_ctx = t_ctx,
  497. };
  498. struct sockaddr_storage unspec;
  499. struct cgroup *cgrp;
  500. int ret;
  501. /* Check socket family since not all sockets represent network
  502. * endpoint (e.g. AF_UNIX).
  503. */
  504. if (sk->sk_family != AF_INET && sk->sk_family != AF_INET6)
  505. return 0;
  506. if (!ctx.uaddr) {
  507. memset(&unspec, 0, sizeof(unspec));
  508. ctx.uaddr = (struct sockaddr *)&unspec;
  509. }
  510. cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
  511. ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], &ctx, BPF_PROG_RUN);
  512. return ret == 1 ? 0 : -EPERM;
  513. }
  514. EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_addr);
  515. /**
  516. * __cgroup_bpf_run_filter_sock_ops() - Run a program on a sock
  517. * @sk: socket to get cgroup from
  518. * @sock_ops: bpf_sock_ops_kern struct to pass to program. Contains
  519. * sk with connection information (IP addresses, etc.) May not contain
  520. * cgroup info if it is a req sock.
  521. * @type: The type of program to be exectuted
  522. *
  523. * socket passed is expected to be of type INET or INET6.
  524. *
  525. * The program type passed in via @type must be suitable for sock_ops
  526. * filtering. No further check is performed to assert that.
  527. *
  528. * This function will return %-EPERM if any if an attached program was found
  529. * and if it returned != 1 during execution. In all other cases, 0 is returned.
  530. */
  531. int __cgroup_bpf_run_filter_sock_ops(struct sock *sk,
  532. struct bpf_sock_ops_kern *sock_ops,
  533. enum bpf_attach_type type)
  534. {
  535. struct cgroup *cgrp = sock_cgroup_ptr(&sk->sk_cgrp_data);
  536. int ret;
  537. ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], sock_ops,
  538. BPF_PROG_RUN);
  539. return ret == 1 ? 0 : -EPERM;
  540. }
  541. EXPORT_SYMBOL(__cgroup_bpf_run_filter_sock_ops);
  542. int __cgroup_bpf_check_dev_permission(short dev_type, u32 major, u32 minor,
  543. short access, enum bpf_attach_type type)
  544. {
  545. struct cgroup *cgrp;
  546. struct bpf_cgroup_dev_ctx ctx = {
  547. .access_type = (access << 16) | dev_type,
  548. .major = major,
  549. .minor = minor,
  550. };
  551. int allow = 1;
  552. rcu_read_lock();
  553. cgrp = task_dfl_cgroup(current);
  554. allow = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], &ctx,
  555. BPF_PROG_RUN);
  556. rcu_read_unlock();
  557. return !allow;
  558. }
  559. EXPORT_SYMBOL(__cgroup_bpf_check_dev_permission);
  560. static const struct bpf_func_proto *
  561. cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
  562. {
  563. switch (func_id) {
  564. case BPF_FUNC_map_lookup_elem:
  565. return &bpf_map_lookup_elem_proto;
  566. case BPF_FUNC_map_update_elem:
  567. return &bpf_map_update_elem_proto;
  568. case BPF_FUNC_map_delete_elem:
  569. return &bpf_map_delete_elem_proto;
  570. case BPF_FUNC_get_current_uid_gid:
  571. return &bpf_get_current_uid_gid_proto;
  572. case BPF_FUNC_trace_printk:
  573. if (capable(CAP_SYS_ADMIN))
  574. return bpf_get_trace_printk_proto();
  575. default:
  576. return NULL;
  577. }
  578. }
  579. static bool cgroup_dev_is_valid_access(int off, int size,
  580. enum bpf_access_type type,
  581. const struct bpf_prog *prog,
  582. struct bpf_insn_access_aux *info)
  583. {
  584. const int size_default = sizeof(__u32);
  585. if (type == BPF_WRITE)
  586. return false;
  587. if (off < 0 || off + size > sizeof(struct bpf_cgroup_dev_ctx))
  588. return false;
  589. /* The verifier guarantees that size > 0. */
  590. if (off % size != 0)
  591. return false;
  592. switch (off) {
  593. case bpf_ctx_range(struct bpf_cgroup_dev_ctx, access_type):
  594. bpf_ctx_record_field_size(info, size_default);
  595. if (!bpf_ctx_narrow_access_ok(off, size, size_default))
  596. return false;
  597. break;
  598. default:
  599. if (size != size_default)
  600. return false;
  601. }
  602. return true;
  603. }
  604. const struct bpf_prog_ops cg_dev_prog_ops = {
  605. };
  606. const struct bpf_verifier_ops cg_dev_verifier_ops = {
  607. .get_func_proto = cgroup_dev_func_proto,
  608. .is_valid_access = cgroup_dev_is_valid_access,
  609. };