Skip to content

Commit

Permalink
(#1108) IPC mechanism server side
Browse files Browse the repository at this point in the history
    - handle IPC mechanism communication between scoped application and
      CLI

    TODO:
    - CLI
    - integration test
    - IPC namespace switch

Closes: #1108
  • Loading branch information
michalbiesek committed Nov 24, 2022
1 parent 8e098d9 commit 14b5cfe
Show file tree
Hide file tree
Showing 13 changed files with 675 additions and 3 deletions.
22 changes: 22 additions & 0 deletions cli/cmd/inspect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package cmd

import (
"github.com/criblio/scope/inspect"
"github.com/spf13/cobra"
)

// inspectCmd represents the inspect command
var inspectCmd = &cobra.Command{
Use: "inspect [flags]",
Short: "Display scope inspect",
Long: `Outputs inspect info.`,
Example: `scope inspect`,
Args: cobra.NoArgs,
Run: func(cmd *cobra.Command, args []string) {
inspect.Inspect()
},
}

func init() {
RootCmd.AddCommand(inspectCmd)
}
9 changes: 9 additions & 0 deletions cli/inspect/inspect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package inspect

import "fmt"

// startConfig represents a processed configuration
func Inspect() error {
fmt.Println("inspect Test")
return nil
}
8 changes: 8 additions & 0 deletions docs/IPC.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# IPC Notes

- For IPC communication we are using pair of message queue:

- `scope` is responsible to create and read on `ScopeCLI`
- Scoped application is responsible to create and read `ScopeIPC.<PID>`

TODO: Picture
1 change: 1 addition & 0 deletions os/linux/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ coretest: export USER ?= $(shell id -u -n)
coretest: $(C_FILES) $(YAML_AR) $(JSON_AR) $(TEST_LIB)
@echo "$${CI:+::group::}Building Tests"
$(CC) -c $(TEST_CFLAGS) $(C_FILES) $(INCLUDES) $(TEST_INCLUDES)
$(CC) $(TEST_CFLAGS) -o test/$(OS)/ipctest ipctest.o ipc.o scopestdlib.o dbg.o test.o $(TEST_AR) $(TEST_LD_FLAGS)
$(CC) $(TEST_CFLAGS) -o test/$(OS)/vdsotest vdsotest.o scopestdlib.o dbg.o test.o $(TEST_AR) $(TEST_LD_FLAGS)
$(CC) $(TEST_CFLAGS) -o test/$(OS)/libvertest libvertest.o libver.o scopestdlib.o dbg.o test.o $(TEST_AR) $(TEST_LD_FLAGS)
$(CC) $(TEST_CFLAGS) -o test/$(OS)/libdirtest libdirtest.o libdir.o nsfile.o libver.o scopestdlib.o dbg.o test.o $(TEST_AR) $(TEST_LD_FLAGS)
Expand Down
2 changes: 1 addition & 1 deletion os/linux/aarch64.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ARCH_OBJ=$(ARCH)
LD_FLAGS=$(MUSL_AR) $(UNWIND_AR) $(PCRE2_AR) $(LS_HPACK_AR) $(YAML_AR) $(JSON_AR) -ldl -lpthread -lrt -lresolv -Lcontrib/build/funchook -lfunchook -Lcontrib/build/funchook/capstone_src-prefix/src/capstone_src-build -lcapstone -z noexecstack
INCLUDES=-I./contrib/libyaml/include -I./contrib/cJSON -I./os/$(OS) -I./contrib/pcre2/src -I./contrib/build/pcre2 -I./contrib/funchook/capstone_src/include/ -I./contrib/jni -I./contrib/jni/linux/ -I./contrib/openssl/include -I./contrib/build/openssl/include -I./contrib/build/libunwind/include -I./contrib/libunwind/include/

$(LIBSCOPE): src/wrap.c src/state.c src/httpstate.c src/metriccapture.c src/report.c src/httpagg.c src/plattime.c src/fn.c os/$(OS)/os.c src/cfgutils.c src/cfg.c src/transport.c src/log.c src/mtc.c src/circbuf.c src/linklist.c src/evtformat.c src/ctl.c src/mtcformat.c src/com.c src/scopestdlib.c src/dbg.c src/search.c src/scopeelf.c src/utils.c src/strset.c src/javabci.c src/javaagent.c
$(LIBSCOPE): src/wrap.c src/state.c src/httpstate.c src/metriccapture.c src/report.c src/httpagg.c src/plattime.c src/fn.c os/$(OS)/os.c src/cfgutils.c src/cfg.c src/transport.c src/log.c src/mtc.c src/circbuf.c src/linklist.c src/evtformat.c src/ctl.c src/mtcformat.c src/com.c src/scopestdlib.c src/dbg.c src/search.c src/scopeelf.c src/utils.c src/strset.c src/javabci.c src/javaagent.c src/ipc.c
@$(MAKE) -C contrib funchook pcre2 openssl ls-hpack musl libyaml libunwind cJSON
@echo "$${CI:+::group::}Building $@"
$(CC) $(CFLAGS) \
Expand Down
2 changes: 1 addition & 1 deletion os/linux/x86_64.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ INCLUDES=-I./contrib/libyaml/include -I./contrib/cJSON -I./os/$(OS) -I./contrib/
# objcopy -I binary -O elf64-x86-64 -B i386 ./lib/$(OS)/libscope.so ./lib/$(OS)/libscope.o && \
# rm -f ./lib/$(OS)/libscope.so

$(LIBSCOPE): src/wrap.c src/state.c src/httpstate.c src/metriccapture.c src/report.c src/httpagg.c src/plattime.c src/fn.c os/$(OS)/os.c src/cfgutils.c src/cfg.c src/transport.c src/log.c src/mtc.c src/circbuf.c src/linklist.c src/evtformat.c src/ctl.c src/mtcformat.c src/com.c src/scopestdlib.c src/dbg.c src/search.c src/sysexec.c src/gocontext.S src/scopeelf.c src/wrap_go.c src/utils.c src/strset.c src/javabci.c src/javaagent.c
$(LIBSCOPE): src/wrap.c src/state.c src/httpstate.c src/metriccapture.c src/report.c src/httpagg.c src/plattime.c src/fn.c os/$(OS)/os.c src/cfgutils.c src/cfg.c src/transport.c src/log.c src/mtc.c src/circbuf.c src/linklist.c src/evtformat.c src/ctl.c src/mtcformat.c src/com.c src/scopestdlib.c src/dbg.c src/search.c src/sysexec.c src/gocontext.S src/scopeelf.c src/wrap_go.c src/utils.c src/strset.c src/javabci.c src/javaagent.c src/ipc.c
@$(MAKE) -C contrib funchook pcre2 openssl ls-hpack musl libyaml cJSON libunwind
@echo "$${CI:+::group::}Building $@"
$(CC) $(CFLAGS) $(ARCH_CFLAGS) \
Expand Down
2 changes: 1 addition & 1 deletion os/macOS/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ $(PCRE2_AR):
cd contrib/pcre2/build && cmake ..
cd contrib/pcre2/build && make

libscope.so: src/wrap.c src/state.c src/httpstate.c src/report.c src/httpagg.c src/plattime.c src/fn.c os/$(OS)/os.c src/cfgutils.c src/cfg.c src/transport.c src/log.c src/mtc.c src/circbuf.c src/linklist.c src/evtformat.c src/ctl.c src/mtcformat.c src/com.c src/scopestdlib.c src/dbg.c src/search.c src/utils.c $(YAML_SRC) contrib/cJSON/cJSON.c
libscope.so: src/wrap.c src/state.c src/httpstate.c src/report.c src/httpagg.c src/plattime.c src/fn.c os/$(OS)/os.c src/cfgutils.c src/cfg.c src/transport.c src/log.c src/mtc.c src/circbuf.c src/linklist.c src/evtformat.c src/ctl.c src/mtcformat.c src/com.c src/scopestdlib.c src/dbg.c src/search.c src/utils.c $(YAML_SRC) contrib/cJSON/cJSON.c src/ipc.c
@echo "Building libscope.so ..."
make $(PCRE2_AR)
$(CC) $(CFLAGS) -shared -fvisibility=hidden -DSCOPE_VER=\"$(SCOPE_VER)\" $(YAML_DEFINES) -o ./lib/$(OS)/$@ $(INCLUDES) $^ -e,prog_version $(LD_FLAGS)
Expand Down
160 changes: 160 additions & 0 deletions src/ipc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
#define _GNU_SOURCE

#include "ipc.h"

/* Inter-process communication module based on the message-queue
*
* Message-queue system limits which are related to `ipcOpenConnection`
* are defined in following files:
*
* "/proc/sys/fs/mqueue/msg_max"
* - describes maximum number of messsages in a queue (QUEUE_MSG_MAX)
*
* "/proc/sys/fs/mqueue/msgsize_max"
* - describes maximum message size in a queue (QUEUE_MSG_SIZE)
*
* "/proc/sys/fs/mqueue/queues_max"
* - describes system-wide limit on the number of message queues that can be created
*
* See details in: https://man7.org/linux/man-pages/man7/mq_overview.7.html
*/

#define QUEUE_MSG_MAX 10
#define QUEUE_MSG_SIZE 8192

#define INPUT_CMD_LEN(x) (sizeof(x)-1)
#define CMD_TABLE_SIZE(x) (sizeof(x)/sizeof(x[0]))

/* Output message function definition
* Fills up the input buffer return the size of message
*
*/
typedef size_t (*out_msg_func_t)(char *, size_t);

static size_t
cmdGetAttach(char *buf, size_t len) {
// scope_snprintf(buf, len, "[%d] %s", g_proc.pid, g_cfg.funcs_attached ? "Attached" : "Detached");
// Excluding the terminating null byte
return scope_snprintf(buf, len, "GetAttach");
}

static size_t
cmdUnknown(char *buf, size_t len) {
// Excluding the terminating null byte
return scope_snprintf(buf, len, "Unknown");
}

typedef struct {
const char *name; // command name string [in]
size_t nameLen; // command name string length [in]
ipc_cmd_t cmd; // command id [out]
} input_cmd_table_t;

typedef struct {
ipc_cmd_t cmd; // command id [in]
out_msg_func_t func; // output func [out]
} output_cmd_table_t;

static int
ipcSend(mqd_t mqdes, const char *data, size_t len) {
return scope_mq_send(mqdes, data, len, 0);
}

static ssize_t
ipcRecv(mqd_t mqdes, char *buf, size_t len) {
return scope_mq_receive(mqdes, buf, len, 0);
}

mqd_t
ipcCreateNonBlockReadConnection(const char *name) {
struct mq_attr attr = {.mq_flags = 0,
.mq_maxmsg = QUEUE_MSG_MAX,
.mq_msgsize = QUEUE_MSG_SIZE,
.mq_curmsgs = 0};
return scope_mq_open(name, O_RDONLY | O_CREAT | O_CLOEXEC | O_NONBLOCK, 0666, &attr);
}

mqd_t
ipcOpenWriteConnection(const char *name) {
return scope_mq_open(name, O_WRONLY | O_NONBLOCK);
}

int
ipcCloseConnection(mqd_t mqdes) {
return scope_mq_close(mqdes);
}

int
ipcDestroyConnection(const char *name) {
return scope_mq_unlink(name);
}

long
ipcInfoMsgCount(mqd_t mqdes) {
struct mq_attr attr;
int res = scope_mq_getattr(mqdes, &attr);
if (res == 0) {
return attr.mq_curmsgs;
}
return -1;
}

bool
ipcIsActive(mqd_t mqdes) {
return mqdes != (mqd_t) -1;
}

bool
ipcRequestMsgHandler(mqd_t mqdes, ipc_cmd_t *cmdRes) {
// TODO do this dynamically based on mqdes
char buf[QUEUE_MSG_SIZE] = {0};

ssize_t recvLen = ipcRecv(mqdes, buf, sizeof(buf));
if (recvLen == -1) {
return FALSE;
}

// The length should be inline with outputCmdTable
input_cmd_table_t inputCmdTable[] = {
{"getStatus", INPUT_CMD_LEN("getStatus"), IPC_CMD_GET_ATTACH_STATUS}
};

for (int i = 0; i < CMD_TABLE_SIZE(inputCmdTable); ++i) {
if ((recvLen == inputCmdTable[i].nameLen) && !scope_memcmp(inputCmdTable[i].name, buf, recvLen)) {
*cmdRes = inputCmdTable[i].cmd;
return TRUE;
}
}
*cmdRes = IPC_CMD_UNKNOWN;
return TRUE;
}

bool
ipcResponseMsgHandler(mqd_t mqdes, ipc_cmd_t cmd) {
// TODO do this dynamically based on mqdes
char buf[QUEUE_MSG_SIZE] = {0};
size_t len;
if (cmd > IPC_CMD_UNKNOWN) {
return FALSE;
}

// The length should be inline with inputCmdTable
output_cmd_table_t outputCmdTable[] = {
{IPC_CMD_GET_ATTACH_STATUS, cmdGetAttach},
{IPC_CMD_UNKNOWN, cmdUnknown}
};

for (int i = 0; i < CMD_TABLE_SIZE(outputCmdTable); ++i) {
if (cmd == outputCmdTable[i].cmd) {
len = outputCmdTable[i].func(buf, sizeof(buf));
break;
}
}

int sendRes = ipcSend(mqdes, buf, len);
if (sendRes == -1) {
return FALSE;
}

return TRUE;
}
25 changes: 25 additions & 0 deletions src/ipc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef __IPC_H__
#define __IPC_H__

#include "scopestdlib.h"
#include "scopetypes.h"


typedef enum {
IPC_CMD_GET_ATTACH_STATUS, // Retrieve attach status
IPC_CMD_UNKNOWN, // Unknown command (Must be last)
} ipc_cmd_t;

// Manage Inter-process connection
mqd_t ipcCreateNonBlockReadConnection(const char *);
mqd_t ipcOpenWriteConnection(const char *);
int ipcCloseConnection(mqd_t);
int ipcDestroyConnection(const char *);
long ipcInfoMsgCount(mqd_t);
bool ipcIsActive(mqd_t);

// IPC Request/Response Handler
bool ipcRequestMsgHandler(mqd_t, ipc_cmd_t *);
bool ipcResponseMsgHandler(mqd_t, ipc_cmd_t);

#endif // __IPC_H__
45 changes: 45 additions & 0 deletions src/wrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "runtimecfg.h"
#include "javaagent.h"
#include "inject.h"
#include "ipc.h"
#include "scopestdlib.h"
#include "../contrib/libmusl/musl.h"

Expand All @@ -55,6 +56,7 @@ static const char *g_cmddir;
static list_t *g_nsslist;
static uint64_t reentrancy_guard = 0ULL;
static rlim_t g_max_fds = 0;
static mqd_t g_receiver_msg_q = (mqd_t) -1;

typedef int (*ssl_rdfunc_t)(SSL *, void *, int);
typedef int (*ssl_wrfunc_t)(SSL *, const void *, int);
Expand Down Expand Up @@ -423,6 +425,38 @@ cmdAttach(void)
return TRUE;
}


