initial commit
This commit is contained in:
commit
72ead3f149
79
README.md
Normal file
79
README.md
Normal file
@ -0,0 +1,79 @@
|
||||
# 练手用的 LSM-BPF 模块
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 环境
|
||||
|
||||
- clang
|
||||
- 我的在 clang15,但是理论上略微旧一点没关系。如果提示头文件缺失或者是不支持 bpf target,请升级
|
||||
- kernel with BTF
|
||||
- 参考:https://github.com/aquasecurity/btfhub/blob/main/docs/supported-distros.md
|
||||
- golang 1.17+
|
||||
- bpftool
|
||||
- `bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h`
|
||||
- bpf2go
|
||||
- cilium 的工具
|
||||
|
||||
### 启动
|
||||
|
||||
- 一个终端
|
||||
```bash
|
||||
go build -o bin/demo
|
||||
sudo ./bin/demo $PWD
|
||||
```
|
||||
- 另一个终端
|
||||
```bash
|
||||
watch ls
|
||||
```
|
||||
- 如果要看日志(不要tail)
|
||||
```bash
|
||||
sudo cat /sys/kernel/debug/tracing/trace_pipe
|
||||
```
|
||||
|
||||
## 代码解释
|
||||
|
||||
### 内核态的 eBPF 程序: [./bpf/lsm.c](./bpf/lsm.c)
|
||||
|
||||
内核态程序主要是三部分:
|
||||
- 生成的 BTF 定义,这个理论上可以在支持 BTF 的发行版上直接用,不需要改
|
||||
- map: 内核和用户态通信的数据结构
|
||||
- hook: 入口点
|
||||
|
||||
和普通的 C 非常像,可以当 C 来写。但是栈空间只有 512 B。我没打错,就 512 Byte。
|
||||
|
||||
#### BTF 定义生成
|
||||
|
||||
```bash
|
||||
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
|
||||
```
|
||||
|
||||
#### map
|
||||
|
||||
map 不在栈空间中,一般用来让
|
||||
- 用户态配置 eBPF 程序
|
||||
- eBPF 程序向用户态传递结果或者性能数据
|
||||
|
||||
参考
|
||||
- https://docs.kernel.org/bpf/maps.html#map-types
|
||||
|
||||
#### hook
|
||||
|
||||
hook 就是一个函数,可以配置为在特定时机被 hook 点调起。
|
||||
|
||||
我们这个 demo 主要是希望尝试写 lsm 模块,比如说和 file_open 这个 hook 有关的信息在
|
||||
- https://github.com/torvalds/linux/blob/master/security/security.c#L2793
|
||||
|
||||
主要是需要关注 hook 需要接受的参数。
|
||||
|
||||
也有很多其他的 hook 点,比如说 kprobe 和 xdp 有关的。我们这个仓库暂时不关心。
|
||||
|
||||
### 用户态
|
||||
|
||||
用户态我选择了用 cilium 的 wrapper,理论上可以用 libbpf 啊或者类似的其他工具来实现。
|
||||
|
||||
### 构建
|
||||
|
||||
整体来说项目是
|
||||
- (一次性)生成 vmlinux.h
|
||||
- bpf2go 工具编译 ebpf 字节码,生成 stub
|
||||
- 编译 go 的二进制
|
2
bin/.gitignore
vendored
Normal file
2
bin/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
*
|
||||
!.gitignore
|
130
bpf/lsm.c
Normal file
130
bpf/lsm.c
Normal file
@ -0,0 +1,130 @@
|
||||
// generated by command: bpftool btf dump file /sys/kernel/btf/vmlinux format c
|
||||
// > vmlinux.h
|
||||
#include "vmlinux.h"
|
||||
|
||||
#include <bpf/bpf_core_read.h>
|
||||
#include <bpf/bpf_helpers.h>
|
||||
#include <bpf/bpf_tracing.h>
|
||||
#include <errno.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
char __license[] SEC("license") = "Dual MIT/GPL";
|
||||
|
||||
char log_fmt_timeout[] = "timeout: %lld %lld";
|
||||
|
||||
#define SECOND (1000 * 1000 * 1000)
|
||||
|
||||
typedef enum status {
|
||||
FILE_PROTECT_ENABLED,
|
||||
FILE_PROTECT_TICK,
|
||||
FILE_PROTECT_MAX,
|
||||
} file_protect_state;
|
||||
|
||||
typedef struct check_ctx {
|
||||
struct dentry *dentry;
|
||||
__u64 need_to_be_checked;
|
||||
__u64 return_value;
|
||||
} check_ctx;
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, FILE_PROTECT_MAX);
|
||||
__type(key, file_protect_state);
|
||||
__type(value, __u64);
|
||||
} states SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 256);
|
||||
__type(key, unsigned long);
|
||||
__type(value, __u8);
|
||||
} roots SEC(".maps");
|
||||
|
||||
struct {
|
||||
__uint(type, BPF_MAP_TYPE_HASH);
|
||||
__uint(max_entries, 1024 * 1024);
|
||||
__type(key, unsigned long);
|
||||
__type(value, __u64);
|
||||
} banned_access SEC(".maps");
|
||||
|
||||
#define MAX_PATH_FRAGEMENTS 256
|
||||
|
||||
static __u64 check_file_need_protection(struct bpf_map *map,
|
||||
unsigned long *inode, __u8 *enabled,
|
||||
check_ctx *ctx) {
|
||||
if (!*enabled) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dentry *dentry = ctx->dentry;
|
||||
int count_down = MAX_PATH_FRAGEMENTS;
|
||||
|
||||
// enumerate from the leaf to root
|
||||
while (count_down-- > 0 && dentry != NULL) {
|
||||
if (dentry->d_inode->i_ino == *inode) {
|
||||
ctx->need_to_be_checked = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __u64 check_service_status(struct bpf_map *map, file_protect_state *kind,
|
||||
__u64 *state, check_ctx *data) {
|
||||
__u64 now;
|
||||
switch (*kind) {
|
||||
case FILE_PROTECT_ENABLED:
|
||||
if (!*state) {
|
||||
data->need_to_be_checked = 0;
|
||||
data->return_value = 0;
|
||||
return 1; // early return to improve performance. return 1 means to stop
|
||||
// iteration.
|
||||
}
|
||||
break;
|
||||
case FILE_PROTECT_TICK:
|
||||
now = bpf_ktime_get_ns();
|
||||
// now - last > 3 seconds
|
||||
// but 3 * SECOND will overflow
|
||||
if ((now - *state) / 3 > SECOND) {
|
||||
data->return_value = EPERM;
|
||||
bpf_trace_printk(log_fmt_timeout, sizeof(log_fmt_timeout), now, *state);
|
||||
}
|
||||
break;
|
||||
case FILE_PROTECT_MAX: // this branch just tell clang to not complaint about
|
||||
// FILE_PROTECT_MAX
|
||||
// noop
|
||||
break;
|
||||
// default: // TAKE CARE!!!! default branch disable enum branch checking.
|
||||
// // noop
|
||||
// break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SEC("lsm/file_open")
|
||||
int BPF_PROG(check_file_open, struct file *file, int ret) {
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
check_ctx data = {
|
||||
.dentry = file->f_path.dentry,
|
||||
.need_to_be_checked = 0,
|
||||
.return_value = 0,
|
||||
};
|
||||
|
||||
bpf_for_each_map_elem(&roots, check_file_need_protection, &data, 0);
|
||||
|
||||
if (!data.need_to_be_checked) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
data.need_to_be_checked = 1;
|
||||
bpf_for_each_map_elem(&states, check_service_status, &data, 0);
|
||||
|
||||
if (!data.need_to_be_checked) {
|
||||
return 0;
|
||||
}
|
||||
return data.return_value;
|
||||
}
|
130595
bpf/vmlinux.h
Normal file
130595
bpf/vmlinux.h
Normal file
File diff suppressed because it is too large
Load Diff
127
fileprotector_bpfeb.go
Normal file
127
fileprotector_bpfeb.go
Normal file
@ -0,0 +1,127 @@
|
||||
// Code generated by bpf2go; DO NOT EDIT.
|
||||
//go:build arm64be || armbe || mips || mips64 || mips64p32 || ppc64 || s390 || s390x || sparc || sparc64
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
)
|
||||
|
||||
type FileProtectorFileProtectState uint32
|
||||
|
||||
// LoadFileProtector returns the embedded CollectionSpec for FileProtector.
|
||||
func LoadFileProtector() (*ebpf.CollectionSpec, error) {
|
||||
reader := bytes.NewReader(_FileProtectorBytes)
|
||||
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't load FileProtector: %w", err)
|
||||
}
|
||||
|
||||
return spec, err
|
||||
}
|
||||
|
||||
// LoadFileProtectorObjects loads FileProtector and converts it into a struct.
|
||||
//
|
||||
// The following types are suitable as obj argument:
|
||||
//
|
||||
// *FileProtectorObjects
|
||||
// *FileProtectorPrograms
|
||||
// *FileProtectorMaps
|
||||
//
|
||||
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||
func LoadFileProtectorObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||
spec, err := LoadFileProtector()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return spec.LoadAndAssign(obj, opts)
|
||||
}
|
||||
|
||||
// FileProtectorSpecs contains maps and programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type FileProtectorSpecs struct {
|
||||
FileProtectorProgramSpecs
|
||||
FileProtectorMapSpecs
|
||||
}
|
||||
|
||||
// FileProtectorSpecs contains programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type FileProtectorProgramSpecs struct {
|
||||
CheckFileOpen *ebpf.ProgramSpec `ebpf:"check_file_open"`
|
||||
}
|
||||
|
||||
// FileProtectorMapSpecs contains maps before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type FileProtectorMapSpecs struct {
|
||||
BannedAccess *ebpf.MapSpec `ebpf:"banned_access"`
|
||||
Roots *ebpf.MapSpec `ebpf:"roots"`
|
||||
States *ebpf.MapSpec `ebpf:"states"`
|
||||
}
|
||||
|
||||
// FileProtectorObjects contains all objects after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to LoadFileProtectorObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type FileProtectorObjects struct {
|
||||
FileProtectorPrograms
|
||||
FileProtectorMaps
|
||||
}
|
||||
|
||||
func (o *FileProtectorObjects) Close() error {
|
||||
return _FileProtectorClose(
|
||||
&o.FileProtectorPrograms,
|
||||
&o.FileProtectorMaps,
|
||||
)
|
||||
}
|
||||
|
||||
// FileProtectorMaps contains all maps after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to LoadFileProtectorObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type FileProtectorMaps struct {
|
||||
BannedAccess *ebpf.Map `ebpf:"banned_access"`
|
||||
Roots *ebpf.Map `ebpf:"roots"`
|
||||
States *ebpf.Map `ebpf:"states"`
|
||||
}
|
||||
|
||||
func (m *FileProtectorMaps) Close() error {
|
||||
return _FileProtectorClose(
|
||||
m.BannedAccess,
|
||||
m.Roots,
|
||||
m.States,
|
||||
)
|
||||
}
|
||||
|
||||
// FileProtectorPrograms contains all programs after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to LoadFileProtectorObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type FileProtectorPrograms struct {
|
||||
CheckFileOpen *ebpf.Program `ebpf:"check_file_open"`
|
||||
}
|
||||
|
||||
func (p *FileProtectorPrograms) Close() error {
|
||||
return _FileProtectorClose(
|
||||
p.CheckFileOpen,
|
||||
)
|
||||
}
|
||||
|
||||
func _FileProtectorClose(closers ...io.Closer) error {
|
||||
for _, closer := range closers {
|
||||
if err := closer.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Do not access this directly.
|
||||
//
|
||||
//go:embed fileprotector_bpfeb.o
|
||||
var _FileProtectorBytes []byte
|
BIN
fileprotector_bpfeb.o
Normal file
BIN
fileprotector_bpfeb.o
Normal file
Binary file not shown.
127
fileprotector_bpfel.go
Normal file
127
fileprotector_bpfel.go
Normal file
@ -0,0 +1,127 @@
|
||||
// Code generated by bpf2go; DO NOT EDIT.
|
||||
//go:build 386 || amd64 || amd64p32 || arm || arm64 || loong64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
)
|
||||
|
||||
type FileProtectorFileProtectState uint32
|
||||
|
||||
// LoadFileProtector returns the embedded CollectionSpec for FileProtector.
|
||||
func LoadFileProtector() (*ebpf.CollectionSpec, error) {
|
||||
reader := bytes.NewReader(_FileProtectorBytes)
|
||||
spec, err := ebpf.LoadCollectionSpecFromReader(reader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't load FileProtector: %w", err)
|
||||
}
|
||||
|
||||
return spec, err
|
||||
}
|
||||
|
||||
// LoadFileProtectorObjects loads FileProtector and converts it into a struct.
|
||||
//
|
||||
// The following types are suitable as obj argument:
|
||||
//
|
||||
// *FileProtectorObjects
|
||||
// *FileProtectorPrograms
|
||||
// *FileProtectorMaps
|
||||
//
|
||||
// See ebpf.CollectionSpec.LoadAndAssign documentation for details.
|
||||
func LoadFileProtectorObjects(obj interface{}, opts *ebpf.CollectionOptions) error {
|
||||
spec, err := LoadFileProtector()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return spec.LoadAndAssign(obj, opts)
|
||||
}
|
||||
|
||||
// FileProtectorSpecs contains maps and programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type FileProtectorSpecs struct {
|
||||
FileProtectorProgramSpecs
|
||||
FileProtectorMapSpecs
|
||||
}
|
||||
|
||||
// FileProtectorSpecs contains programs before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type FileProtectorProgramSpecs struct {
|
||||
CheckFileOpen *ebpf.ProgramSpec `ebpf:"check_file_open"`
|
||||
}
|
||||
|
||||
// FileProtectorMapSpecs contains maps before they are loaded into the kernel.
|
||||
//
|
||||
// It can be passed ebpf.CollectionSpec.Assign.
|
||||
type FileProtectorMapSpecs struct {
|
||||
BannedAccess *ebpf.MapSpec `ebpf:"banned_access"`
|
||||
Roots *ebpf.MapSpec `ebpf:"roots"`
|
||||
States *ebpf.MapSpec `ebpf:"states"`
|
||||
}
|
||||
|
||||
// FileProtectorObjects contains all objects after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to LoadFileProtectorObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type FileProtectorObjects struct {
|
||||
FileProtectorPrograms
|
||||
FileProtectorMaps
|
||||
}
|
||||
|
||||
func (o *FileProtectorObjects) Close() error {
|
||||
return _FileProtectorClose(
|
||||
&o.FileProtectorPrograms,
|
||||
&o.FileProtectorMaps,
|
||||
)
|
||||
}
|
||||
|
||||
// FileProtectorMaps contains all maps after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to LoadFileProtectorObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type FileProtectorMaps struct {
|
||||
BannedAccess *ebpf.Map `ebpf:"banned_access"`
|
||||
Roots *ebpf.Map `ebpf:"roots"`
|
||||
States *ebpf.Map `ebpf:"states"`
|
||||
}
|
||||
|
||||
func (m *FileProtectorMaps) Close() error {
|
||||
return _FileProtectorClose(
|
||||
m.BannedAccess,
|
||||
m.Roots,
|
||||
m.States,
|
||||
)
|
||||
}
|
||||
|
||||
// FileProtectorPrograms contains all programs after they have been loaded into the kernel.
|
||||
//
|
||||
// It can be passed to LoadFileProtectorObjects or ebpf.CollectionSpec.LoadAndAssign.
|
||||
type FileProtectorPrograms struct {
|
||||
CheckFileOpen *ebpf.Program `ebpf:"check_file_open"`
|
||||
}
|
||||
|
||||
func (p *FileProtectorPrograms) Close() error {
|
||||
return _FileProtectorClose(
|
||||
p.CheckFileOpen,
|
||||
)
|
||||
}
|
||||
|
||||
func _FileProtectorClose(closers ...io.Closer) error {
|
||||
for _, closer := range closers {
|
||||
if err := closer.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Do not access this directly.
|
||||
//
|
||||
//go:embed fileprotector_bpfel.o
|
||||
var _FileProtectorBytes []byte
|
BIN
fileprotector_bpfel.o
Normal file
BIN
fileprotector_bpfel.o
Normal file
Binary file not shown.
9
go.mod
Normal file
9
go.mod
Normal file
@ -0,0 +1,9 @@
|
||||
module git.jeffthecoder.xyz/public/demo-ebpf-lsm
|
||||
|
||||
go 1.21.0
|
||||
|
||||
require (
|
||||
github.com/cilium/ebpf v0.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
)
|
6
go.sum
Normal file
6
go.sum
Normal file
@ -0,0 +1,6 @@
|
||||
github.com/cilium/ebpf v0.11.0 h1:V8gS/bTCCjX9uUnkUFUpPsksM8n1lXBAvHcpiFk1X2Y=
|
||||
github.com/cilium/ebpf v0.11.0/go.mod h1:WE7CZAnqOL2RouJ4f1uyNhqr2P4CCvXFIqdRDUgWsVs=
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
111
main.go
Normal file
111
main.go
Normal file
@ -0,0 +1,111 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/cilium/ebpf"
|
||||
"github.com/cilium/ebpf/link"
|
||||
"github.com/cilium/ebpf/rlimit"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/cilium/ebpf/cmd/bpf2go FileProtector bpf/lsm.c -- -I./bpf -O2
|
||||
|
||||
/*
|
||||
#include <time.h>
|
||||
static unsigned long long get_nsecs(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
return (unsigned long long)ts.tv_sec * 1000000000UL + ts.tv_nsec;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
|
||||
const ( // bpf2go cannot restore enum to corresponding names. so i do it manually
|
||||
FileProtectorFileProtectStateEnabled FileProtectorFileProtectState = iota
|
||||
FileProtectorFileProtectStateTick
|
||||
FileProtectorFileProtectStateMax
|
||||
)
|
||||
|
||||
func main() {
|
||||
fDebug := flag.Bool("debug", false, "toggle to show full ebpf verifier error")
|
||||
flag.Parse()
|
||||
|
||||
if err := rlimit.RemoveMemlock(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fileProtectorObjects := FileProtectorObjects{}
|
||||
if err := LoadFileProtectorObjects(&fileProtectorObjects, &ebpf.CollectionOptions{
|
||||
Programs: ebpf.ProgramOptions{
|
||||
LogSize: ebpf.DefaultVerifierLogSize * 1024,
|
||||
},
|
||||
}); err != nil {
|
||||
var ve *ebpf.VerifierError
|
||||
if *fDebug && errors.As(err, &ve) {
|
||||
// Using %+v will print the whole verifier error, not just the last
|
||||
// few lines.
|
||||
fmt.Printf("Verifier error: %+v\n", ve)
|
||||
}
|
||||
log.Panic("failed to attach lsm: ", err)
|
||||
}
|
||||
defer fileProtectorObjects.Close()
|
||||
log.Println("lsm loaded")
|
||||
|
||||
lsm, err := link.AttachLSM(link.LSMOptions{
|
||||
Program: fileProtectorObjects.CheckFileOpen,
|
||||
})
|
||||
if err != nil {
|
||||
log.Panic("failed to attach lsm: ", err)
|
||||
}
|
||||
defer lsm.Close()
|
||||
log.Println("lsm attached")
|
||||
|
||||
log.Println("configure maps...")
|
||||
for _, path := range flag.Args() {
|
||||
path, _ = filepath.Abs(path)
|
||||
log.Println("-", path)
|
||||
stat, err := os.Stat(path)
|
||||
if err != nil {
|
||||
log.Println("W: ", err)
|
||||
continue
|
||||
}
|
||||
switch stat := stat.Sys().(type) {
|
||||
case *syscall.Stat_t:
|
||||
if err := fileProtectorObjects.FileProtectorMaps.Roots.Update(stat.Ino, uint8(1), ebpf.UpdateAny); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
default:
|
||||
log.Printf("W: incompatible type of stat: %T", stat)
|
||||
continue
|
||||
}
|
||||
}
|
||||
// you should also protect the daemon config itself
|
||||
|
||||
log.Println("configuration done. enabling...")
|
||||
|
||||
if err := fileProtectorObjects.FileProtectorMaps.States.Update(FileProtectorFileProtectStateEnabled, uint64(1), ebpf.UpdateAny); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(time.Second * 10)
|
||||
defer ticker.Stop()
|
||||
log.Println("ticking...but with one step slower intentionally!")
|
||||
for {
|
||||
now := uint64(C.get_nsecs())
|
||||
log.Println("tick:", now)
|
||||
|
||||
if err := fileProtectorObjects.FileProtectorMaps.States.Update(FileProtectorFileProtectStateTick, uint64(now), ebpf.UpdateAny); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
<-ticker.C
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user