kubeshield / bpf-opa-demo

Apache License 2.0
30 stars 5 forks source link

falco maps and workflow #4

Open tahsinrahman opened 5 years ago

tahsinrahman commented 5 years ago
syscall_table_map
-----------------
key:    syscall_id
value:  flags
        enter_event_type
        exit_event_type

flags:
enum syscall_flags {
    UF_NONE = 0,
    UF_USED = (1 << 0),
    UF_NEVER_DROP = (1 << 1),
    UF_ALWAYS_DROP = (1 << 2),
    UF_SIMPLEDRIVER_KEEP = (1 << 3),
};

event_types:
    PPME_GENERIC_E = 0,
    PPME_GENERIC_X = 1,
    PPME_SYSCALL_OPEN_E = 2,
    PPME_SYSCALL_OPEN_X = 3,
    PPME_SYSCALL_CLOSE_E = 4,
    PPME_SYSCALL_CLOSE_X = 5,
    PPME_SYSCALL_READ_E = 6,
    PPME_SYSCALL_READ_X = 7,
    PPME_SYSCALL_WRITE_E = 8,
    PPME_SYSCALL_WRITE_X = 9,
    PPME_SYSCALL_BRK_1_E = 10,
    PPME_SYSCALL_BRK_1_X = 11

example:
key:                    __NR_open
value:
    flags:              UF_USED | UF_NEVER_DROP
    enter_event_type:   PPME_SYSCALL_OPEN_E
    exit_event_type:    PPME_SYSCALL_OPEN_X
tahsinrahman commented 5 years ago
filler_table_map
----------------
key:                PPME_GENERIC_E          PPME_GENERIC_X          PPME_SYSCALL_OPEN_E     PPME_SYSCALL_OPEN_X         
value:
    filler_id:      PPM_FILLER_sys_generic  PPM_FILLER_sys_generic  PPM_FILLER_sys_empty    PPME_SYSCALL_sys_open_x 
tahsinrahman commented 5 years ago
event_table_map
---------------
key:                PPME_GENERIC_E          PPME_GENERIC_X          PPME_SYSCALL_OPEN_E     PPME_SYSCALL_OPEN_X
value:
    name
    catagory
    flags
    no of params
    params:
        name
        type
        format

enum ppm_event_category {
    EC_UNKNOWN = 0, /* Unknown */
    EC_OTHER = 1,   /* No specific category */
    EC_FILE = 2,    /* File operation (open, close...) or file I/O */
    EC_NET = 3,     /* Network operation (socket, bind...) or network I/O */
    EC_IPC = 4,     /* IPC operation (pipe, futex...) or IPC I/O (e.g. on a pipe) */
    EC_MEMORY = 5,  /* Memory-related operation (e.g. brk) */
    EC_PROCESS = 6, /* Process-related operation (fork, clone...) */
    EC_SLEEP = 7,   /* Plain sleep */
    EC_SYSTEM = 8,  /* System-related operations (e.g. reboot) */
    EC_SIGNAL = 9,  /* Signal-related operations (e.g. signal) */
    EC_USER = 10,   /* User-related operations (e.g. getuid) */
    EC_TIME = 11,   /* Time-related syscalls (e.g. gettimeofday) */
    EC_PROCESSING = 12, /* User level processing. Never used for system calls */
    EC_IO_BASE = 32,/* used for masking */
    EC_IO_READ = 32,/* General I/O read (can be file, socket, IPC...) */
    EC_IO_WRITE = 33,/* General I/O write (can be file, socket, IPC...) */
    EC_IO_OTHER = 34,/* General I/O that is neither read not write (can be file, socket, IPC...) */
    EC_WAIT = 64,   /* General wait (can be file, socket, IPC...) */
    EC_SCHEDULER = 128, /* Scheduler event (e.g. context switch) */
    EC_INTERNAL = 256,  /* Internal event that shouldn't be shown to the user */
};

enum ppm_event_flags {
    EF_NONE = 0,
    EF_CREATES_FD = (1 << 0), /* This event creates an FD (e.g. open) */
    EF_DESTROYS_FD = (1 << 1), /* This event destroys an FD (e.g. close) */
    EF_USES_FD = (1 << 2), /* This event operates on an FD. */
    EF_READS_FROM_FD = (1 << 3), /* This event reads data from an FD. */
    EF_WRITES_TO_FD = (1 << 4), /* This event writes data to an FD. */
    EF_MODIFIES_STATE = (1 << 5), /* This event causes the machine state to change and should not be dropped by the filtering engine. */
    EF_UNUSED = (1 << 6), /* This event is not used */
    EF_WAITS = (1 << 7), /* This event reads data from an FD. */
    EF_SKIPPARSERESET = (1 << 8), /* This event shouldn't pollute the parser lastevent state tracker. */
    EF_OLD_VERSION = (1 << 9), /* This event is kept for backward compatibility */
    EF_DROP_FALCO = (1 << 10) /* This event should not be passed up to Falco */
};

params: what params this syscall takes
    name: eg: fd, path, flags, mode for open() syscall

