167234743SAlexei Starovoitov /* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ 267234743SAlexei Starovoitov /* Copyright (c) 2021 Facebook */ 367234743SAlexei Starovoitov #ifndef __SKEL_INTERNAL_H 467234743SAlexei Starovoitov #define __SKEL_INTERNAL_H 567234743SAlexei Starovoitov 6*6fe65f1bSAlexei Starovoitov #ifdef __KERNEL__ 7*6fe65f1bSAlexei Starovoitov #include <linux/fdtable.h> 8*6fe65f1bSAlexei Starovoitov #include <linux/mm.h> 9*6fe65f1bSAlexei Starovoitov #include <linux/mman.h> 10*6fe65f1bSAlexei Starovoitov #include <linux/slab.h> 11*6fe65f1bSAlexei Starovoitov #include <linux/bpf.h> 12*6fe65f1bSAlexei Starovoitov #else 1367234743SAlexei Starovoitov #include <unistd.h> 1467234743SAlexei Starovoitov #include <sys/syscall.h> 1567234743SAlexei Starovoitov #include <sys/mman.h> 16*6fe65f1bSAlexei Starovoitov #include <stdlib.h> 17*6fe65f1bSAlexei Starovoitov #include "bpf.h" 18*6fe65f1bSAlexei Starovoitov #endif 1967234743SAlexei Starovoitov 20e32cb12fSTiezhu Yang #ifndef __NR_bpf 21e32cb12fSTiezhu Yang # if defined(__mips__) && defined(_ABIO32) 22e32cb12fSTiezhu Yang # define __NR_bpf 4355 23e32cb12fSTiezhu Yang # elif defined(__mips__) && defined(_ABIN32) 24e32cb12fSTiezhu Yang # define __NR_bpf 6319 25e32cb12fSTiezhu Yang # elif defined(__mips__) && defined(_ABI64) 26e32cb12fSTiezhu Yang # define __NR_bpf 5315 27e32cb12fSTiezhu Yang # endif 28e32cb12fSTiezhu Yang #endif 29e32cb12fSTiezhu Yang 3067234743SAlexei Starovoitov /* This file is a base header for auto-generated *.lskel.h files. 3167234743SAlexei Starovoitov * Its contents will change and may become part of auto-generation in the future. 3267234743SAlexei Starovoitov * 3367234743SAlexei Starovoitov * The layout of bpf_[map|prog]_desc and bpf_loader_ctx is feature dependent 3467234743SAlexei Starovoitov * and will change from one version of libbpf to another and features 3567234743SAlexei Starovoitov * requested during loader program generation. 3667234743SAlexei Starovoitov */ 3767234743SAlexei Starovoitov struct bpf_map_desc { 3867234743SAlexei Starovoitov /* output of the loader prog */ 3967234743SAlexei Starovoitov int map_fd; 40*6fe65f1bSAlexei Starovoitov /* input for the loader prog */ 41*6fe65f1bSAlexei Starovoitov __u32 max_entries; 42*6fe65f1bSAlexei Starovoitov __aligned_u64 initial_value; 4367234743SAlexei Starovoitov }; 4467234743SAlexei Starovoitov struct bpf_prog_desc { 4567234743SAlexei Starovoitov int prog_fd; 4667234743SAlexei Starovoitov }; 4767234743SAlexei Starovoitov 48*6fe65f1bSAlexei Starovoitov enum { 49*6fe65f1bSAlexei Starovoitov BPF_SKEL_KERNEL = (1ULL << 0), 50*6fe65f1bSAlexei Starovoitov }; 51*6fe65f1bSAlexei Starovoitov 5267234743SAlexei Starovoitov struct bpf_loader_ctx { 53*6fe65f1bSAlexei Starovoitov __u32 sz; 54*6fe65f1bSAlexei Starovoitov __u32 flags; 5567234743SAlexei Starovoitov __u32 log_level; 5667234743SAlexei Starovoitov __u32 log_size; 5767234743SAlexei Starovoitov __u64 log_buf; 5867234743SAlexei Starovoitov }; 5967234743SAlexei Starovoitov 6067234743SAlexei Starovoitov struct bpf_load_and_run_opts { 6167234743SAlexei Starovoitov struct bpf_loader_ctx *ctx; 6267234743SAlexei Starovoitov const void *data; 6367234743SAlexei Starovoitov const void *insns; 6467234743SAlexei Starovoitov __u32 data_sz; 6567234743SAlexei Starovoitov __u32 insns_sz; 6667234743SAlexei Starovoitov const char *errstr; 6767234743SAlexei Starovoitov }; 6867234743SAlexei Starovoitov 69*6fe65f1bSAlexei Starovoitov long bpf_sys_bpf(__u32 cmd, void *attr, __u32 attr_size); 70*6fe65f1bSAlexei Starovoitov 7167234743SAlexei Starovoitov static inline int skel_sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr, 7267234743SAlexei Starovoitov unsigned int size) 7367234743SAlexei Starovoitov { 74*6fe65f1bSAlexei Starovoitov #ifdef __KERNEL__ 75*6fe65f1bSAlexei Starovoitov return bpf_sys_bpf(cmd, attr, size); 76*6fe65f1bSAlexei Starovoitov #else 7767234743SAlexei Starovoitov return syscall(__NR_bpf, cmd, attr, size); 78*6fe65f1bSAlexei Starovoitov #endif 7967234743SAlexei Starovoitov } 8067234743SAlexei Starovoitov 81*6fe65f1bSAlexei Starovoitov #ifdef __KERNEL__ 82*6fe65f1bSAlexei Starovoitov static inline int close(int fd) 83*6fe65f1bSAlexei Starovoitov { 84*6fe65f1bSAlexei Starovoitov return close_fd(fd); 85*6fe65f1bSAlexei Starovoitov } 86*6fe65f1bSAlexei Starovoitov 87*6fe65f1bSAlexei Starovoitov static inline void *skel_alloc(size_t size) 88*6fe65f1bSAlexei Starovoitov { 89*6fe65f1bSAlexei Starovoitov struct bpf_loader_ctx *ctx = kzalloc(size, GFP_KERNEL); 90*6fe65f1bSAlexei Starovoitov 91*6fe65f1bSAlexei Starovoitov if (!ctx) 92*6fe65f1bSAlexei Starovoitov return NULL; 93*6fe65f1bSAlexei Starovoitov ctx->flags |= BPF_SKEL_KERNEL; 94*6fe65f1bSAlexei Starovoitov return ctx; 95*6fe65f1bSAlexei Starovoitov } 96*6fe65f1bSAlexei Starovoitov 97*6fe65f1bSAlexei Starovoitov static inline void skel_free(const void *p) 98*6fe65f1bSAlexei Starovoitov { 99*6fe65f1bSAlexei Starovoitov kfree(p); 100*6fe65f1bSAlexei Starovoitov } 101*6fe65f1bSAlexei Starovoitov 102*6fe65f1bSAlexei Starovoitov /* skel->bss/rodata maps are populated the following way: 103*6fe65f1bSAlexei Starovoitov * 104*6fe65f1bSAlexei Starovoitov * For kernel use: 105*6fe65f1bSAlexei Starovoitov * skel_prep_map_data() allocates kernel memory that kernel module can directly access. 106*6fe65f1bSAlexei Starovoitov * Generated lskel stores the pointer in skel->rodata and in skel->maps.rodata.initial_value. 107*6fe65f1bSAlexei Starovoitov * The loader program will perform probe_read_kernel() from maps.rodata.initial_value. 108*6fe65f1bSAlexei Starovoitov * skel_finalize_map_data() sets skel->rodata to point to actual value in a bpf map and 109*6fe65f1bSAlexei Starovoitov * does maps.rodata.initial_value = ~0ULL to signal skel_free_map_data() that kvfree 110*6fe65f1bSAlexei Starovoitov * is not nessary. 111*6fe65f1bSAlexei Starovoitov * 112*6fe65f1bSAlexei Starovoitov * For user space: 113*6fe65f1bSAlexei Starovoitov * skel_prep_map_data() mmaps anon memory into skel->rodata that can be accessed directly. 114*6fe65f1bSAlexei Starovoitov * Generated lskel stores the pointer in skel->rodata and in skel->maps.rodata.initial_value. 115*6fe65f1bSAlexei Starovoitov * The loader program will perform copy_from_user() from maps.rodata.initial_value. 116*6fe65f1bSAlexei Starovoitov * skel_finalize_map_data() remaps bpf array map value from the kernel memory into 117*6fe65f1bSAlexei Starovoitov * skel->rodata address. 118*6fe65f1bSAlexei Starovoitov * 119*6fe65f1bSAlexei Starovoitov * The "bpftool gen skeleton -L" command generates lskel.h that is suitable for 120*6fe65f1bSAlexei Starovoitov * both kernel and user space. The generated loader program does 121*6fe65f1bSAlexei Starovoitov * either bpf_probe_read_kernel() or bpf_copy_from_user() from initial_value 122*6fe65f1bSAlexei Starovoitov * depending on bpf_loader_ctx->flags. 123*6fe65f1bSAlexei Starovoitov */ 124*6fe65f1bSAlexei Starovoitov static inline void skel_free_map_data(void *p, __u64 addr, size_t sz) 125*6fe65f1bSAlexei Starovoitov { 126*6fe65f1bSAlexei Starovoitov if (addr != ~0ULL) 127*6fe65f1bSAlexei Starovoitov kvfree(p); 128*6fe65f1bSAlexei Starovoitov /* When addr == ~0ULL the 'p' points to 129*6fe65f1bSAlexei Starovoitov * ((struct bpf_array *)map)->value. See skel_finalize_map_data. 130*6fe65f1bSAlexei Starovoitov */ 131*6fe65f1bSAlexei Starovoitov } 132*6fe65f1bSAlexei Starovoitov 133*6fe65f1bSAlexei Starovoitov static inline void *skel_prep_map_data(const void *val, size_t mmap_sz, size_t val_sz) 134*6fe65f1bSAlexei Starovoitov { 135*6fe65f1bSAlexei Starovoitov void *addr; 136*6fe65f1bSAlexei Starovoitov 137*6fe65f1bSAlexei Starovoitov addr = kvmalloc(val_sz, GFP_KERNEL); 138*6fe65f1bSAlexei Starovoitov if (!addr) 139*6fe65f1bSAlexei Starovoitov return NULL; 140*6fe65f1bSAlexei Starovoitov memcpy(addr, val, val_sz); 141*6fe65f1bSAlexei Starovoitov return addr; 142*6fe65f1bSAlexei Starovoitov } 143*6fe65f1bSAlexei Starovoitov 144*6fe65f1bSAlexei Starovoitov static inline void *skel_finalize_map_data(__u64 *init_val, size_t mmap_sz, int flags, int fd) 145*6fe65f1bSAlexei Starovoitov { 146*6fe65f1bSAlexei Starovoitov struct bpf_map *map; 147*6fe65f1bSAlexei Starovoitov void *addr = NULL; 148*6fe65f1bSAlexei Starovoitov 149*6fe65f1bSAlexei Starovoitov kvfree((void *) (long) *init_val); 150*6fe65f1bSAlexei Starovoitov *init_val = ~0ULL; 151*6fe65f1bSAlexei Starovoitov 152*6fe65f1bSAlexei Starovoitov /* At this point bpf_load_and_run() finished without error and 153*6fe65f1bSAlexei Starovoitov * 'fd' is a valid bpf map FD. All sanity checks below should succeed. 154*6fe65f1bSAlexei Starovoitov */ 155*6fe65f1bSAlexei Starovoitov map = bpf_map_get(fd); 156*6fe65f1bSAlexei Starovoitov if (IS_ERR(map)) 157*6fe65f1bSAlexei Starovoitov return NULL; 158*6fe65f1bSAlexei Starovoitov if (map->map_type != BPF_MAP_TYPE_ARRAY) 159*6fe65f1bSAlexei Starovoitov goto out; 160*6fe65f1bSAlexei Starovoitov addr = ((struct bpf_array *)map)->value; 161*6fe65f1bSAlexei Starovoitov /* the addr stays valid, since FD is not closed */ 162*6fe65f1bSAlexei Starovoitov out: 163*6fe65f1bSAlexei Starovoitov bpf_map_put(map); 164*6fe65f1bSAlexei Starovoitov return addr; 165*6fe65f1bSAlexei Starovoitov } 166*6fe65f1bSAlexei Starovoitov 167*6fe65f1bSAlexei Starovoitov #else 168*6fe65f1bSAlexei Starovoitov 169*6fe65f1bSAlexei Starovoitov static inline void *skel_alloc(size_t size) 170*6fe65f1bSAlexei Starovoitov { 171*6fe65f1bSAlexei Starovoitov return calloc(1, size); 172*6fe65f1bSAlexei Starovoitov } 173*6fe65f1bSAlexei Starovoitov 174*6fe65f1bSAlexei Starovoitov static inline void skel_free(void *p) 175*6fe65f1bSAlexei Starovoitov { 176*6fe65f1bSAlexei Starovoitov free(p); 177*6fe65f1bSAlexei Starovoitov } 178*6fe65f1bSAlexei Starovoitov 179*6fe65f1bSAlexei Starovoitov static inline void skel_free_map_data(void *p, __u64 addr, size_t sz) 180*6fe65f1bSAlexei Starovoitov { 181*6fe65f1bSAlexei Starovoitov munmap(p, sz); 182*6fe65f1bSAlexei Starovoitov } 183*6fe65f1bSAlexei Starovoitov 184*6fe65f1bSAlexei Starovoitov static inline void *skel_prep_map_data(const void *val, size_t mmap_sz, size_t val_sz) 185*6fe65f1bSAlexei Starovoitov { 186*6fe65f1bSAlexei Starovoitov void *addr; 187*6fe65f1bSAlexei Starovoitov 188*6fe65f1bSAlexei Starovoitov addr = mmap(NULL, mmap_sz, PROT_READ | PROT_WRITE, 189*6fe65f1bSAlexei Starovoitov MAP_SHARED | MAP_ANONYMOUS, -1, 0); 190*6fe65f1bSAlexei Starovoitov if (addr == (void *) -1) 191*6fe65f1bSAlexei Starovoitov return NULL; 192*6fe65f1bSAlexei Starovoitov memcpy(addr, val, val_sz); 193*6fe65f1bSAlexei Starovoitov return addr; 194*6fe65f1bSAlexei Starovoitov } 195*6fe65f1bSAlexei Starovoitov 196*6fe65f1bSAlexei Starovoitov static inline void *skel_finalize_map_data(__u64 *init_val, size_t mmap_sz, int flags, int fd) 197*6fe65f1bSAlexei Starovoitov { 198*6fe65f1bSAlexei Starovoitov void *addr; 199*6fe65f1bSAlexei Starovoitov 200*6fe65f1bSAlexei Starovoitov addr = mmap((void *) (long) *init_val, mmap_sz, flags, MAP_SHARED | MAP_FIXED, fd, 0); 201*6fe65f1bSAlexei Starovoitov if (addr == (void *) -1) 202*6fe65f1bSAlexei Starovoitov return NULL; 203*6fe65f1bSAlexei Starovoitov return addr; 204*6fe65f1bSAlexei Starovoitov } 205*6fe65f1bSAlexei Starovoitov #endif 206*6fe65f1bSAlexei Starovoitov 20767234743SAlexei Starovoitov static inline int skel_closenz(int fd) 20867234743SAlexei Starovoitov { 20967234743SAlexei Starovoitov if (fd > 0) 21067234743SAlexei Starovoitov return close(fd); 21167234743SAlexei Starovoitov return -EINVAL; 21267234743SAlexei Starovoitov } 21367234743SAlexei Starovoitov 214e981f41fSAlexei Starovoitov #ifndef offsetofend 215e981f41fSAlexei Starovoitov #define offsetofend(TYPE, MEMBER) \ 216e981f41fSAlexei Starovoitov (offsetof(TYPE, MEMBER) + sizeof((((TYPE *)0)->MEMBER))) 217e981f41fSAlexei Starovoitov #endif 218e981f41fSAlexei Starovoitov 219e981f41fSAlexei Starovoitov static inline int skel_map_create(enum bpf_map_type map_type, 220e981f41fSAlexei Starovoitov const char *map_name, 221e981f41fSAlexei Starovoitov __u32 key_size, 222e981f41fSAlexei Starovoitov __u32 value_size, 223e981f41fSAlexei Starovoitov __u32 max_entries) 224e981f41fSAlexei Starovoitov { 225e981f41fSAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, map_extra); 226e981f41fSAlexei Starovoitov union bpf_attr attr; 227e981f41fSAlexei Starovoitov 228e981f41fSAlexei Starovoitov memset(&attr, 0, attr_sz); 229e981f41fSAlexei Starovoitov 230e981f41fSAlexei Starovoitov attr.map_type = map_type; 231e981f41fSAlexei Starovoitov strncpy(attr.map_name, map_name, sizeof(attr.map_name)); 232e981f41fSAlexei Starovoitov attr.key_size = key_size; 233e981f41fSAlexei Starovoitov attr.value_size = value_size; 234e981f41fSAlexei Starovoitov attr.max_entries = max_entries; 235e981f41fSAlexei Starovoitov 236e981f41fSAlexei Starovoitov return skel_sys_bpf(BPF_MAP_CREATE, &attr, attr_sz); 237e981f41fSAlexei Starovoitov } 238e981f41fSAlexei Starovoitov 239e981f41fSAlexei Starovoitov static inline int skel_map_update_elem(int fd, const void *key, 240e981f41fSAlexei Starovoitov const void *value, __u64 flags) 241e981f41fSAlexei Starovoitov { 242e981f41fSAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, flags); 243e981f41fSAlexei Starovoitov union bpf_attr attr; 244e981f41fSAlexei Starovoitov 245e981f41fSAlexei Starovoitov memset(&attr, 0, attr_sz); 246e981f41fSAlexei Starovoitov attr.map_fd = fd; 247e981f41fSAlexei Starovoitov attr.key = (long) key; 248e981f41fSAlexei Starovoitov attr.value = (long) value; 249e981f41fSAlexei Starovoitov attr.flags = flags; 250e981f41fSAlexei Starovoitov 251e981f41fSAlexei Starovoitov return skel_sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz); 252e981f41fSAlexei Starovoitov } 253e981f41fSAlexei Starovoitov 254c69f94a3SAlexei Starovoitov static inline int skel_raw_tracepoint_open(const char *name, int prog_fd) 255c69f94a3SAlexei Starovoitov { 256c69f94a3SAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint.prog_fd); 257c69f94a3SAlexei Starovoitov union bpf_attr attr; 258c69f94a3SAlexei Starovoitov 259c69f94a3SAlexei Starovoitov memset(&attr, 0, attr_sz); 260c69f94a3SAlexei Starovoitov attr.raw_tracepoint.name = (long) name; 261c69f94a3SAlexei Starovoitov attr.raw_tracepoint.prog_fd = prog_fd; 262c69f94a3SAlexei Starovoitov 263c69f94a3SAlexei Starovoitov return skel_sys_bpf(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz); 264c69f94a3SAlexei Starovoitov } 265c69f94a3SAlexei Starovoitov 266c69f94a3SAlexei Starovoitov static inline int skel_link_create(int prog_fd, int target_fd, 267c69f94a3SAlexei Starovoitov enum bpf_attach_type attach_type) 268c69f94a3SAlexei Starovoitov { 269c69f94a3SAlexei Starovoitov const size_t attr_sz = offsetofend(union bpf_attr, link_create.iter_info_len); 270c69f94a3SAlexei Starovoitov union bpf_attr attr; 271c69f94a3SAlexei Starovoitov 272c69f94a3SAlexei Starovoitov memset(&attr, 0, attr_sz); 273c69f94a3SAlexei Starovoitov attr.link_create.prog_fd = prog_fd; 274c69f94a3SAlexei Starovoitov attr.link_create.target_fd = target_fd; 275c69f94a3SAlexei Starovoitov attr.link_create.attach_type = attach_type; 276c69f94a3SAlexei Starovoitov 277c69f94a3SAlexei Starovoitov return skel_sys_bpf(BPF_LINK_CREATE, &attr, attr_sz); 278c69f94a3SAlexei Starovoitov } 279c69f94a3SAlexei Starovoitov 280*6fe65f1bSAlexei Starovoitov #ifdef __KERNEL__ 281*6fe65f1bSAlexei Starovoitov #define set_err 282*6fe65f1bSAlexei Starovoitov #else 283*6fe65f1bSAlexei Starovoitov #define set_err err = -errno 284*6fe65f1bSAlexei Starovoitov #endif 285*6fe65f1bSAlexei Starovoitov 28667234743SAlexei Starovoitov static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts) 28767234743SAlexei Starovoitov { 28867234743SAlexei Starovoitov int map_fd = -1, prog_fd = -1, key = 0, err; 28967234743SAlexei Starovoitov union bpf_attr attr; 29067234743SAlexei Starovoitov 291*6fe65f1bSAlexei Starovoitov err = map_fd = skel_map_create(BPF_MAP_TYPE_ARRAY, "__loader.map", 4, opts->data_sz, 1); 29267234743SAlexei Starovoitov if (map_fd < 0) { 29367234743SAlexei Starovoitov opts->errstr = "failed to create loader map"; 294*6fe65f1bSAlexei Starovoitov set_err; 29567234743SAlexei Starovoitov goto out; 29667234743SAlexei Starovoitov } 29767234743SAlexei Starovoitov 298e981f41fSAlexei Starovoitov err = skel_map_update_elem(map_fd, &key, opts->data, 0); 29967234743SAlexei Starovoitov if (err < 0) { 30067234743SAlexei Starovoitov opts->errstr = "failed to update loader map"; 301*6fe65f1bSAlexei Starovoitov set_err; 30267234743SAlexei Starovoitov goto out; 30367234743SAlexei Starovoitov } 30467234743SAlexei Starovoitov 30567234743SAlexei Starovoitov memset(&attr, 0, sizeof(attr)); 30667234743SAlexei Starovoitov attr.prog_type = BPF_PROG_TYPE_SYSCALL; 30767234743SAlexei Starovoitov attr.insns = (long) opts->insns; 30867234743SAlexei Starovoitov attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn); 30967234743SAlexei Starovoitov attr.license = (long) "Dual BSD/GPL"; 31067234743SAlexei Starovoitov memcpy(attr.prog_name, "__loader.prog", sizeof("__loader.prog")); 31167234743SAlexei Starovoitov attr.fd_array = (long) &map_fd; 31267234743SAlexei Starovoitov attr.log_level = opts->ctx->log_level; 31367234743SAlexei Starovoitov attr.log_size = opts->ctx->log_size; 31467234743SAlexei Starovoitov attr.log_buf = opts->ctx->log_buf; 31567234743SAlexei Starovoitov attr.prog_flags = BPF_F_SLEEPABLE; 316*6fe65f1bSAlexei Starovoitov err = prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr)); 31767234743SAlexei Starovoitov if (prog_fd < 0) { 31867234743SAlexei Starovoitov opts->errstr = "failed to load loader prog"; 319*6fe65f1bSAlexei Starovoitov set_err; 32067234743SAlexei Starovoitov goto out; 32167234743SAlexei Starovoitov } 32267234743SAlexei Starovoitov 32367234743SAlexei Starovoitov memset(&attr, 0, sizeof(attr)); 32467234743SAlexei Starovoitov attr.test.prog_fd = prog_fd; 32567234743SAlexei Starovoitov attr.test.ctx_in = (long) opts->ctx; 32667234743SAlexei Starovoitov attr.test.ctx_size_in = opts->ctx->sz; 3275d67f349SAlexei Starovoitov err = skel_sys_bpf(BPF_PROG_RUN, &attr, sizeof(attr)); 32867234743SAlexei Starovoitov if (err < 0 || (int)attr.test.retval < 0) { 32967234743SAlexei Starovoitov opts->errstr = "failed to execute loader prog"; 330e68ac008SKumar Kartikeya Dwivedi if (err < 0) { 331*6fe65f1bSAlexei Starovoitov set_err; 332e68ac008SKumar Kartikeya Dwivedi } else { 33367234743SAlexei Starovoitov err = (int)attr.test.retval; 334*6fe65f1bSAlexei Starovoitov #ifndef __KERNEL__ 335e68ac008SKumar Kartikeya Dwivedi errno = -err; 336*6fe65f1bSAlexei Starovoitov #endif 337e68ac008SKumar Kartikeya Dwivedi } 33867234743SAlexei Starovoitov goto out; 33967234743SAlexei Starovoitov } 34067234743SAlexei Starovoitov err = 0; 34167234743SAlexei Starovoitov out: 34267234743SAlexei Starovoitov if (map_fd >= 0) 34367234743SAlexei Starovoitov close(map_fd); 34467234743SAlexei Starovoitov if (prog_fd >= 0) 34567234743SAlexei Starovoitov close(prog_fd); 34667234743SAlexei Starovoitov return err; 34767234743SAlexei Starovoitov } 34867234743SAlexei Starovoitov 34967234743SAlexei Starovoitov #endif 350