garlic

package module
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 11, 2022 License: GPL-3.0 Imports: 8 Imported by: 0

README

GArLIC: GolAng LInux Connector

GARLIC is a simple proc connector interface for golang.

It's dead simple, and built on top of @mdlayher's gloang netlink library

The Proc Connector interface is mildly obscure, and you can read more here

Go Report Card CircleCI GoDoc

Tutorial

//Open a connection to the local Proc connector instance
//This requires root.
cn, err := DialPCN()
	if err != nil {
		log.Fatalf("%s", err)
	}

//Read in events
for {
    data, err := cn.ReadPCN()

	if err != nil {
		log.Errorf("Read fail: %s", err)
    }
	fmt.Printf("%#v\n", data)
}

//You can also filter by a list of events
cn, err := DialPCNWithEvents([]EventType{ProcEventGID, ProcEventExit})
	if err != nil {
		log.Fatalf("%s", err)
	}

Why?

Because it's fun. Also, garlic is my favorite seasoning.

What's next?

  • A CLI implementation is in the works.
  • Find a non-root way to run the tests.
  • Start looking at perf data
  • add new interfaces
  • Expand tests

Documentation

Overview

Package garlic is a simple proc connector interface for golang.

Index

Examples

Constants

View Source
const (
	//ProcCnMcastListen registers a listen event with the kernel
	ProcCnMcastListen = iota + 1
	//ProcCnMcastIgnore registers an ignore event with the kernel
	ProcCnMcastIgnore = iota
)
View Source
const CnIdxProc = 0x1

CnIdxProc is the Id used for proc/connector, and is a unique identifier which is used for message routing and must be registered in connector.h for in-kernel usage.

View Source
const CnValProc = 0x1

CnValProc is the corrisponding value used by chID, and is a unique identifier which is used for message routing and must be registered in connector.h for in-kernel usage.

Variables

This section is empty.

Functions

This section is empty.

Types

type CnConn

type CnConn struct {
	// contains filtered or unexported fields
}

CnConn contains the connection to the proc connector socket

func DialPCN

func DialPCN() (CnConn, error)

DialPCN connects to the proc connector socket, and returns a connection that will listens for all available event types: None, Fork, Execm UID, GID, SID, Ptrace, Comm, Coredump and Exit. The operation requires root.

Example

This example demonstrates garlic in the most simplistic use case: connect and read Proc connector requres root, and the underlying scoket returns an array from netlink

cn, err := DialPCN()
if err != nil {
	fmt.Printf("%s", err)
}

//Read in events
for {
	data, err := cn.ReadPCN()

	if err != nil {
		fmt.Printf("Read fail: %s", err)
	}
	fmt.Printf("%#v\n", data)
}
Output:

func DialPCNWithEvents

func DialPCNWithEvents(events []EventType) (CnConn, error)

DialPCNWithEvents is the same as DialPCN(), but with a filter that allows you select a particular proc event. It uses bitmasks and PBF to filter for the given events. This operation requires root.

Example

This demonstrates reading a specific array of selected events

cn, err := DialPCNWithEvents([]EventType{ProcEventGID, ProcEventExit})
if err != nil {
	fmt.Printf("%s", err)
}

//Read in events
for {
	data, err := cn.ReadPCN()

	if err != nil {
		fmt.Printf("Read fail: %s", err)
	}
	fmt.Printf("%#v\n", data)
}
Output:

func (CnConn) ClosePCN

func (c CnConn) ClosePCN() error

ClosePCN closes the netlink connection

func (CnConn) ReadPCN

func (c CnConn) ReadPCN() ([]ProcEvent, error)

ReadPCN reads waits for a Proc connector event to come across the nl socket, and returns an event struct This is a blocking operation

type Comm

type Comm struct {
	ProcessPid  uint32 `json:"process_pid" pretty:"Process PID"`
	ProcessTgid uint32 `json:"process_tgid" pretty:"Process TGID"`
	Comm        string `json:"command" pretty:"Command"`
}

Comm represents changes to the command name, /proc/$PID/comm

func (Comm) Pid

func (c Comm) Pid() uint32

Pid returns the event Process ID

func (Comm) Tgid

func (c Comm) Tgid() uint32

Tgid returns the event thread group ID

type Coredump

type Coredump struct {
	ProcessPid  uint32 `json:"process_pid" pretty:"Process PID"`
	ProcessTgid uint32 `json:"process_tgid" pretty:"Process TGID"`
}

Coredump is the event for...core dumps

func (Coredump) Pid

func (c Coredump) Pid() uint32

Pid returns the event Process ID

func (Coredump) Tgid

func (c Coredump) Tgid() uint32

Tgid returns the event thread group ID

type EventData

type EventData interface {
	Pid() uint32

	Tgid() uint32
}

EventData is an interface that encapsulates the union type used in cn_proc The PID and TGID fields are the only attributes shared by all the event types. Go get all the other fields, cast to a concrete type

type EventType

type EventType uint32

