LCOV - code coverage report
Current view: top level - bpfilter/cgen/prog - link.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 114 0
Test Date: 2025-02-26 17:59:59 Functions: 0.0 % 14 0

            Line data    Source code
       1              : // SPDX-License-Identifier: GPL-2.0-only
       2              : /*
       3              :  * Copyright (c) 2022 Meta Platforms, Inc. and affiliates.
       4              :  */
       5              : 
       6              : #include "bpfilter/cgen/prog/link.h"
       7              : 
       8              : #include <linux/bpf.h>
       9              : 
      10              : #include <errno.h>
      11              : #include <fcntl.h>
      12              : #include <stdio.h>
      13              : #include <stdlib.h>
      14              : #include <string.h>
      15              : #include <unistd.h>
      16              : 
      17              : #include "core/bpf.h"
      18              : #include "core/dump.h"
      19              : #include "core/helper.h"
      20              : #include "core/hook.h"
      21              : #include "core/logger.h"
      22              : #include "core/marsh.h"
      23              : #include "core/nf.h"
      24              : 
      25            0 : int bf_link_new(struct bf_link **link, const char *name, enum bf_hook hook)
      26              : {
      27            0 :     _cleanup_bf_link_ struct bf_link *_link = NULL;
      28              : 
      29            0 :     bf_assert(link && name);
      30            0 :     bf_assert(name[0] != '\0');
      31              : 
      32            0 :     _link = malloc(sizeof(*_link));
      33            0 :     if (!_link)
      34              :         return -ENOMEM;
      35              : 
      36              :     // snprintf() will write the \0 as part of the BPF_OBJ_NAME_LEN bytes
      37            0 :     (void)snprintf(_link->name, BPF_OBJ_NAME_LEN, name);
      38              : 
      39            0 :     _link->fd = -1;
      40            0 :     _link->hook = hook;
      41              : 
      42            0 :     *link = TAKE_PTR(_link);
      43              : 
      44            0 :     return 0;
      45              : }
      46              : 
      47            0 : int bf_link_new_from_marsh(struct bf_link **link, int dir_fd,
      48              :                            const struct bf_marsh *marsh)
      49              : {
      50            0 :     _cleanup_bf_link_ struct bf_link *_link = NULL;
      51              :     struct bf_marsh *elem = NULL;
      52              :     int r;
      53              : 
      54            0 :     bf_assert(link && marsh);
      55              : 
      56            0 :     _link = malloc(sizeof(*_link));
      57            0 :     if (!_link)
      58              :         return -ENOMEM;
      59              : 
      60            0 :     _link->fd = -1;
      61              : 
      62            0 :     if (!(elem = bf_marsh_next_child(marsh, elem)))
      63              :         return -EINVAL;
      64            0 :     memcpy(&_link->name, elem->data, BPF_OBJ_NAME_LEN);
      65              : 
      66            0 :     if (!(elem = bf_marsh_next_child(marsh, elem)))
      67              :         return -EINVAL;
      68            0 :     memcpy(&_link->hook, elem->data, sizeof(_link->hook));
      69              : 
      70            0 :     if (bf_marsh_next_child(marsh, elem))
      71            0 :         return bf_err_r(-E2BIG, "too many elements in bf_link marsh");
      72              : 
      73            0 :     if (dir_fd != -1) {
      74            0 :         r = bf_bpf_obj_get(_link->name, dir_fd, &_link->fd);
      75            0 :         if (r) {
      76            0 :             return bf_err_r(r, "failed to open pinned BPF link '%s'",
      77              :                             _link->name);
      78              :         }
      79              :     }
      80              : 
      81            0 :     *link = TAKE_PTR(_link);
      82              : 
      83            0 :     return 0;
      84              : }
      85              : 
      86            0 : void bf_link_free(struct bf_link **link)
      87              : {
      88            0 :     bf_assert(link);
      89              : 
      90            0 :     if (!*link)
      91              :         return;
      92              : 
      93              :     closep(&(*link)->fd);
      94              :     freep((void *)link);
      95              : }
      96              : 
      97            0 : int bf_link_marsh(const struct bf_link *link, struct bf_marsh **marsh)
      98              : {
      99            0 :     _cleanup_bf_marsh_ struct bf_marsh *_marsh = NULL;
     100              :     int r;
     101              : 
     102            0 :     bf_assert(link && marsh);
     103              : 
     104            0 :     r = bf_marsh_new(&_marsh, NULL, 0);
     105            0 :     if (r)
     106              :         return r;
     107              : 
     108            0 :     r = bf_marsh_add_child_raw(&_marsh, &link->name, BPF_OBJ_NAME_LEN);
     109            0 :     if (r)
     110              :         return r;
     111              : 
     112            0 :     r = bf_marsh_add_child_raw(&_marsh, &link->hook, sizeof(link->hook));
     113            0 :     if (r)
     114              :         return r;
     115              : 
     116            0 :     *marsh = TAKE_PTR(_marsh);
     117              : 
     118            0 :     return 0;
     119              : }
     120              : 
     121            0 : void bf_link_dump(const struct bf_link *link, prefix_t *prefix)
     122              : {
     123            0 :     bf_assert(link && prefix);
     124              : 
     125            0 :     DUMP(prefix, "struct bf_link at %p", link);
     126              : 
     127            0 :     bf_dump_prefix_push(prefix);
     128            0 :     DUMP(prefix, "name: %s", link->name);
     129            0 :     DUMP(prefix, "fd: %d", link->fd);
     130            0 :     DUMP(bf_dump_prefix_last(prefix), "hook: %s", bf_hook_to_str(link->hook));
     131            0 :     bf_dump_prefix_pop(prefix);
     132            0 : }
     133              : 
     134            0 : int bf_link_attach_xdp(struct bf_link *link, int prog_fd, unsigned int ifindex,
     135              :                        enum bf_xdp_attach_mode mode)
     136              : {
     137            0 :     union bpf_attr attr = {
     138              :         .link_create =
     139              :             {
     140              :                 .prog_fd = prog_fd,
     141              :                 .target_fd = ifindex,
     142              :                 .attach_type = BPF_XDP,
     143              :                 .flags = mode,
     144              :             },
     145              :     };
     146              :     int r;
     147              : 
     148            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     149            0 :     if (r < 0)
     150              :         return r;
     151              : 
     152            0 :     link->fd = r;
     153              : 
     154            0 :     return 0;
     155              : }
     156              : 
     157            0 : int bf_link_attach_tc(struct bf_link *link, int prog_fd, unsigned int ifindex)
     158              : {
     159            0 :     union bpf_attr attr = {
     160              :         .link_create =
     161              :             {
     162              :                 .prog_fd = prog_fd,
     163              :                 .target_fd = ifindex,
     164            0 :                 .attach_type = bf_hook_to_attach_type(link->hook),
     165              :             },
     166              :     };
     167              :     int r;
     168              : 
     169            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     170            0 :     if (r < 0)
     171              :         return r;
     172              : 
     173            0 :     link->fd = r;
     174              : 
     175            0 :     return 0;
     176              : }
     177              : 
     178            0 : int bf_link_attach_nf(struct bf_link *link, int prog_fd, unsigned int family,
     179              :                       int priority)
     180              : {
     181            0 :     union bpf_attr attr = {
     182              :         .link_create =
     183              :             {
     184              :                 .prog_fd = prog_fd,
     185              :                 .attach_type = BPF_NETFILTER,
     186              :                 .netfilter =
     187              :                     {
     188              :                         .pf = family,
     189            0 :                         .hooknum = bf_hook_to_nf_hook(link->hook),
     190              :                         .priority = priority,
     191              :                     },
     192              :             },
     193              :     };
     194              :     int r;
     195              : 
     196            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     197            0 :     if (r < 0)
     198              :         return r;
     199              : 
     200            0 :     link->fd = r;
     201              : 
     202            0 :     return 0;
     203              : }
     204              : 
     205            0 : int bf_link_attach_cgroup(struct bf_link *link, int prog_fd,
     206              :                           const char *cgroup_path)
     207              : {
     208              :     _cleanup_close_ int cgroup_fd = -1;
     209            0 :     union bpf_attr attr = {
     210              :         .link_create =
     211              :             {
     212              :                 .prog_fd = prog_fd,
     213            0 :                 .attach_type = bf_hook_to_attach_type(link->hook),
     214              :             },
     215              :     };
     216              :     int r;
     217              : 
     218            0 :     cgroup_fd = open(cgroup_path, O_DIRECTORY | O_RDONLY);
     219            0 :     if (cgroup_fd < 0)
     220            0 :         return bf_err_r(errno, "failed to open cgroup '%s'", cgroup_path);
     221              : 
     222            0 :     attr.link_create.target_fd = cgroup_fd;
     223              : 
     224            0 :     r = bf_bpf(BPF_LINK_CREATE, &attr);
     225            0 :     if (r < 0)
     226              :         return r;
     227              : 
     228            0 :     link->fd = r;
     229              : 
     230            0 :     return 0;
     231              : }
     232              : 
     233            0 : int bf_link_update(struct bf_link *link, int new_prog_fd)
     234              : {
     235            0 :     union bpf_attr attr = {
     236            0 :         .link_update.link_fd = link->fd,
     237              :         .link_update.new_prog_fd = new_prog_fd,
     238              :     };
     239              : 
     240            0 :     return bf_bpf(BPF_LINK_UPDATE, &attr);
     241              : }
     242              : 
     243            0 : int bf_link_detach(struct bf_link *link)
     244              : {
     245            0 :     union bpf_attr attr = {
     246            0 :         .link_detach.link_fd = link->fd,
     247              :     };
     248              :     int r;
     249              : 
     250            0 :     r = bf_bpf(BPF_LINK_DETACH, &attr);
     251            0 :     if (r)
     252              :         return r;
     253              : 
     254              :     closep(&link->fd);
     255              : 
     256            0 :     return 0;
     257              : }
     258              : 
     259            0 : int bf_link_pin(struct bf_link *link, int dir_fd)
     260              : {
     261              :     int r;
     262              : 
     263            0 :     bf_assert(link);
     264            0 :     bf_assert(dir_fd > 0);
     265              : 
     266            0 :     r = bf_bpf_obj_pin(link->name, link->fd, dir_fd);
     267            0 :     if (r)
     268            0 :         return bf_err_r(r, "failed to pin BPF link '%s'", link->name);
     269              : 
     270              :     return 0;
     271              : }
     272              : 
     273            0 : void bf_link_unpin(struct bf_link *link, int dir_fd)
     274              : {
     275              :     int r;
     276              : 
     277            0 :     bf_assert(link);
     278            0 :     bf_assert(dir_fd > 0);
     279              : 
     280            0 :     r = unlinkat(dir_fd, link->name, 0);
     281            0 :     if (r < 0 && errno != ENOENT) {
     282              :         // Do not warn on ENOENT, we want the file to be gone!
     283            0 :         bf_warn_r(
     284              :             errno,
     285              :             "failed to unlink BPF link '%s', assuming the link is not pinned",
     286              :             link->name);
     287              :     }
     288            0 : }
     289              : 
     290            0 : int bf_link_get_info(struct bf_link *link, struct bpf_link_info *info)
     291              : {
     292            0 :     union bpf_attr attr = {};
     293              : 
     294            0 :     bf_assert(link && info);
     295              : 
     296            0 :     if (link->fd == -1)
     297              :         return -ENOENT;
     298              : 
     299            0 :     attr.info.bpf_fd = link->fd;
     300            0 :     attr.info.info_len = sizeof(*info);
     301            0 :     attr.info.info = bf_ptr_to_u64(info);
     302              : 
     303            0 :     return bf_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr);
     304              : }
        

Generated by: LCOV version 2.0-1