Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

automatic fault discovery for cpython #642

Merged
merged 2 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -588,4 +588,53 @@ public void checkWildflyaddServletPre(int classID, int methodID, Object[] args)
SmithLogger.exception(e);
}
}

/*

public ManagedFilter addFilter(FilterInfo filterInfo)


*/

public void checkWildflyaddFilterPre(int classID, int methodID, Object[] args) {
SmithLogger.logger.info("checkWildflyaddFilter pre_hook call success");
if(args.length < 2) {
return ;
}

try {
Object filterInfo = args[1];
if(filterInfo != null) {
Class<?> filterClass = (Class<?>)Reflection.getField(filterInfo,"filterClass");
String filterName = (String)Reflection.getField(filterInfo,"name");

if(filterName != null) {
if (filterClass != null) {
if(SmithProbe.getInstance().classIsSended(filterClass)) {
return ;
}

ClassFilter classFilter = new ClassFilter();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这部分已经封装了API,可以直接调用sendMetadataObject

SmithHandler.queryClassFilter((Class<?>)filterClass, classFilter);

classFilter.setTransId();

classFilter.setRuleId(-1);
classFilter.setStackTrace(Thread.currentThread().getStackTrace());
if (client != null) {
client.write(Operate.SCANCLASS, classFilter);
client.write(Operate.COUNTMEMSHELL, classFilter);
SmithLogger.logger.info("send metadata: " + classFilter.toString());
// SmithProbe.getInstance().sendClass(filterClass, classFilter.getTransId());
}
} else {
SmithLogger.logger.warning("can't find "+filterName);
}
}
}
} catch (Exception e) {
SmithLogger.exception(e);
}
}
}

14 changes: 14 additions & 0 deletions rasp/jvm/JVMProbe/src/main/resources/class.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -353,3 +353,17 @@
- id: 0
name: connect
desc: (Ljava/net/SocketAddress;)Z
- id: 38
name: io.undertow.servlet.core.ManagedFilters
methods:
- id: 0
name: addFilter
desc: (Lio/undertow/servlet/api/FilterInfo;)Lio/undertow/servlet/core/ManagedFilter;
preHook: checkWildflyaddFilterPre
- id: 39
name: org.glassfish.web.loader.WebappClassLoader
methods:
- id: 0
name: addFilter
desc: (Lio/undertow/servlet/api/FilterInfo;)Lio/undertow/servlet/core/ManagedFilter;
preHook: checkWildflyaddFilterPre
14 changes: 13 additions & 1 deletion rasp/python/python-probe/rasp/probe/client/smith_message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
constexpr auto RUNTIME = "CPython";
constexpr auto PROBE_VERSION = "1.0.0";

extern int pid;