EventType is a type for carrying around the valid list of event types

const (

	//ProcEventNone is only used for ACK events
	ProcEventNone EventType = 0x00000000
	//ProcEventFork is a fork event
	ProcEventFork EventType = 0x00000001
	//ProcEventExec is a exec() event
	ProcEventExec EventType = 0x00000002
	//ProcEventUID is a user ID change
	ProcEventUID EventType = 0x00000004
	//ProcEventGID is a group ID change
	ProcEventGID EventType = 0x00000040
	//ProcEventSID is a session ID change
	ProcEventSID EventType = 0x00000080
	//ProcEventSID is a process trace event
	ProcEventPtrace EventType = 0x00000100
	//ProcEventComm is a comm(and) value change. Any value over 16 bytes will be truncated
	ProcEventComm EventType = 0x00000200
	//ProcEventCoredump is a core dump event
	ProcEventCoredump EventType = 0x40000000
	//ProcEventExit is an exit() event
	ProcEventExit EventType = 0x80000000
)

These types are taken from cn_proc.h, and represent all the known types that the proc connector will notify on

type Exec

type Exec struct {
	ProcessPid  uint32 `json:"proces_pid" pretty:"Process PID"`
	ProcessTgid uint32 `json:"process_tgid" pretty:"Process TGID"`
}

Exec is the event for process exec()s

func (Exec) Pid

func (e Exec) Pid() uint32

Pid returns the event Process ID

func (Exec) Tgid

func (e Exec) Tgid() uint32

Tgid returns the event thread group ID

type Exit

type Exit struct {
	ProcessPid  uint32 `json:"process_pid" pretty:"Process PID"`
	ProcessTgid uint32 `json:"process_tgid" pretty:"Process TGID"`
	ExitCode    uint32 `json:"exit_code" pretty:"Exit Code"`
	ExitSignal  uint32 `json:"exit_signal" pretty:"Exit Signal"`
}

Exit is the event for exit()

func (Exit) Pid

func (e Exit) Pid() uint32

Pid returns the event Process ID

func (Exit) Tgid

func (e Exit) Tgid() uint32

Tgid returns the event thread group ID

type Fork

type Fork struct {
	ParentPid  uint32 `json:"parent_pid" pretty:"Parent PID"`
	ParentTgid uint32 `josn:"parent_tgid" pretty:"Parent TGID"`
	ChildPid   uint32 `json:"child_pid" pretty:"Child PID"`
	ChildTgid  uint32 `json:"child_tgid" pretty:"Child TGID"`
}

Fork is the event for process forks

func (Fork) Pid

func (f Fork) Pid() uint32

Pid returns the event Process ID

func (Fork) Tgid

func (f Fork) Tgid() uint32

Tgid returns the event thread group ID

type ID

type ID struct {
	ProcessPid  uint32 `json:"process_pid" pretty:"Process PID"`
	ProcessTgid uint32 `json:"process_tgid" pretty:"Process TGID"`
	RealID      uint32 `json:"real_id" pretty:"Real ID"`
	EffectiveID uint32 `json:"effective_id" pretty:"Effective ID"`
}

ID represents UID/GID changes for a process. in cn_proc.h, the real/effective GID/UID is a series of union types, which Go does not have. creating a super-special interface for this would be overkill, So we're going to rename the vars and just use two. Consumers should use `what` to distinguish between the two.

func (ID) Pid

func (i ID) Pid() uint32

Pid returns the event Process ID

func (ID) Tgid

func (i ID) Tgid() uint32

Tgid returns the event thread group ID

type ProcEvent

type ProcEvent struct {
	WhatString string    `json:"event_string"`
	What       EventType `json:"event"`
	CPU        uint32    `json:"cpu"`
	Timestamp  time.Time `json:"timestamp"`
	EventData  EventData `json:"event_data"`
}

ProcEvent is the struct representing all the event data that comes across the wire, in parsed form.

type Ptrace

type Ptrace struct {
	ProcessPid  uint32 `json:"process_pid" pretty:"Process PID"`
	ProcessTgid uint32 `json:"process_tgid" pretty:"Process TGID"`
	TracerPid   uint32 `json:"tracrer_pid" pretty:"Tracer PID"`
	TracerTgid  uint32 `json:"tracer_tgid" pretty:"Tracer TGID"`
}

Ptrace is the event for ptrace events

func (Ptrace) Pid

func (p Ptrace) Pid() uint32

Pid returns the event Process ID

func (Ptrace) Tgid

func (p Ptrace) Tgid() uint32

Tgid returns the event thread group ID

type Sid

type Sid struct {
	ProcessPid  uint32 `json:"process_pid" pretty:"Process PID"`
	ProcessTgid uint32 `json:"process_tgid" pretty:"Process TGID"`
}

Sid is the event for Session ID changes

func (Sid) Pid

func (s Sid) Pid() uint32

Pid returns the event process ID

func (Sid) Tgid

func (s Sid) Tgid() uint32

Tgid returns the event thread group ID

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL