mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-02-27 13:57:26 +03:00
Add abstraction model for BPF programs
This object takes a number of bpf_insn members and wraps them together with the in-kernel reference id. Will be needed by the firewall code.
This commit is contained in:
parent
3f0c2342c0
commit
71e5200f94
@ -443,6 +443,8 @@ foreach ident : [
|
|||||||
#include <keyutils.h>'''],
|
#include <keyutils.h>'''],
|
||||||
['copy_file_range', '''#include <sys/syscall.h>
|
['copy_file_range', '''#include <sys/syscall.h>
|
||||||
#include <unistd.h>'''],
|
#include <unistd.h>'''],
|
||||||
|
['bpf', '''#include <sys/syscall.h>
|
||||||
|
#include <unistd.h>'''],
|
||||||
['explicit_bzero' , '''#include <string.h>'''],
|
['explicit_bzero' , '''#include <string.h>'''],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
182
src/basic/bpf-program.c
Normal file
182
src/basic/bpf-program.c
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
/***
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bpf_program_cgroup_attach(BPFProgram *p, int type, const char *path) {
|
||||||
|
_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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
55
src/basic/bpf-program.h
Normal file
55
src/basic/bpf-program.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/***
|
||||||
|
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/>.
|
||||||
|
|
||||||
|
[Except for the stuff copy/pasted from the kernel sources, see below]
|
||||||
|
***/
|
||||||
|
|
||||||
|
#include <linux/bpf.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
|
||||||
|
#include "list.h"
|
||||||
|
#include "macro.h"
|
||||||
|
|
||||||
|
typedef struct BPFProgram BPFProgram;
|
||||||
|
|
||||||
|
struct BPFProgram {
|
||||||
|
int kernel_fd;
|
||||||
|
uint32_t prog_type;
|
||||||
|
|
||||||
|
size_t n_instructions;
|
||||||
|
size_t allocated;
|
||||||
|
struct bpf_insn *instructions;
|
||||||
|
};
|
||||||
|
|
||||||
|
int bpf_program_new(uint32_t prog_type, BPFProgram **ret);
|
||||||
|
BPFProgram *bpf_program_unref(BPFProgram *p);
|
||||||
|
|
||||||
|
int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *insn, size_t count);
|
||||||
|
int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size);
|
||||||
|
|
||||||
|
int bpf_program_cgroup_attach(BPFProgram *p, int type, const char *path);
|
||||||
|
int bpf_program_cgroup_detach(int type, const char *path);
|
||||||
|
|
||||||
|
int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags);
|
||||||
|
int bpf_map_update_element(int fd, const void *key, void *value);
|
||||||
|
int bpf_map_lookup_element(int fd, const void *key, void *value);
|
||||||
|
|
||||||
|
DEFINE_TRIVIAL_CLEANUP_FUNC(BPFProgram*, bpf_program_unref);
|
@ -1,4 +1,6 @@
|
|||||||
basic_sources_plain = files('''
|
basic_sources_plain = files('''
|
||||||
|
MurmurHash2.c
|
||||||
|
MurmurHash2.h
|
||||||
af-list.c
|
af-list.c
|
||||||
af-list.h
|
af-list.h
|
||||||
alloc-util.c
|
alloc-util.c
|
||||||
@ -16,6 +18,8 @@ basic_sources_plain = files('''
|
|||||||
bitmap.c
|
bitmap.c
|
||||||
bitmap.h
|
bitmap.h
|
||||||
blkid-util.h
|
blkid-util.h
|
||||||
|
bpf-program.c
|
||||||
|
bpf-program.h
|
||||||
btrfs-ctree.h
|
btrfs-ctree.h
|
||||||
btrfs-util.c
|
btrfs-util.c
|
||||||
btrfs-util.h
|
btrfs-util.h
|
||||||
@ -24,10 +28,10 @@ basic_sources_plain = files('''
|
|||||||
bus-label.h
|
bus-label.h
|
||||||
calendarspec.c
|
calendarspec.c
|
||||||
calendarspec.h
|
calendarspec.h
|
||||||
capability-util.c
|
|
||||||
capability-util.h
|
|
||||||
cap-list.c
|
cap-list.c
|
||||||
cap-list.h
|
cap-list.h
|
||||||
|
capability-util.c
|
||||||
|
capability-util.h
|
||||||
cgroup-util.c
|
cgroup-util.c
|
||||||
cgroup-util.h
|
cgroup-util.h
|
||||||
chattr-util.c
|
chattr-util.c
|
||||||
@ -61,10 +65,10 @@ basic_sources_plain = files('''
|
|||||||
extract-word.h
|
extract-word.h
|
||||||
fd-util.c
|
fd-util.c
|
||||||
fd-util.h
|
fd-util.h
|
||||||
fileio.c
|
|
||||||
fileio.h
|
|
||||||
fileio-label.c
|
fileio-label.c
|
||||||
fileio-label.h
|
fileio-label.h
|
||||||
|
fileio.c
|
||||||
|
fileio.h
|
||||||
format-util.h
|
format-util.h
|
||||||
fs-util.c
|
fs-util.c
|
||||||
fs-util.h
|
fs-util.h
|
||||||
@ -82,9 +86,9 @@ basic_sources_plain = files('''
|
|||||||
hostname-util.h
|
hostname-util.h
|
||||||
in-addr-util.c
|
in-addr-util.c
|
||||||
in-addr-util.h
|
in-addr-util.h
|
||||||
ioprio.h
|
|
||||||
io-util.c
|
io-util.c
|
||||||
io-util.h
|
io-util.h
|
||||||
|
ioprio.h
|
||||||
journal-importer.c
|
journal-importer.c
|
||||||
journal-importer.h
|
journal-importer.h
|
||||||
khash.c
|
khash.c
|
||||||
@ -106,13 +110,11 @@ basic_sources_plain = files('''
|
|||||||
mempool.c
|
mempool.c
|
||||||
mempool.h
|
mempool.h
|
||||||
missing_syscall.h
|
missing_syscall.h
|
||||||
|
mkdir-label.c
|
||||||
mkdir.c
|
mkdir.c
|
||||||
mkdir.h
|
mkdir.h
|
||||||
mkdir-label.c
|
|
||||||
mount-util.c
|
mount-util.c
|
||||||
mount-util.h
|
mount-util.h
|
||||||
MurmurHash2.c
|
|
||||||
MurmurHash2.h
|
|
||||||
nss-util.h
|
nss-util.h
|
||||||
ordered-set.c
|
ordered-set.c
|
||||||
ordered-set.h
|
ordered-set.h
|
||||||
@ -138,9 +140,9 @@ basic_sources_plain = files('''
|
|||||||
rlimit-util.h
|
rlimit-util.h
|
||||||
rm-rf.c
|
rm-rf.c
|
||||||
rm-rf.h
|
rm-rf.h
|
||||||
securebits.h
|
|
||||||
securebits-util.c
|
securebits-util.c
|
||||||
securebits-util.h
|
securebits-util.h
|
||||||
|
securebits.h
|
||||||
selinux-util.c
|
selinux-util.c
|
||||||
selinux-util.h
|
selinux-util.h
|
||||||
set.h
|
set.h
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
|
|
||||||
/* Missing glibc definitions to access certain kernel APIs */
|
/* Missing glibc definitions to access certain kernel APIs */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#if !HAVE_DECL_PIVOT_ROOT
|
#if !HAVE_DECL_PIVOT_ROOT
|
||||||
static inline int pivot_root(const char *new_root, const char *put_old) {
|
static inline int pivot_root(const char *new_root, const char *put_old) {
|
||||||
return syscall(SYS_pivot_root, new_root, put_old);
|
return syscall(SYS_pivot_root, new_root, put_old);
|
||||||
@ -316,3 +318,33 @@ static inline ssize_t copy_file_range(int fd_in, loff_t *off_in,
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !HAVE_DECL_BPF
|
||||||
|
# ifndef __NR_bpf
|
||||||
|
# if defined __i386__
|
||||||
|
# define __NR_bpf 357
|
||||||
|
# elif defined __x86_64__
|
||||||
|
# define __NR_bpf 321
|
||||||
|
# elif defined __aarch64__
|
||||||
|
# define __NR_bpf 280
|
||||||
|
# elif defined __sparc__
|
||||||
|
# define __NR_bpf 349
|
||||||
|
# elif defined __s390__
|
||||||
|
# define __NR_bpf 351
|
||||||
|
# else
|
||||||
|
# warning "__NR_bpf not defined for your architecture"
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
union bpf_attr;
|
||||||
|
|
||||||
|
static inline int bpf(int cmd, union bpf_attr *attr, size_t size) {
|
||||||
|
#ifdef __NR_bpf
|
||||||
|
return (int) syscall(__NR_bpf, cmd, attr, size);
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user