std::string getVersion() {
const char *version = Py_GetVersion();

Expand All @@ -17,7 +19,6 @@ std::string getVersion() {
}

void to_json(nlohmann::json &j, const SmithMessage &message) {
static pid_t pid = getpid();
static std::string version = getVersion();

j = {
Expand All @@ -44,6 +45,17 @@ void to_json(nlohmann::json &j, const Heartbeat &heartbeat) {
};
}

void to_json(nlohmann::json &j, const ExceptionInfo &exceptioninfo) {
j["signal_num"] = exceptioninfo.signal;

for (const auto &stackTrace: exceptioninfo.stackTrace) {
if (!*stackTrace)
break;

j["stack_trace"].push_back(stackTrace);
}
}

void to_json(nlohmann::json &j, const Trace &trace) {
j = {
{"class_id", trace.classID},
Expand Down
9 changes: 8 additions & 1 deletion rasp/python/python-probe/rasp/probe/client/smith_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ enum Operate {
DETECT,
FILTER,
BLOCK,
LIMIT
LIMIT,
EXCEPTIONINFO
};

struct ExceptionInfo {
int signal;
char stackTrace[FRAME_COUNT][FRAME_LENGTH];
};

struct SmithMessage {
Expand Down Expand Up @@ -101,6 +107,7 @@ void from_json(const nlohmann::json &j, SmithMessage &message);

void to_json(nlohmann::json &j, const Heartbeat &heartbeat);
void to_json(nlohmann::json &j, const Trace &trace);
void to_json(nlohmann::json &j, const ExceptionInfo &exceptioninfo);

void from_json(const nlohmann::json &j, MatchRule &rule);
void from_json(const nlohmann::json &j, Filter &filter);
Expand Down
43 changes: 43 additions & 0 deletions rasp/python/python-probe/rasp/probe/client/smith_probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ bool pass(const Trace &trace, const std::map<std::tuple<int, int>, Filter> &filt
return true;
}


void startProbe() {
gProbe->infoefd = -1;
int efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);

if (efd < 0) {
Expand All @@ -108,6 +110,16 @@ void startProbe() {
}

gProbe->efd = efd;

int infoefd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);

if (infoefd < 0) {
LOG_ERROR("create info event fd failed");
return;
}

gProbe->infoefd = infoefd;

std::fill_n(gProbe->quotas[0], sizeof(gProbe->quotas) / sizeof(**gProbe->quotas), DEFAULT_QUOTAS);

if (fork() != 0)
Expand Down Expand Up @@ -365,5 +377,36 @@ void startProbe() {
}
);

zero::async::promise::loop<void>(
[=, sender = sender, event = zero::ptr::makeRef<aio::ev::Event>(context, infoefd)](const auto &loop) {
std::optional<size_t> index = gProbe->info.acquire();

if (!index) {
gProbe->infowaiting = true;

event->on(EV_READ, 30s)->then([=](short what) {
if (what & EV_TIMEOUT) {
P_CONTINUE(loop);
return;
}

eventfd_t value;
eventfd_read(infoefd, &value);

P_CONTINUE(loop);
});

return;
}

ExceptionInfo info = gProbe->info[*index];
gProbe->info.release(*index);

sender->trySend({EXCEPTIONINFO, gProbe->info[*index]});

P_CONTINUE(loop);
}
);

context->dispatch();
}
4 changes: 4 additions & 0 deletions rasp/python/python-probe/rasp/probe/client/smith_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ constexpr auto BLOCK_RULE_LENGTH = 256;
constexpr auto BLOCK_RULE_MAX_COUNT = 8;

constexpr auto TRACE_BUFFER_SIZE = 100;
constexpr auto EXCEPTIONINFO_BUFFER_SIZE = 100;

constexpr auto MAX_POLICY_COUNT = 10;
constexpr auto PREPARED_POLICY_COUNT = 100;
Expand All @@ -31,11 +32,14 @@ struct Policy {
struct Probe {
#define gProbe Probe::getInstance()
int efd{-1};
int infoefd;
std::atomic<bool> waiting;
std::atomic<bool> infowaiting;
std::atomic<int> quotas[CLASS_MAX][METHOD_MAX];
z_rwlock_t locks[CLASS_MAX][METHOD_MAX];
std::pair<size_t, Policy *[MAX_POLICY_COUNT]> policies[CLASS_MAX][METHOD_MAX];
zero::atomic::CircularBuffer<Trace, TRACE_BUFFER_SIZE> buffer;
zero::atomic::CircularBuffer<ExceptionInfo, EXCEPTIONINFO_BUFFER_SIZE> info;
zero::atomic::CircularBuffer<Policy *, PREPARED_POLICY_COUNT> nodes;

Policy *popNode();
Expand Down
71 changes: 71 additions & 0 deletions rasp/python/python-probe/rasp/probe/library.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
#include "library.h"
#include "client/smith_probe.h"
#include <csignal>
#include <execinfo.h>
#include <sys/prctl.h>
#include <sys/eventfd.h>
#include <zero/log.h>
#include <re.h>

int pid = 0;

struct PyTrace : public PyObject, Trace {

};
Expand Down Expand Up @@ -178,10 +181,78 @@ constexpr PyMethodDef MODULE_METHODS[] = {
{nullptr, nullptr, 0, nullptr}
};

void send_exception_info(int sig) {
void *buffer[100];
struct ExceptionInfo exceptioninfo;
int nptrs = backtrace(buffer, 100);
char **stackstrings = backtrace_symbols(buffer, nptrs);
if(!stackstrings)
return ;

memset(&exceptioninfo,0,sizeof(struct ExceptionInfo));

exceptioninfo.signal = sig;
for (int i = 0; i < std::min(FRAME_COUNT, nptrs); i++) {
snprintf((char*)&exceptioninfo.stackTrace[i],FRAME_LENGTH,"%s",stackstrings[i]);
}

free(stackstrings);

std::optional<size_t> index = gProbe->info.reserve();

if (!index)
return;

gProbe->info[*index] = exceptioninfo;
gProbe->info.commit(*index);

if (gProbe->info.size() < EXCEPTIONINFO_BUFFER_SIZE / 2)
return;

bool expected = true;

if (!gProbe->infowaiting.compare_exchange_strong(expected, false))
return;

eventfd_t value = 1;
eventfd_write(gProbe->infoefd, value);
}

/*
void printinfo(int sig) {
void *buffer[100];
int nptrs = backtrace(buffer, 100);
char **strings = backtrace_symbols(buffer, nptrs);

printf("Caught signal %d:\n", sig);
printf("Backtrace:\n");
for (int i = 0; i < nptrs; i++) {
printf("%s\n", strings[i]);
}

free(strings);
}
*/

void signal_handler(int sig) {
//printinfo(sig);
send_exception_info(sig);
sleep(30);
exit(0);
}

INIT_FUNCTION(probe) {
if (!gProbe)
INIT_RETURN(nullptr);

signal(SIGTERM, signal_handler); // 15
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些信号处理函数,对于子进程能生效吗?

signal(SIGINT, signal_handler); // 2
signal(SIGSEGV, signal_handler); // 11
signal(SIGFPE, signal_handler); // 8
signal(SIGILL, signal_handler); // 4

pid = getpid();

auto nodes = (Policy *) allocShared(sizeof(Policy) * (PREPARED_POLICY_COUNT - 1));

if (!nodes)
Expand Down