- Go 1.25+
- Clang 12+
- LLVM toolchain
- libbpf development headers
- Linux kernel headers
# Install dependencies
./scripts/install-deps.sh
# Build all components
./scripts/build.sh
# Build with Docker image
./scripts/build.sh --dockerNeuroSentry/
├── cmd/neurosentry/ # Main application entry point
├── pkg/
│ ├── bpf/ # eBPF C programs
│ ├── agent/ # User-space agent logic
│ ├── config/ # Configuration handling
│ └── policy/ # Policy engine
├── deploy/
│ ├── docker/ # Docker builds
│ └── kubernetes/ # K8s manifests
├── docs/ # Documentation
└── scripts/ # Build and test scripts
- Define the hook in
pkg/bpf/neurosentry_lsm.c:
SEC("lsm/new_hook_name")
int BPF_PROG(my_new_hook, struct relevant_struct *arg) {
// Your logic here
return 0; // Return 0 for allow, -EPERM for deny
}- Generate Go bindings:
cd pkg/bpf
go generate ./...- Attach from Go code in
pkg/bpf/bpf.go:
l, err := link.AttachLSM(link.LSMOptions{
Program: objs.MyNewHook,
})
if err != nil {
return fmt.Errorf("attaching hook: %w", err)
}
m.links = append(m.links, l)- Define the uprobe in
pkg/bpf/neurosentry_uprobe.c:
SEC("uprobe")
int uprobe_my_function(struct pt_regs *ctx) {
// Access arguments via PT_REGS_PARM1(ctx), etc.
return 0;
}- Attach from Go:
exe, err := link.OpenExecutable("/path/to/binary")
if err != nil {
return err
}
uprobe, err := exe.Uprobe("function_name", objs.UprobeMyFunction, nil)
if err != nil {
return err
}
m.links = append(m.links, uprobe)- Define the component interface in
pkg/agent/:
type MyComponent struct {
cfg *config.Config
// Add fields
}
func NewMyComponent(cfg *config.Config) *MyComponent {
return &MyComponent{cfg: cfg}
}
func (c *MyComponent) Name() string {
return "my-component"
}
func (c *MyComponent) Start(ctx context.Context) error {
// Start logic
return nil
}
func (c *MyComponent) Stop() error {
// Stop logic
return nil
}- Register in controller:
// In Controller.initComponents()
myComp := NewMyComponent(c.cfg)
c.components = append(c.components, myComp)// In MetricsCollector
customMetric := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "neurosentry_custom_metric",
Help: "Description of metric",
},
[]string{"label1", "label2"},
)
// Register
prometheus.MustRegister(customMetric)
// Use
customMetric.WithLabelValues("value1", "value2").Inc()# Run all tests
./scripts/test.sh
# Run with coverage
./scripts/test.sh --coverage
# Run with linters
./scripts/test.sh --lintUse VM or container for eBPF testing:
# Start test VM
vagrant up
# Run tests in VM
vagrant ssh -c "cd /vagrant && sudo ./scripts/test.sh"# Start test environment
cd demos/test-environment
docker-compose up -d
# Run integration tests
go test -v ./tests/integration/...- Follow standard Go conventions
- Use
gofmtfor formatting - Run
golangci-lintbefore submitting PRs
go fmt ./...
golangci-lint run ./...- Use kernel coding style
- Keep programs under 4096 instructions ( verifier limit)
- Use helper functions for code reuse
- Add bpf_printk for debugging (remove in production)
# Enable verifier logs
echo 1 > /sys/kernel/debug/tracing/options/trace_printk
# View verifier output
bpftool prog dump xlated id <prog_id>
bpftool prog dump jited id <prog_id># Enable debug logs
sudo ./bin/neurosentry --log-level debug
# View ring buffer events
sudo bpftool map dump name events
# Check map contents
sudo bpftool map dump name trusted_pids# Trace BPF programs
bpftrace -e 'kprobe:bpf_prog_run_xdp { printf("XDP prog run\n"); }'- Fork the repository
- Create a feature branch
- Make changes with tests
- Run linting and tests
- Submit pull request
- Tests pass
- Code formatted (
go fmt) - Linter passes (
golangci-lint) - Documentation updated
- eBPF verifier happy
- No new security issues
For security vulnerabilities, email: tonghuaroot@gmail.com (subject prefix [NeuroSentry Security]). See SECURITY.md for details.
Do not open public issues for security problems.
- Update version in
cmd/neurosentry/main.go - Update CHANGELOG.md
- Create git tag
- Build release binaries
- Push to GitHub releases
- Build and push Docker images
# Tag release
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
# Build release binaries
./scripts/build-release.sh
# Build Docker images
docker build -t neurosentry:v1.0.0 .
docker push neurosentry:v1.0.0- Use per-CPU maps to avoid lock contention
- Batch operations when updating maps
- Use ring buffers instead of perf arrays
- Minimize string operations in kernel
- Use sync.Pool for frequently allocated objects
- Buffer channels appropriately
- Use binary unmarshaling for ring buffer data
- Profile with pprof
# Enable pprof
import _ "net/http/pprof"
# Analyze
go tool pprof http://localhost:2112/debug/pprof/profile