enum ppm_param_type {
    PT_NONE = 0,
    PT_INT8 = 1,
    PT_INT16 = 2,
    PT_INT32 = 3,
    PT_INT64 = 4,
    PT_UINT8 = 5,
    PT_UINT16 = 6,
    PT_UINT32 = 7,
    PT_UINT64 = 8,
    PT_CHARBUF = 9, /* A printable buffer of bytes, NULL terminated */
    PT_BYTEBUF = 10, /* A raw buffer of bytes not suitable for printing */
    PT_ERRNO = 11,  /* this is an INT64, but will be interpreted as an error code */
    PT_SOCKADDR = 12, /* A sockaddr structure, 1byte family + data */
    PT_SOCKTUPLE = 13, /* A sockaddr tuple,1byte family + 12byte data + 12byte data */
    PT_FD = 14, /* An fd, 64bit */
    PT_PID = 15, /* A pid/tid, 64bit */
    PT_FDLIST = 16, /* A list of fds, 16bit count + count * (64bit fd + 16bit flags) */
    PT_FSPATH = 17, /* A string containing a relative or absolute file system path, null terminated */
    PT_SYSCALLID = 18, /* A 16bit system call ID. Can be used as a key for the g_syscall_info_table table. */
    PT_SIGTYPE = 19, /* An 8bit signal number */
    PT_RELTIME = 20, /* A relative time. Seconds * 10^9  + nanoseconds. 64bit. */
    PT_ABSTIME = 21, /* An absolute time interval. Seconds from epoch * 10^9  + nanoseconds. 64bit. */
    PT_PORT = 22, /* A TCP/UDP prt. 2 bytes. */
    PT_L4PROTO = 23, /* A 1 byte IP protocol type. */
    PT_SOCKFAMILY = 24, /* A 1 byte socket family. */
    PT_BOOL = 25, /* A boolean value, 4 bytes. */
    PT_IPV4ADDR = 26, /* A 4 byte raw IPv4 address. */
    PT_DYN = 27, /* Type can vary depending on the context. Used for filter fields like evt.rawarg. */
    PT_FLAGS8 = 28, /* this is an UINT8, but will be interpreted as 8 bit flags. */
    PT_FLAGS16 = 29, /* this is an UINT16, but will be interpreted as 16 bit flags. */
    PT_FLAGS32 = 30, /* this is an UINT32, but will be interpreted as 32 bit flags. */
    PT_UID = 31, /* this is an UINT32, MAX_UINT32 will be interpreted as no value. */
    PT_GID = 32, /* this is an UINT32, MAX_UINT32 will be interpreted as no value. */
    PT_DOUBLE = 33, /* this is a double precision floating point number. */
    PT_SIGSET = 34, /* sigset_t. I only store the lower UINT32 of it */
    PT_CHARBUFARRAY = 35,   /* Pointer to an array of strings, exported by the user events decoder. 64bit. For internal use only. */
    PT_CHARBUF_PAIR_ARRAY = 36, /* Pointer to an array of string pairs, exported by the user events decoder. 64bit. For internal use only. */
    PT_IPV4NET = 37, /* An IPv4 network. */
    PT_IPV6ADDR = 38, /* A 16 byte raw IPv6 address. */
    PT_IPV6NET = 39, /* An IPv6 network. */
    PT_IPADDR = 40,  /* Either an IPv4 or IPv6 address. The length indicates which one it is. */
    PT_IPNET = 41,  /* Either an IPv4 or IPv6 network. The length indicates which one it is. */
    PT_MAX = 42 /* array size */
};

enum ppm_print_format {
    PF_NA = 0,
    PF_DEC = 1, /* decimal */
    PF_HEX = 2, /* hexadecimal */
    PF_10_PADDED_DEC = 3, /* decimal padded to 10 digits, useful to print the fractional part of a ns timestamp */
    PF_ID = 4,
    PF_DIR = 5,
    PF_OCT = 6, /* octal */
};

example:
syscall_name:   "open"
event_flags:    EC_FILE, EF_CREATES_FD | EF_MODIFIES_STATE
no of params:   5
params:
    -   fd
        PT_FD
        PF_DEC
    -   name
        PT_FSPATH
        PF_NA
    -   flags
        PT_FLAGS32
        PF_HEX
    -   mode
        PT_UINT32
        PF_OCT
    -   dev
        PT_UINT32
        PF_HEX
tahsinrahman commented 5 years ago
Workflow
--------
raw_tracepoint sys_enter
------------------------

get syscall id
query syscall table(syscall_id)
get event pair()
    flags
    ppm_enter_event_type
    ppm_exit_event_type
    eg:
        UF_USED | UF_NEVER_DROP
        PPME_SYSCALL_OPEN_E
        PPME_SYSCALL_OPEN_X
if flag & UF_USED
    event_type = enter_event_type
    drop_flags = event.flags
else
    event_type = PPME_GENERIC_E
    drop_flag  = always_drop

call_filler(event_type, drop_flags)

call_filler
-----------
if drop_event(drop_flags) returns true
        return

filler_id = filler_table_map[event_type]
tail_call(filler_id)

tail_call
---------
init_filler_data()
    data.event          =   query event_info_table [event_type]
    data.filler_info    =   query filler_table     [event_type]

FILLER(sys_open_x)
    fd      get_argument(0)
    value_to_ring(fd)
        param_info = data.event.params
        switch param.type
            stores in data.buff[]

    name    get_argument(1)
    value_to_ring(name)

    flags
    mode
    device

push_event_frame(data)
    store data into perf_event_map