static void
mqConfig(void) {
if (ipcIsActive(g_receiver_msg_q) == FALSE) {
return;
}

long msgCount = ipcInfoMsgCount(g_receiver_msg_q);
if (msgCount <= 0) {
return;
}

ipc_cmd_t cmd = -1;

if (ipcRequestMsgHandler(g_receiver_msg_q, &cmd) == FALSE) {
return;
}

// Handle response
mqd_t cliMqDes = ipcOpenWriteConnection("/ScopeCLI");
if (ipcIsActive(cliMqDes) == FALSE) {
scopeLogError("/ScopeCLI is missing.");
return;
}

if (ipcResponseMsgHandler(cliMqDes, cmd) == FALSE) {
scopeLogError("Error: with sending answet to /ScopeCLI for cmd %d", cmd);
}

ipcCloseConnection(cliMqDes);
}

static void
remoteConfig()
{
Expand Down Expand Up @@ -1002,6 +1036,11 @@ handleExit(void)
ctlDisconnect(g_ctl, CFG_CTL);
logFlush(g_log);
logDisconnect(g_log);
ipcCloseConnection(g_receiver_msg_q);
g_receiver_msg_q = (mqd_t) -1;
char name[256];
scope_snprintf(name, sizeof(name), "/ScopeIPC.%d", g_proc.pid);
ipcDestroyConnection(name);
}

static void *
Expand Down Expand Up @@ -1081,6 +1120,7 @@ periodic(void *arg)
}
}
remoteConfig();
mqConfig();
}

return NULL;
Expand Down Expand Up @@ -1636,6 +1676,11 @@ init(void)
setMachineID(g_proc.machine_id);
setUUID(g_proc.uuid);

// Create IPC connection message queue
char name[256];
scope_snprintf(name, sizeof(name), "/ScopeIPC.%d", g_proc.pid);
g_receiver_msg_q = ipcCreateNonBlockReadConnection(name);

// initEnv() will set this TRUE if it detects `scope_attach_PID.env` in
// `/dev/shm` with our PID indicating we were injected into a running
// process.
Expand Down
1 change: 1 addition & 0 deletions test/execute.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ fi
declare -i ERR=0

run_test test/${OS}/vdsotest
run_test test/${OS}/ipctest
run_test test/${OS}/libvertest
run_test test/${OS}/libdirtest
run_test test/${OS}/nsinfotest
Expand Down
Loading

0 comments on commit 14b5cfe

Please sign in to comment.