LCOV - code coverage report
Current view: top level - libbpfilter - ctx.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 64.0 % 200 128
Test Date: 2026-04-17 15:45:04 Functions: 86.4 % 22 19
Branches: 35.9 % 192 69

             Branch data     Line data    Source code
       1                 :             : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :             : /*
       3                 :             :  * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <dirent.h>
       7                 :             : #include <errno.h>
       8                 :             : #include <fcntl.h>
       9                 :             : #include <stdbool.h>
      10                 :             : #include <stdlib.h>
      11                 :             : #include <sys/file.h>
      12                 :             : #include <unistd.h>
      13                 :             : 
      14                 :             : #include <bpfilter/bpf.h>
      15                 :             : #include <bpfilter/btf.h>
      16                 :             : #include <bpfilter/chain.h>
      17                 :             : #include <bpfilter/core/list.h>
      18                 :             : #include <bpfilter/ctx.h>
      19                 :             : #include <bpfilter/dump.h>
      20                 :             : #include <bpfilter/elfstub.h>
      21                 :             : #include <bpfilter/helper.h>
      22                 :             : #include <bpfilter/hook.h>
      23                 :             : #include <bpfilter/io.h>
      24                 :             : #include <bpfilter/logger.h>
      25                 :             : #include <bpfilter/pack.h>
      26                 :             : 
      27                 :             : #include "cgen/cgen.h"
      28                 :             : 
      29                 :             : #define _free_bf_ctx_ __attribute__((cleanup(_bf_ctx_free)))
      30                 :             : 
      31                 :             : /**
      32                 :             :  * @struct bf_ctx
      33                 :             :  *
      34                 :             :  * bpfilter working context. Only one context is used during the library's
      35                 :             :  * lifetime.
      36                 :             :  */
      37                 :             : struct bf_ctx
      38                 :             : {
      39                 :             :     /// BPF token file descriptor
      40                 :             :     int token_fd;
      41                 :             : 
      42                 :             :     int lock_fd;
      43                 :             : 
      44                 :             :     bf_list cgens;
      45                 :             : 
      46                 :             :     struct bf_elfstub *stubs[_BF_ELFSTUB_MAX];
      47                 :             : 
      48                 :             :     /// Pass a token to BPF system calls, obtained from bpffs.
      49                 :             :     bool with_bpf_token;
      50                 :             : 
      51                 :             :     /// Path to the bpffs to pin the BPF objects into.
      52                 :             :     const char *bpffs_path;
      53                 :             : 
      54                 :             :     /// Verbose flags.
      55                 :             :     uint16_t verbose;
      56                 :             : };
      57                 :             : 
      58                 :             : static void _bf_ctx_free(struct bf_ctx **ctx);
      59                 :             : 
      60                 :             : /// Global runtime context. Hidden in this translation unit.
      61                 :             : static struct bf_ctx *_bf_global_ctx = NULL;
      62                 :             : 
      63                 :           0 : static int _bf_ctx_gen_token(const char *bpffs_path)
      64                 :             : {
      65                 :           0 :     _cleanup_close_ int mnt_fd = -1;
      66                 :           0 :     _cleanup_close_ int bpffs_fd = -1;
      67                 :           0 :     _cleanup_close_ int token_fd = -1;
      68                 :             : 
      69                 :           0 :     mnt_fd = open(bpffs_path, O_DIRECTORY);
      70         [ #  # ]:           0 :     if (mnt_fd < 0)
      71         [ #  # ]:           0 :         return bf_err_r(errno, "failed to open '%s'", bpffs_path);
      72                 :             : 
      73                 :           0 :     bpffs_fd = openat(mnt_fd, ".", 0, O_RDWR);
      74         [ #  # ]:           0 :     if (bpffs_fd < 0)
      75         [ #  # ]:           0 :         return bf_err_r(errno, "failed to get bpffs FD from '%s'", bpffs_path);
      76                 :             : 
      77                 :           0 :     token_fd = bf_bpf_token_create(bpffs_fd);
      78         [ #  # ]:           0 :     if (token_fd < 0) {
      79         [ #  # ]:           0 :         return bf_err_r(token_fd, "failed to create BPF token for '%s'",
      80                 :             :                         bpffs_path);
      81                 :             :     }
      82                 :             : 
      83                 :           0 :     return TAKE_FD(token_fd);
      84                 :             : }
      85                 :             : 
      86                 :             : /**
      87                 :             :  * Create and initialize a new context.
      88                 :             :  *
      89                 :             :  * On failure, @p ctx is left unchanged.
      90                 :             :  *
      91                 :             :  * @param ctx New context to create. Can't be NULL.
      92                 :             :  * @param with_bpf_token If true, create a BPF token from bpffs.
      93                 :             :  * @param bpffs_path Path to the bpffs mountpoint. Can't be NULL.
      94                 :             :  * @param verbose Bitmask of verbose flags.
      95                 :             :  * @return 0 on success, negative errno value on failure.
      96                 :             :  */
      97                 :         341 : static int _bf_ctx_new(struct bf_ctx **ctx, bool with_bpf_token,
      98                 :             :                        const char *bpffs_path, uint16_t verbose)
      99                 :             : {
     100                 :         341 :     _free_bf_ctx_ struct bf_ctx *_ctx = NULL;
     101                 :             :     int r;
     102                 :             : 
     103                 :             :     assert(ctx);
     104                 :             :     assert(bpffs_path);
     105                 :             : 
     106                 :         341 :     _ctx = calloc(1, sizeof(*_ctx));
     107         [ +  - ]:         341 :     if (!_ctx)
     108                 :             :         return -ENOMEM;
     109                 :             : 
     110                 :         341 :     r = bf_btf_setup();
     111         [ -  + ]:         341 :     if (r)
     112         [ #  # ]:           0 :         return bf_err_r(r, "failed to load vmlinux BTF");
     113                 :             : 
     114                 :         341 :     _ctx->with_bpf_token = with_bpf_token;
     115                 :         341 :     _ctx->bpffs_path = bpffs_path;
     116                 :         341 :     _ctx->verbose = verbose;
     117                 :         341 :     _ctx->lock_fd = -1;
     118                 :             : 
     119                 :         341 :     _ctx->token_fd = -1;
     120         [ -  + ]:         341 :     if (_ctx->with_bpf_token) {
     121                 :           0 :         _cleanup_close_ int token_fd = -1;
     122                 :             : 
     123                 :           0 :         r = bf_btf_kernel_has_token();
     124         [ #  # ]:           0 :         if (r == -ENOENT) {
     125         [ #  # ]:           0 :             bf_err(
     126                 :             :                 "--with-bpf-token requested, but this kernel doesn't support BPF token");
     127                 :           0 :             return r;
     128                 :             :         }
     129         [ #  # ]:           0 :         if (r)
     130         [ #  # ]:           0 :             return bf_err_r(r, "failed to check for BPF token support");
     131                 :             : 
     132                 :           0 :         token_fd = _bf_ctx_gen_token(_ctx->bpffs_path);
     133         [ #  # ]:           0 :         if (token_fd < 0)
     134         [ #  # ]:           0 :             return bf_err_r(token_fd, "failed to generate a BPF token");
     135                 :             : 
     136                 :           0 :         _ctx->token_fd = TAKE_FD(token_fd);
     137                 :             :     }
     138                 :             : 
     139                 :         341 :     _ctx->cgens = bf_list_default(bf_cgen_free, bf_cgen_pack);
     140                 :             : 
     141         [ +  + ]:        2046 :     for (enum bf_elfstub_id id = 0; id < _BF_ELFSTUB_MAX; ++id) {
     142                 :        1705 :         r = bf_elfstub_new(&_ctx->stubs[id], id);
     143         [ -  + ]:        1705 :         if (r)
     144         [ #  # ]:           0 :             return bf_err_r(r, "failed to create ELF stub ID %u", id);
     145                 :             :     }
     146                 :             : 
     147                 :         341 :     *ctx = TAKE_PTR(_ctx);
     148                 :             : 
     149                 :         341 :     return 0;
     150                 :             : }
     151                 :             : 
     152                 :             : /**
     153                 :             :  * Free a context.
     154                 :             :  *
     155                 :             :  * If @p ctx points to a NULL pointer, this function does nothing. Once
     156                 :             :  * the function returns, @p ctx points to a NULL pointer.
     157                 :             :  *
     158                 :             :  * @param ctx Context to free. Can't be NULL.
     159                 :             :  */
     160                 :         682 : static void _bf_ctx_free(struct bf_ctx **ctx)
     161                 :             : {
     162                 :             :     assert(ctx);
     163                 :             : 
     164         [ +  + ]:         682 :     if (!*ctx)
     165                 :             :         return;
     166                 :             : 
     167                 :         341 :     closep(&(*ctx)->token_fd);
     168                 :         341 :     closep(&(*ctx)->lock_fd);
     169                 :         341 :     bf_list_clean(&(*ctx)->cgens);
     170                 :             : 
     171         [ +  + ]:        2046 :     for (enum bf_elfstub_id id = 0; id < _BF_ELFSTUB_MAX; ++id)
     172                 :        1705 :         bf_elfstub_free(&(*ctx)->stubs[id]);
     173                 :             : 
     174                 :         341 :     bf_btf_teardown();
     175                 :             : 
     176                 :             :     freep((void *)ctx);
     177                 :             : }
     178                 :             : 
     179                 :             : /**
     180                 :             :  * See @ref bf_ctx_dump for details.
     181                 :             :  */
     182                 :           0 : static void _bf_ctx_dump(const struct bf_ctx *ctx, prefix_t *prefix)
     183                 :             : {
     184         [ #  # ]:           0 :     DUMP(prefix, "struct bf_ctx at %p", ctx);
     185                 :             : 
     186                 :           0 :     bf_dump_prefix_push(prefix);
     187                 :             : 
     188         [ #  # ]:           0 :     DUMP(prefix, "token_fd: %d", ctx->token_fd);
     189                 :             : 
     190                 :             :     // Codegens
     191         [ #  # ]:           0 :     DUMP(bf_dump_prefix_last(prefix), "cgens: bf_list<struct bf_cgen>[%lu]",
     192                 :             :          bf_list_size(&ctx->cgens));
     193                 :           0 :     bf_dump_prefix_push(prefix);
     194   [ #  #  #  #  :           0 :     bf_list_foreach (&ctx->cgens, cgen_node) {
                   #  # ]
     195                 :             :         struct bf_cgen *cgen = bf_list_node_get_data(cgen_node);
     196                 :             : 
     197         [ #  # ]:           0 :         if (bf_list_is_tail(&ctx->cgens, cgen_node))
     198                 :           0 :             bf_dump_prefix_last(prefix);
     199                 :             : 
     200                 :           0 :         bf_cgen_dump(cgen, prefix);
     201                 :             :     }
     202                 :           0 :     bf_dump_prefix_pop(prefix);
     203                 :             : 
     204                 :           0 :     bf_dump_prefix_pop(prefix);
     205                 :           0 : }
     206                 :             : 
     207                 :             : /**
     208                 :             :  * See @ref bf_ctx_get_cgen for details.
     209                 :             :  */
     210                 :        6121 : static struct bf_cgen *_bf_ctx_get_cgen(const struct bf_ctx *ctx,
     211                 :             :                                         const char *name)
     212                 :             : {
     213                 :             :     assert(ctx);
     214                 :             :     assert(name);
     215                 :             : 
     216   [ +  +  +  +  :       12642 :     bf_list_foreach (&ctx->cgens, cgen_node) {
                   +  + ]
     217                 :             :         struct bf_cgen *cgen = bf_list_node_get_data(cgen_node);
     218                 :             : 
     219         [ +  + ]:        4251 :         if (bf_streq(cgen->chain->name, name))
     220                 :             :             return cgen;
     221                 :             :     }
     222                 :             : 
     223                 :             :     return NULL;
     224                 :             : }
     225                 :             : 
     226                 :             : /**
     227                 :             :  * See @ref bf_ctx_get_cgens for details.
     228                 :             :  */
     229                 :           4 : static int _bf_ctx_get_cgens(const struct bf_ctx *ctx, bf_list *cgens)
     230                 :             : {
     231                 :           4 :     _clean_bf_list_ bf_list _cgens = bf_list_default(NULL, NULL);
     232                 :             :     int r;
     233                 :             : 
     234                 :             :     assert(ctx);
     235                 :             :     assert(cgens);
     236                 :             : 
     237   [ +  -  +  +  :          18 :     bf_list_foreach (&ctx->cgens, cgen_node) {
                   +  + ]
     238                 :           5 :         r = bf_list_add_tail(&_cgens, bf_list_node_get_data(cgen_node));
     239         [ +  - ]:           5 :         if (r)
     240                 :             :             return r;
     241                 :             :     }
     242                 :             : 
     243                 :           4 :     *cgens = bf_list_move(_cgens);
     244                 :             : 
     245                 :           4 :     return 0;
     246                 :             : }
     247                 :             : 
     248                 :             : /**
     249                 :             :  * See @ref bf_ctx_set_cgen for details.
     250                 :             :  */
     251                 :        1171 : static int _bf_ctx_set_cgen(struct bf_ctx *ctx, struct bf_cgen *cgen)
     252                 :             : {
     253                 :             :     assert(ctx);
     254                 :             :     assert(cgen);
     255                 :             : 
     256         [ -  + ]:        1171 :     if (_bf_ctx_get_cgen(ctx, cgen->chain->name))
     257         [ #  # ]:           0 :         return bf_err_r(-EEXIST, "codegen already exists in context");
     258                 :             : 
     259                 :        1171 :     return bf_list_add_tail(&ctx->cgens, cgen);
     260                 :             : }
     261                 :             : 
     262                 :         262 : static int _bf_ctx_delete_cgen(struct bf_ctx *ctx, struct bf_cgen *cgen,
     263                 :             :                                bool unload)
     264                 :             : {
     265   [ +  -  +  - ]:         574 :     bf_list_foreach (&ctx->cgens, cgen_node) {
     266                 :             :         struct bf_cgen *_cgen = bf_list_node_get_data(cgen_node);
     267                 :             : 
     268   [ +  +  -  + ]:         287 :         if (_cgen != cgen)
     269                 :             :             continue;
     270                 :             : 
     271         [ +  - ]:         262 :         if (unload)
     272                 :         262 :             bf_cgen_unload(_cgen);
     273                 :             : 
     274                 :         262 :         bf_list_delete(&ctx->cgens, cgen_node);
     275                 :             : 
     276                 :         262 :         return 0;
     277                 :             :     }
     278                 :             : 
     279                 :             :     return -ENOENT;
     280                 :             : }
     281                 :             : 
     282                 :             : static void _bf_free_dir(DIR **dir)
     283                 :             : {
     284         [ -  + ]:         341 :     if (!*dir)
     285                 :             :         return;
     286                 :             : 
     287                 :         341 :     closedir(*dir);
     288                 :             :     *dir = NULL;
     289                 :             : }
     290                 :             : 
     291                 :             : #define _free_dir_ __attribute__((__cleanup__(_bf_free_dir)))
     292                 :             : 
     293                 :             : /**
     294                 :             :  * @brief Discover and restore chains from bpffs context maps.
     295                 :             :  *
     296                 :             :  * Iterates subdirectories under `{bpffs}/bpfilter/`, deserializing each
     297                 :             :  * chain's `bf_ctx` context map into a `bf_cgen` and adding it to the
     298                 :             :  * global context. The global context must already be initialized via
     299                 :             :  * `bf_ctx_setup` before calling this function.
     300                 :             :  *
     301                 :             :  * @return 0 on success, or a negative errno value on failure.
     302                 :             :  */
     303                 :         341 : static int _bf_ctx_discover(void)
     304                 :             : {
     305                 :         341 :     _cleanup_close_ int bpffs_fd = -1;
     306                 :         341 :     _cleanup_close_ int pindir_fd = -1;
     307                 :             :     _free_dir_ DIR *dir = NULL;
     308                 :             :     struct dirent *entry;
     309                 :             :     int iter_fd;
     310                 :             :     int r;
     311                 :             : 
     312                 :         341 :     bpffs_fd = bf_opendir(_bf_global_ctx->bpffs_path);
     313         [ -  + ]:         341 :     if (bpffs_fd < 0) {
     314         [ #  # ]:           0 :         return bf_err_r(bpffs_fd, "failed to open bpffs at %s",
     315                 :             :                         _bf_global_ctx->bpffs_path);
     316                 :             :     }
     317                 :             : 
     318                 :         341 :     pindir_fd = bf_opendir_at(bpffs_fd, "bpfilter", false);
     319         [ -  + ]:         341 :     if (pindir_fd < 0) {
     320         [ #  # ]:           0 :         if (pindir_fd == -ENOENT) {
     321         [ #  # ]:           0 :             bf_info("no bpfilter pin directory found, nothing to discover");
     322                 :             :             return 0;
     323                 :             :         }
     324         [ #  # ]:           0 :         return bf_err_r(pindir_fd, "failed to open pin directory");
     325                 :             :     }
     326                 :             : 
     327                 :             :     /* fdopendir() takes ownership of the fd: dup so pindir_fd remains valid
     328                 :             :      * for openat() calls inside the loop. */
     329                 :         341 :     iter_fd = dup(pindir_fd);
     330         [ -  + ]:         341 :     if (iter_fd < 0)
     331         [ #  # ]:           0 :         return bf_err_r(-errno, "failed to dup pin directory fd");
     332                 :             : 
     333                 :         341 :     dir = fdopendir(iter_fd);
     334         [ -  + ]:         341 :     if (!dir) {
     335                 :           0 :         r = -errno;
     336                 :           0 :         close(iter_fd);
     337         [ #  # ]:           0 :         return bf_err_r(r, "failed to open pin directory for iteration");
     338                 :             :     }
     339                 :             : 
     340                 :             :     for (;;) {
     341                 :        1342 :         _free_bf_cgen_ struct bf_cgen *cgen = NULL;
     342                 :        1342 :         _cleanup_close_ int chain_fd = -1;
     343                 :             : 
     344                 :        1342 :         errno = 0;
     345                 :        1342 :         entry = readdir(dir);
     346         [ +  + ]:        1342 :         if (!entry)
     347                 :             :             break;
     348                 :             : 
     349   [ +  +  +  + ]:        1001 :         if (bf_streq(entry->d_name, ".") || bf_streq(entry->d_name, ".."))
     350                 :         682 :             continue;
     351                 :             : 
     352         [ -  + ]:         319 :         if (entry->d_type != DT_DIR)
     353                 :           0 :             continue;
     354                 :             : 
     355                 :         319 :         chain_fd = openat(pindir_fd, entry->d_name, O_DIRECTORY);
     356         [ -  + ]:         319 :         if (chain_fd < 0) {
     357         [ #  # ]:           0 :             bf_warn("failed to open chain directory '%s', skipping",
     358                 :             :                     entry->d_name);
     359                 :           0 :             continue;
     360                 :             :         }
     361                 :             : 
     362                 :         319 :         r = bf_cgen_new_from_dir_fd(&cgen, chain_fd);
     363         [ -  + ]:         319 :         if (r) {
     364         [ #  # ]:           0 :             bf_warn("failed to restore chain '%s', skipping", entry->d_name);
     365                 :           0 :             continue;
     366                 :             :         }
     367                 :             : 
     368         [ +  - ]:         319 :         bf_info("discovered chain '%s'", entry->d_name);
     369                 :             : 
     370                 :         319 :         r = bf_list_push(&_bf_global_ctx->cgens, (void **)&cgen);
     371         [ -  + ]:         319 :         if (r) {
     372         [ #  # ]:           0 :             bf_warn("failed to add restored chain '%s' to context, skipping",
     373                 :             :                     entry->d_name);
     374                 :             :         }
     375                 :             :     }
     376                 :             : 
     377         [ -  + ]:         341 :     if (errno)
     378         [ #  # ]:           0 :         return bf_err_r(-errno, "failed to read pin directory");
     379                 :             : 
     380                 :             :     return 0;
     381                 :             : }
     382                 :             : 
     383                 :         341 : int bf_ctx_setup(bool with_bpf_token, const char *bpffs_path, uint16_t verbose)
     384                 :             : {
     385                 :         341 :     _cleanup_close_ int pindir_fd = -1;
     386                 :             :     int r;
     387                 :             : 
     388                 :         341 :     r = _bf_ctx_new(&_bf_global_ctx, with_bpf_token, bpffs_path, verbose);
     389         [ -  + ]:         341 :     if (r)
     390         [ #  # ]:           0 :         return bf_err_r(r, "failed to create new context");
     391                 :             : 
     392                 :         341 :     pindir_fd = bf_ctx_get_pindir_fd();
     393         [ -  + ]:         341 :     if (pindir_fd < 0) {
     394                 :           0 :         _bf_ctx_free(&_bf_global_ctx);
     395         [ #  # ]:           0 :         return bf_err_r(pindir_fd, "failed to get pin directory FD");
     396                 :             :     }
     397                 :             : 
     398                 :         341 :     r = flock(pindir_fd, LOCK_EX | LOCK_NB);
     399         [ -  + ]:         341 :     if (r) {
     400                 :           0 :         _bf_ctx_free(&_bf_global_ctx);
     401         [ #  # ]:           0 :         return bf_err_r(-errno, "failed to lock pin directory");
     402                 :             :     }
     403                 :             : 
     404                 :         341 :     r = _bf_ctx_discover();
     405         [ -  + ]:         341 :     if (r) {
     406                 :           0 :         _bf_ctx_free(&_bf_global_ctx);
     407         [ #  # ]:           0 :         return bf_err_r(r, "failed to discover chains");
     408                 :             :     }
     409                 :             : 
     410                 :         341 :     _bf_global_ctx->lock_fd = TAKE_FD(pindir_fd);
     411                 :             : 
     412                 :         341 :     return 0;
     413                 :             : }
     414                 :             : 
     415                 :         341 : void bf_ctx_teardown(void)
     416                 :             : {
     417                 :         341 :     _bf_ctx_free(&_bf_global_ctx);
     418                 :         341 : }
     419                 :             : 
     420                 :        1690 : static void _bf_ctx_flush(struct bf_ctx *ctx)
     421                 :             : {
     422                 :             :     assert(ctx);
     423                 :             : 
     424   [ +  +  +  +  :        5158 :     bf_list_foreach (&ctx->cgens, cgen_node) {
                   +  + ]
     425                 :             :         struct bf_cgen *cgen = bf_list_node_get_data(cgen_node);
     426                 :             : 
     427                 :         889 :         bf_cgen_unload(cgen);
     428                 :         889 :         bf_list_delete(&ctx->cgens, cgen_node);
     429                 :             :     }
     430                 :        1690 : }
     431                 :             : 
     432                 :        1690 : void bf_ctx_flush(void)
     433                 :             : {
     434         [ +  - ]:        1690 :     if (!_bf_global_ctx)
     435                 :             :         return;
     436                 :             : 
     437                 :        1690 :     _bf_ctx_flush(_bf_global_ctx);
     438                 :             : }
     439                 :             : 
     440                 :           0 : void bf_ctx_dump(prefix_t *prefix)
     441                 :             : {
     442         [ #  # ]:           0 :     if (!_bf_global_ctx)
     443                 :             :         return;
     444                 :             : 
     445                 :           0 :     _bf_ctx_dump(_bf_global_ctx, prefix);
     446                 :             : }
     447                 :             : 
     448                 :        4950 : struct bf_cgen *bf_ctx_get_cgen(const char *name)
     449                 :             : {
     450         [ +  - ]:        4950 :     if (!_bf_global_ctx)
     451                 :             :         return NULL;
     452                 :             : 
     453                 :        4950 :     return _bf_ctx_get_cgen(_bf_global_ctx, name);
     454                 :             : }
     455                 :             : 
     456                 :           4 : int bf_ctx_get_cgens(bf_list *cgens)
     457                 :             : {
     458         [ -  + ]:           4 :     if (!_bf_global_ctx)
     459         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "context is not initialized");
     460                 :             : 
     461                 :           4 :     return _bf_ctx_get_cgens(_bf_global_ctx, cgens);
     462                 :             : }
     463                 :             : 
     464                 :        1171 : int bf_ctx_set_cgen(struct bf_cgen *cgen)
     465                 :             : {
     466         [ -  + ]:        1171 :     if (!_bf_global_ctx)
     467         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "context is not initialized");
     468                 :             : 
     469                 :        1171 :     return _bf_ctx_set_cgen(_bf_global_ctx, cgen);
     470                 :             : }
     471                 :             : 
     472                 :         262 : int bf_ctx_delete_cgen(struct bf_cgen *cgen, bool unload)
     473                 :             : {
     474         [ -  + ]:         262 :     if (!_bf_global_ctx)
     475         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "context is not initialized");
     476                 :             : 
     477                 :         262 :     return _bf_ctx_delete_cgen(_bf_global_ctx, cgen, unload);
     478                 :             : }
     479                 :             : 
     480                 :        6265 : int bf_ctx_token(void)
     481                 :             : {
     482         [ +  - ]:        6265 :     if (!_bf_global_ctx)
     483                 :             :         return -1;
     484                 :             : 
     485                 :        6265 :     return _bf_global_ctx->token_fd;
     486                 :             : }
     487                 :             : 
     488                 :        4510 : int bf_ctx_get_pindir_fd(void)
     489                 :             : {
     490                 :        4510 :     _cleanup_close_ int bpffs_fd = -1;
     491                 :        4510 :     _cleanup_close_ int pindir_fd = -1;
     492                 :             : 
     493         [ -  + ]:        4510 :     if (!_bf_global_ctx)
     494         [ #  # ]:           0 :         return bf_err_r(-EINVAL, "context is not initialized");
     495                 :             : 
     496                 :        4510 :     bpffs_fd = bf_opendir(_bf_global_ctx->bpffs_path);
     497         [ -  + ]:        4510 :     if (bpffs_fd < 0) {
     498         [ #  # ]:           0 :         return bf_err_r(bpffs_fd, "failed to open bpffs at %s",
     499                 :             :                         _bf_global_ctx->bpffs_path);
     500                 :             :     }
     501                 :             : 
     502                 :        4510 :     pindir_fd = bf_opendir_at(bpffs_fd, "bpfilter", true);
     503         [ -  + ]:        4510 :     if (pindir_fd < 0) {
     504         [ #  # ]:           0 :         return bf_err_r(pindir_fd, "failed to open pin directory %s/bpfilter",
     505                 :             :                         _bf_global_ctx->bpffs_path);
     506                 :             :     }
     507                 :             : 
     508                 :        4510 :     return TAKE_FD(pindir_fd);
     509                 :             : }
     510                 :             : 
     511                 :        2363 : const struct bf_elfstub *bf_ctx_get_elfstub(enum bf_elfstub_id id)
     512                 :             : {
     513         [ +  - ]:        2363 :     if (!_bf_global_ctx)
     514                 :             :         return NULL;
     515                 :             : 
     516                 :        2363 :     return _bf_global_ctx->stubs[id];
     517                 :             : }
     518                 :             : 
     519                 :        6200 : bool bf_ctx_is_verbose(enum bf_verbose opt)
     520                 :             : {
     521         [ +  - ]:        6200 :     if (!_bf_global_ctx)
     522                 :             :         return false;
     523                 :             : 
     524                 :        6200 :     return _bf_global_ctx->verbose & BF_FLAG(opt);
     525                 :             : }
        

Generated by: LCOV version 2.0-1