2017-11-18 19:09:20 +03:00
/* SPDX-License-Identifier: LGPL-2.1+ */
2016-10-18 18:57:10 +03:00
/***
This file is part of systemd .
Copyright 2016 Daniel Mack
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation ; either version 2.1 of the License , or
( at your option ) any later version .
systemd is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <fcntl.h>
# include <sys/stat.h>
# include <sys/types.h>
# include <unistd.h>
# include "alloc-util.h"
# include "bpf-program.h"
# include "fd-util.h"
# include "log.h"
# include "missing.h"
int bpf_program_new ( uint32_t prog_type , BPFProgram * * ret ) {
_cleanup_ ( bpf_program_unrefp ) BPFProgram * p = NULL ;
p = new0 ( BPFProgram , 1 ) ;
if ( ! p )
return log_oom ( ) ;
p - > prog_type = prog_type ;
p - > kernel_fd = - 1 ;
* ret = p ;
p = NULL ;
return 0 ;
}
BPFProgram * bpf_program_unref ( BPFProgram * p ) {
if ( ! p )
return NULL ;
safe_close ( p - > kernel_fd ) ;
free ( p - > instructions ) ;
return mfree ( p ) ;
}
int bpf_program_add_instructions ( BPFProgram * p , const struct bpf_insn * instructions , size_t count ) {
assert ( p ) ;
if ( ! GREEDY_REALLOC ( p - > instructions , p - > allocated , p - > n_instructions + count ) )
return - ENOMEM ;
memcpy ( p - > instructions + p - > n_instructions , instructions , sizeof ( struct bpf_insn ) * count ) ;
p - > n_instructions + = count ;
return 0 ;
}
int bpf_program_load_kernel ( BPFProgram * p , char * log_buf , size_t log_size ) {
union bpf_attr attr ;
assert ( p ) ;
if ( p - > kernel_fd > = 0 )
return - EBUSY ;
attr = ( union bpf_attr ) {
. prog_type = p - > prog_type ,
. insns = PTR_TO_UINT64 ( p - > instructions ) ,
. insn_cnt = p - > n_instructions ,
. license = PTR_TO_UINT64 ( " GPL " ) ,
. log_buf = PTR_TO_UINT64 ( log_buf ) ,
. log_level = ! ! log_buf ,
. log_size = log_size ,
} ;
p - > kernel_fd = bpf ( BPF_PROG_LOAD , & attr , sizeof ( attr ) ) ;
if ( p - > kernel_fd < 0 )
return - errno ;
return 0 ;
}
2017-09-21 21:38:07 +03:00
int bpf_program_cgroup_attach ( BPFProgram * p , int type , const char * path , uint32_t flags ) {
2016-10-18 18:57:10 +03:00
_cleanup_close_ int fd = - 1 ;
union bpf_attr attr ;
assert ( p ) ;
assert ( type > = 0 ) ;
assert ( path ) ;
fd = open ( path , O_DIRECTORY | O_RDONLY | O_CLOEXEC ) ;
if ( fd < 0 )
return - errno ;
attr = ( union bpf_attr ) {
. attach_type = type ,
. target_fd = fd ,
. attach_bpf_fd = p - > kernel_fd ,
2017-09-21 21:38:07 +03:00
. attach_flags = flags ,
2016-10-18 18:57:10 +03:00
} ;
if ( bpf ( BPF_PROG_ATTACH , & attr , sizeof ( attr ) ) < 0 )
return - errno ;
return 0 ;
}
int bpf_program_cgroup_detach ( int type , const char * path ) {
_cleanup_close_ int fd = - 1 ;
union bpf_attr attr ;
assert ( path ) ;
fd = open ( path , O_DIRECTORY | O_RDONLY | O_CLOEXEC ) ;
if ( fd < 0 )
return - errno ;
attr = ( union bpf_attr ) {
. attach_type = type ,
. target_fd = fd ,
} ;
if ( bpf ( BPF_PROG_DETACH , & attr , sizeof ( attr ) ) < 0 )
return - errno ;
return 0 ;
}
int bpf_map_new ( enum bpf_map_type type , size_t key_size , size_t value_size , size_t max_entries , uint32_t flags ) {
union bpf_attr attr = {
. map_type = type ,
. key_size = key_size ,
. value_size = value_size ,
. max_entries = max_entries ,
. map_flags = flags ,
} ;
int fd ;
fd = bpf ( BPF_MAP_CREATE , & attr , sizeof ( attr ) ) ;
if ( fd < 0 )
return - errno ;
return fd ;
}
int bpf_map_update_element ( int fd , const void * key , void * value ) {
union bpf_attr attr = {
. map_fd = fd ,
. key = PTR_TO_UINT64 ( key ) ,
. value = PTR_TO_UINT64 ( value ) ,
} ;
if ( bpf ( BPF_MAP_UPDATE_ELEM , & attr , sizeof ( attr ) ) < 0 )
return - errno ;
return 0 ;
}
int bpf_map_lookup_element ( int fd , const void * key , void * value ) {
union bpf_attr attr = {
. map_fd = fd ,
. key = PTR_TO_UINT64 ( key ) ,
. value = PTR_TO_UINT64 ( value ) ,
} ;
if ( bpf ( BPF_MAP_LOOKUP_ELEM , & attr , sizeof ( attr ) ) < 0 )
return - errno ;
return 0 ;
}