mirror of https://github.com/proot-me/proot.git
Merge branch 'python-dev' of https://github.com/mickael-guene/PRoot into python-dev
Closes: https://github.com/proot-me/PRoot/pull/82
This commit is contained in:
commit
f01ace5de1
|
@ -9,7 +9,7 @@ compiler: gcc
|
|||
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq libtalloc-dev libarchive-dev uthash-dev gdb strace realpath
|
||||
- sudo apt-get install -qq libtalloc-dev libarchive-dev uthash-dev gdb strace realpath swig
|
||||
- sudo -H pip install cpp-coveralls==0.3.12
|
||||
|
||||
script: make -C src loader.exe loader-m32.exe build.h && env CFLAGS=--coverage LDFLAGS='--coverage' make -C src proot care && env PATH=/bin:/usr/bin:/sbin:/usr/sbin:$PWD/src PROOT_NO_SECCOMP=1 make -C tests
|
||||
|
|
|
@ -14,6 +14,9 @@ STRIP = $(CROSS_COMPILE)strip
|
|||
OBJCOPY = $(CROSS_COMPILE)objcopy
|
||||
OBJDUMP = $(CROSS_COMPILE)objdump
|
||||
|
||||
HAS_SWIG := $(shell swig -version 2>/dev/null)
|
||||
HAS_PYTHON_CONFIG := $(shell python2.7-config --ldflags 2>/dev/null)
|
||||
|
||||
CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -I. -I$(VPATH)
|
||||
CFLAGS += -Wall -Wextra -O2
|
||||
LDFLAGS += -ltalloc -Wl,-z,noexecstack
|
||||
|
@ -70,6 +73,13 @@ ifdef HAS_LOADER_32BIT
|
|||
OBJECTS += loader/loader-m32-wrapped.o
|
||||
endif
|
||||
|
||||
ifneq ($(and $(HAS_SWIG),$(HAS_PYTHON_CONFIG)),)
|
||||
OBJECTS += extension/python/python.o \
|
||||
extension/python/proot_wrap.o \
|
||||
extension/python/python_extension.o \
|
||||
extension/python/proot.o
|
||||
endif
|
||||
|
||||
CARE_OBJECTS = \
|
||||
cli/care.o \
|
||||
cli/care-manual.o \
|
||||
|
@ -108,6 +118,10 @@ CHECK_VERSION = VERSION=$$($(GIT) describe --tags --dirty --abbrev=8 --always 2>
|
|||
then /bin/echo -e "\#undef VERSION\n\#define VERSION \"$${VERSION}\""; \
|
||||
fi;
|
||||
|
||||
ifneq ($(and $(HAS_SWIG),$(HAS_PYTHON_CONFIG)),)
|
||||
CHECK_PYTHON_EXTENSION = /bin/echo -e "\#define HAVE_PYTHON_EXTENSION"
|
||||
endif
|
||||
|
||||
CHECK_FEATURES = process_vm seccomp_filter
|
||||
CHECK_PROGRAMS = $(foreach feature,$(CHECK_FEATURES),.check_$(feature))
|
||||
CHECK_OBJECTS = $(foreach feature,$(CHECK_FEATURES),.check_$(feature).o)
|
||||
|
@ -130,6 +144,7 @@ build.h: $(CHECK_RESULTS)
|
|||
$(Q)echo "#ifndef BUILD_H" >> $@
|
||||
$(Q)echo "#define BUILD_H" >> $@
|
||||
$(Q)sh -c '$(CHECK_VERSION)' >> $@
|
||||
$(Q)sh -c '$(CHECK_PYTHON_EXTENSION)' >> $@
|
||||
$(Q)cat $^ >> $@
|
||||
$(Q)echo "#endif /* BUILD_H */" >> $@
|
||||
|
||||
|
@ -175,6 +190,37 @@ cli/care-manual.o: manual cli/cli.o
|
|||
cli/%-licenses.o: licenses cli/cli.o
|
||||
$(OBJIFY)
|
||||
|
||||
######################################################################
|
||||
# Python extension
|
||||
|
||||
define build_python_extension
|
||||
CPPFLAGS += `python2.7-config --includes`
|
||||
LDFLAGS += `python2.7-config --ldflags`
|
||||
SWIG = swig
|
||||
quiet_SWIG = @echo " SWIG $$@"; swig
|
||||
|
||||
.INTERMEDIATE:python_extension.py
|
||||
python_extension.py: extension/python/python_extension.py
|
||||
$$(Q)cp $$< $$@
|
||||
extension/python/python_extension.o: python_extension.py cli/cli.o
|
||||
$$(OBJIFY)
|
||||
|
||||
.SECONDARY: proot_wrap.c proot.py
|
||||
proot_wrap.c proot.py: extension/python/proot.i
|
||||
$$($$(quiet)SWIG) -python -outcurrentdir -I$$(VPATH) $$(VPATH)/extension/python/proot.i
|
||||
|
||||
extension/python/proot.o: proot.py cli/cli.o
|
||||
$$(OBJIFY)
|
||||
|
||||
extension/python/proot_wrap.o: proot_wrap.c
|
||||
$$($$(quiet)CC) $$(CPPFLAGS) $$(CFLAGS) -MD -c $$< -o $$@
|
||||
|
||||
endef
|
||||
|
||||
ifneq ($(and $(HAS_SWIG),$(HAS_PYTHON_CONFIG)),)
|
||||
$(eval $(build_python_extension))
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# Build rules for the loader
|
||||
|
||||
|
@ -205,6 +251,7 @@ loader$1.exe: loader/loader$1
|
|||
|
||||
loader/loader$1-wrapped.o: loader$1.exe cli/cli.o
|
||||
$$(OBJIFY)
|
||||
|
||||
endef
|
||||
|
||||
$(eval $(build_loader))
|
||||
|
@ -230,7 +277,7 @@ BINDIR ?= $(PREFIX)/bin
|
|||
|
||||
.PHONY: clean distclean install install-care uninstall
|
||||
clean distclean:
|
||||
-$(RM) -f $(CHECK_OBJECTS) $(CHECK_PROGRAMS) $(CHECK_RESULTS) $(OBJECTS) $(CARE_OBJECTS) $(LOADER_OBJECTS) $(LOADER-m32_OBJECTS) proot care loader/loader loader/loader-m32 cli/care-manual.o $(DEPS) build.h licenses
|
||||
-$(RM) -f $(CHECK_OBJECTS) $(CHECK_PROGRAMS) $(CHECK_RESULTS) $(OBJECTS) $(CARE_OBJECTS) $(LOADER_OBJECTS) $(LOADER-m32_OBJECTS) proot care loader/loader loader/loader-m32 cli/care-manual.o $(DEPS) build.h licenses proot.py proot_wrap.c
|
||||
|
||||
install: proot
|
||||
$($(quiet)INSTALL) -D $< $(DESTDIR)$(BINDIR)/$<
|
||||
|
|
|
@ -323,6 +323,14 @@ static int handle_option_n(Tracee *tracee, const Cli *cli UNUSED, const char *va
|
|||
return status;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON_EXTENSION
|
||||
static int handle_option_P(Tracee *tracee, const Cli *cli UNUSED, const char *value)
|
||||
{
|
||||
(void) initialize_extension(tracee, python_callback, value);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize @tracee->qemu.
|
||||
*/
|
||||
|
|
|
@ -60,6 +60,9 @@ static int handle_option_0(Tracee *tracee, const Cli *cli, const char *value);
|
|||
static int handle_option_i(Tracee *tracee, const Cli *cli, const char *value);
|
||||
static int handle_option_p(Tracee *tracee, const Cli *cli, const char *value);
|
||||
static int handle_option_n(Tracee *tracee, const Cli *cli, const char *value);
|
||||
#ifdef HAVE_PYTHON_EXTENSION
|
||||
static int handle_option_P(Tracee *tracee, const Cli *cli, const char *value);
|
||||
#endif
|
||||
static int handle_option_R(Tracee *tracee, const Cli *cli, const char *value);
|
||||
static int handle_option_S(Tracee *tracee, const Cli *cli, const char *value);
|
||||
static int handle_option_kill_on_exit(Tracee *tracee, const Cli *cli, const char *value);
|
||||
|
@ -260,6 +263,16 @@ Copyright (C) 2015 STMicroelectronics, licensed under GPL v2 or later.",
|
|||
\tto run multiple instances of a same program without worrying about the same ports\n\
|
||||
\tbeing used twice.",
|
||||
},
|
||||
#ifdef HAVE_PYTHON_EXTENSION
|
||||
{ .class = "Extension options",
|
||||
.arguments = {
|
||||
{ .name = "-P", .separator = ' ', .value = "string" },
|
||||
{ .name = NULL, .separator = '\0', .value = NULL } },
|
||||
.handler = handle_option_p,
|
||||
.description = "Allow to access tracee information from python (experimental).",
|
||||
.detail = "\tThis option allow to launch a python script as an extension (experimental).",
|
||||
},
|
||||
#endif
|
||||
{ .class = "Alias options",
|
||||
.arguments = {
|
||||
{ .name = "-R", .separator = ' ', .value = "path" },
|
||||
|
|
|
@ -180,6 +180,7 @@ static inline int notify_extensions(Tracee *tracee, ExtensionEvent event,
|
|||
extern int kompat_callback(Extension *extension, ExtensionEvent event, intptr_t d1, intptr_t d2);
|
||||
extern int fake_id0_callback(Extension *extension, ExtensionEvent event, intptr_t d1, intptr_t d2);
|
||||
extern int care_callback(Extension *extension, ExtensionEvent event, intptr_t d1, intptr_t d2);
|
||||
extern int python_callback(Extension *extension, ExtensionEvent event, intptr_t d1, intptr_t d2);
|
||||
|
||||
/* Added extensions. */
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
%module proot
|
||||
%{
|
||||
#include "arch.h"
|
||||
#include "syscall/sysnum.h"
|
||||
#include "tracee/tracee.h"
|
||||
#include "tracee/reg.h"
|
||||
#include "tracee/mem.h"
|
||||
#include "extension/extension.h"
|
||||
|
||||
/* define an internal global with correct PR number */
|
||||
#define SYSNUM(item) static const int PR_internal ## item = PR_ ## item;
|
||||
#include "syscall/sysnums.list"
|
||||
#undef SYSNUM
|
||||
%}
|
||||
|
||||
/* now say PR_item has value PR_internal */
|
||||
/* works but ugly. Another way to do this ? */
|
||||
#define SYSNUM(item) static const int PR_ ## item = PR_internal ## item;
|
||||
%include "syscall/sysnums.list"
|
||||
#undef SYSNUM
|
||||
|
||||
/* python extension helper */
|
||||
%inline %{
|
||||
Tracee *get_tracee_from_extension(long extension_handle)
|
||||
{
|
||||
Extension *extension = (Extension *)extension_handle;
|
||||
Tracee *tracee = TRACEE(extension);
|
||||
|
||||
return tracee;
|
||||
}
|
||||
%}
|
||||
|
||||
/* arch.h */
|
||||
typedef unsigned long word_t;
|
||||
|
||||
/* tracee/tracee.h */
|
||||
typedef enum {
|
||||
CURRENT = 0,
|
||||
ORIGINAL = 1,
|
||||
MODIFIED = 2,
|
||||
NB_REG_VERSION
|
||||
} RegVersion;
|
||||
|
||||
/* syscall/sysnum.h */
|
||||
typedef enum Sysnum;
|
||||
extern Sysnum get_sysnum(const Tracee *tracee, RegVersion version);
|
||||
extern void set_sysnum(Tracee *tracee, Sysnum sysnum);
|
||||
|
||||
/* tracee/reg.h */
|
||||
typedef enum {
|
||||
SYSARG_NUM = 0,
|
||||
SYSARG_1,
|
||||
SYSARG_2,
|
||||
SYSARG_3,
|
||||
SYSARG_4,
|
||||
SYSARG_5,
|
||||
SYSARG_6,
|
||||
SYSARG_RESULT,
|
||||
STACK_POINTER,
|
||||
INSTR_POINTER,
|
||||
RTLD_FINI,
|
||||
STATE_FLAGS,
|
||||
USERARG_1,
|
||||
} Reg;
|
||||
|
||||
extern word_t peek_reg(const Tracee *tracee, RegVersion version, Reg reg);
|
||||
extern void poke_reg(Tracee *tracee, Reg reg, word_t value);
|
||||
|
||||
/* tracee/mem.h */
|
||||
/* make read_data / write_data pythonic */
|
||||
%apply (char *STRING, size_t LENGTH) { (const void *src_tracer, word_t size2) };
|
||||
extern int write_data(const Tracee *tracee, word_t dest_tracee, const void *src_tracer, word_t size2);
|
||||
|
||||
%include <cstring.i>
|
||||
%rename(read_data) read_data_for_python;
|
||||
%cstring_output_withsize(void *dest_tracer, int *size2);
|
||||
%inline %{
|
||||
void read_data_for_python(const Tracee *tracee, word_t src_tracee, void *dest_tracer, int *size2)
|
||||
{
|
||||
int res = read_data(tracee, dest_tracer, src_tracee, *size2);
|
||||
/* in case of error we return empty string */
|
||||
if (res)
|
||||
*size2 = 0;
|
||||
}
|
||||
%}
|
||||
|
||||
/* extension/extention.h */
|
||||
typedef enum {
|
||||
GUEST_PATH,
|
||||
HOST_PATH,
|
||||
SYSCALL_ENTER_START,
|
||||
SYSCALL_ENTER_END,
|
||||
SYSCALL_EXIT_START,
|
||||
SYSCALL_EXIT_END,
|
||||
NEW_STATUS,
|
||||
INHERIT_PARENT,
|
||||
INHERIT_CHILD,
|
||||
SYSCALL_CHAINED_ENTER,
|
||||
SYSCALL_CHAINED_EXIT,
|
||||
INITIALIZATION,
|
||||
REMOVED,
|
||||
PRINT_CONFIG,
|
||||
PRINT_USAGE,
|
||||
} ExtensionEvent;
|
|
@ -0,0 +1,185 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <Python.h>
|
||||
|
||||
#include "extension/extension.h"
|
||||
#include "cli/note.h"
|
||||
#include "path/temp.h"
|
||||
|
||||
/* FIXME: need to handle error code properly */
|
||||
|
||||
static PyObject *python_callback_func;
|
||||
|
||||
//static bool is_seccomp_disabling_done = false;
|
||||
/* List of syscalls handled by this extensions. */
|
||||
static FilteredSysnum filtered_sysnums[] = {
|
||||
FILTERED_SYSNUM_END,
|
||||
};
|
||||
|
||||
/* build by swig */
|
||||
extern void init_proot(void);
|
||||
|
||||
/* create python files */
|
||||
extern unsigned char _binary_python_extension_py_start;
|
||||
extern unsigned char _binary_python_extension_py_size;
|
||||
extern unsigned char _binary_proot_py_start;
|
||||
extern unsigned char _binary_proot_py_size;
|
||||
|
||||
static int create_python_file(const char *tmp_dir, const char *python_file_name, unsigned char *start_file, unsigned char *size_file)
|
||||
{
|
||||
void *start = (void *) start_file;
|
||||
size_t size = (size_t) size_file;
|
||||
char python_full_file_name[PATH_MAX];
|
||||
int fd;
|
||||
int status;
|
||||
|
||||
status = snprintf(python_full_file_name, PATH_MAX, "%s/%s", tmp_dir, python_file_name);
|
||||
if (status < 0 || status >= PATH_MAX) {
|
||||
status = -1;
|
||||
} else {
|
||||
fd = open(python_full_file_name, O_WRONLY | O_CREAT, S_IRWXU);
|
||||
if (fd >= 0) {
|
||||
status = write(fd, start, size);
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
return status>0?0:-1;
|
||||
}
|
||||
|
||||
static int create_python_extension(const char *tmp_dir)
|
||||
{
|
||||
return create_python_file(tmp_dir, "python_extension.py",
|
||||
&_binary_python_extension_py_start,
|
||||
&_binary_python_extension_py_size);
|
||||
}
|
||||
|
||||
static int create_proot(const char *tmp_dir)
|
||||
{
|
||||
return create_python_file(tmp_dir, "proot.py",
|
||||
&_binary_proot_py_start,
|
||||
&_binary_proot_py_size);
|
||||
}
|
||||
|
||||
/* init python once */
|
||||
void init_python_env()
|
||||
{
|
||||
static bool is_done = false;
|
||||
|
||||
if (!is_done) {
|
||||
char path_insert[PATH_MAX];
|
||||
PyObject *pName, *pModule;
|
||||
const char *tmp_dir;
|
||||
int status;
|
||||
|
||||
tmp_dir = create_temp_directory(NULL, "proot-python");
|
||||
status = snprintf(path_insert, PATH_MAX, "sys.path.insert(0, '%s')", tmp_dir);
|
||||
if (status < 0 || status >= PATH_MAX) {
|
||||
note(NULL, ERROR, USER, "Unable to create tmp directory\n");
|
||||
} else if (create_python_extension(tmp_dir) || create_proot(tmp_dir)) {
|
||||
note(NULL, ERROR, USER, "Unable to create python file\n");
|
||||
is_done = true;
|
||||
} else {
|
||||
Py_Initialize();
|
||||
init_proot();
|
||||
PyRun_SimpleString("import sys");
|
||||
PyRun_SimpleString(path_insert);
|
||||
pName = PyString_FromString("python_extension");
|
||||
if (pName) {
|
||||
pModule = PyImport_Import(pName);
|
||||
Py_DECREF(pName);
|
||||
if (pModule) {
|
||||
python_callback_func = PyObject_GetAttrString(pModule, "python_callback");
|
||||
if (python_callback_func && PyCallable_Check(python_callback_func))
|
||||
;//note(NULL, INFO, USER, "python_callback find\n");
|
||||
else
|
||||
note(NULL, ERROR, USER, "python_callback_func error\n");
|
||||
} else {
|
||||
PyErr_Print();
|
||||
note(NULL, ERROR, USER, "pModule error\n");
|
||||
}
|
||||
} else
|
||||
note(NULL, ERROR, USER, "pName error\n");
|
||||
is_done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* call python callback */
|
||||
static int python_callback_func_wrapper(Extension *extension, ExtensionEvent event, intptr_t data1, intptr_t data2)
|
||||
{
|
||||
int res = 0;
|
||||
PyObject *pArgs;
|
||||
PyObject *pValue;
|
||||
|
||||
pArgs = PyTuple_New(4);
|
||||
if (pArgs) {
|
||||
/* setargs */
|
||||
pValue = PyLong_FromLong((long) extension);
|
||||
if (!pValue)
|
||||
note(NULL, ERROR, USER, "pValue allocation failure\n");
|
||||
PyTuple_SetItem(pArgs, 0, pValue);
|
||||
|
||||
pValue = PyInt_FromLong(event);
|
||||
if (!pValue)
|
||||
note(NULL, ERROR, USER, "pValue allocation failure\n");
|
||||
PyTuple_SetItem(pArgs, 1, pValue);
|
||||
|
||||
pValue = PyInt_FromLong(data1);
|
||||
if (!pValue)
|
||||
note(NULL, ERROR, USER, "pValue allocation failure\n");
|
||||
PyTuple_SetItem(pArgs, 2, pValue);
|
||||
|
||||
pValue = PyInt_FromLong(data2);
|
||||
if (!pValue)
|
||||
note(NULL, ERROR, USER, "pValue allocation failure\n");
|
||||
PyTuple_SetItem(pArgs, 3, pValue);
|
||||
|
||||
/* call function */
|
||||
pValue = PyObject_CallObject(python_callback_func, pArgs);
|
||||
if (pValue != NULL) {
|
||||
res = PyInt_AsLong(pValue);
|
||||
Py_DECREF(pValue);
|
||||
} else {
|
||||
PyErr_Print();
|
||||
note(NULL, ERROR, USER, "fail to call callback\n");
|
||||
}
|
||||
Py_DECREF(pArgs);
|
||||
} else
|
||||
note(NULL, ERROR, USER, "pArgs allocation failure\n");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for this @extension. It is triggered each time an @event
|
||||
* occurred. See ExtensionEvent for the meaning of @data1 and @data2.
|
||||
*/
|
||||
int python_callback(Extension *extension, ExtensionEvent event, intptr_t data1, intptr_t data2)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
switch (event) {
|
||||
case INITIALIZATION:
|
||||
{
|
||||
/* not working. Use 'export PROOT_NO_SECCOMP=1' */
|
||||
/*if (!is_seccomp_disabling_done) {
|
||||
Tracee *tracee = TRACEE(extension);
|
||||
|
||||
if (tracee->seccomp == ENABLED)
|
||||
tracee->seccomp = DISABLING;
|
||||
is_seccomp_disabling_done = true;
|
||||
}*/
|
||||
init_python_env();
|
||||
res = python_callback_func_wrapper(extension, event, data1, data2);
|
||||
|
||||
extension->filtered_sysnums = filtered_sysnums;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
res = python_callback_func_wrapper(extension, event, data1, data2);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
from proot import *
|
||||
import ctypes
|
||||
import imp
|
||||
|
||||
client = None
|
||||
|
||||
def python_callback(extension, event, data1, data2):
|
||||
global client
|
||||
res = 0
|
||||
|
||||
if event == 11:
|
||||
if client:
|
||||
print "Already have a client => refuse to use %s" % (ctypes.string_at(data1))
|
||||
else:
|
||||
client = imp.load_source('client', ctypes.string_at(data1))
|
||||
if client:
|
||||
return client.python_callback(extension, event, data1, data2)
|
||||
|
||||
return 0
|
|
@ -0,0 +1,119 @@
|
|||
#!/bin/sh
|
||||
# Test for Python Extension for PRoot
|
||||
set -eu
|
||||
|
||||
# Check for test dependencies
|
||||
for cmd in mcookie cat grep rm find; do
|
||||
if ! command -v "${cmd}" > /dev/null; then
|
||||
exit 125
|
||||
fi
|
||||
done
|
||||
|
||||
# Check for PRoot binary
|
||||
if [ ! -e "${PROOT}" ]; then
|
||||
exit 125
|
||||
fi
|
||||
|
||||
# Check for python flag
|
||||
if ! "${PROOT}" --help | grep -- -p | grep string; then
|
||||
exit 125
|
||||
fi
|
||||
|
||||
TMP="$(mcookie)_hide.py"
|
||||
|
||||
# The following python script will hide all files
|
||||
cat > "/tmp/${TMP}" <<EOF
|
||||
import struct
|
||||
|
||||
from proot import *
|
||||
|
||||
class Dents(object):
|
||||
"""docstring for Dents"""
|
||||
def __init__(self):
|
||||
super(Dents, self).__init__()
|
||||
self.d_ino = 0
|
||||
self.d_off = 0
|
||||
self.d_reclen = 0
|
||||
self.d_name = None
|
||||
self.d_type = 0
|
||||
|
||||
def get_real_size(self, buf):
|
||||
res = 0
|
||||
for b in buf:
|
||||
if b == 0:
|
||||
return res
|
||||
res += 1
|
||||
return res
|
||||
|
||||
def unpack(self, buf):
|
||||
dirent_header_format = "LLH"
|
||||
(self.d_ino, self.d_off, self.d_reclen) = struct.unpack_from(dirent_header_format, buf)
|
||||
max_size = self.d_reclen - 2 - struct.calcsize(dirent_header_format)
|
||||
d_name = struct.unpack_from('%dB' % max_size, buf, struct.calcsize(dirent_header_format))
|
||||
real_size = self.get_real_size(d_name)
|
||||
(self.d_name, ) = struct.unpack_from('%ds' % real_size, buf, struct.calcsize(dirent_header_format))
|
||||
(self.d_type, ) = struct.unpack_from('B', buf, self.d_reclen - 1)
|
||||
|
||||
return self.d_reclen
|
||||
|
||||
def pack(self):
|
||||
dirent_header_size = struct.calcsize("LLH")
|
||||
d_name_length = len(self.d_name)
|
||||
d_reclen = d_name_length + 2 + dirent_header_size
|
||||
d_reclen = (d_reclen + 7) & ~7
|
||||
d_name_length = d_reclen - 2 - dirent_header_size
|
||||
buf = struct.pack('LLH%dsBB' % d_name_length, self.d_ino, self.d_off, self.d_reclen, self.d_name, 0, self.d_type)
|
||||
|
||||
return buf
|
||||
|
||||
def get_getdents(tracee, res, addr):
|
||||
dents = []
|
||||
buf = read_data(tracee, addr, res)
|
||||
pos = 0
|
||||
while pos < res:
|
||||
d = Dents()
|
||||
pos += d.unpack(buf[pos:])
|
||||
dents.append(d)
|
||||
|
||||
return dents
|
||||
|
||||
def put_dents(tracee, addr, dents):
|
||||
pos = 0
|
||||
for d in dents:
|
||||
buf = d.pack()
|
||||
write_data(tracee, pos + addr, buf)
|
||||
pos += len(buf)
|
||||
|
||||
poke_reg(tracee, SYSARG_RESULT, pos)
|
||||
|
||||
def filter_dents(dents):
|
||||
res = []
|
||||
for d in dents:
|
||||
#we remove all files
|
||||
if d.d_type != 8:
|
||||
res.append(d)
|
||||
|
||||
return res
|
||||
|
||||
def python_callback(extension, event, data1, data2):
|
||||
if event == SYSCALL_EXIT_END:
|
||||
tracee = get_tracee_from_extension(extension)
|
||||
no = get_sysnum(tracee, CURRENT)
|
||||
if no == PR_getdents:
|
||||
res = peek_reg(tracee, CURRENT, SYSARG_RESULT)
|
||||
if res > 0:
|
||||
addr = peek_reg(tracee, CURRENT, SYSARG_2)
|
||||
dents = get_getdents(tracee, res, addr)
|
||||
dents = filter_dents(dents)
|
||||
put_dents(tracee, addr, dents)
|
||||
|
||||
return 0
|
||||
EOF
|
||||
|
||||
# If script passes result from find will be empty
|
||||
if [ "$(env PROOT_NO_SECCOMP=1 "${PROOT}" -p "/tmp/${TMP}" find . -maxdepth 1 -type f)" ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf "/tmp/${TMP}" "/tmp/${TMP}c"
|
||||
|
Loading…
Reference in New Issue