refactor: run python code without su -.

This commit is contained in:
liqiang-fit2cloud 2025-12-03 09:52:02 +08:00
parent 39d4ebc49c
commit 71f1e26c8f
3 changed files with 27 additions and 47 deletions

View File

@ -186,6 +186,7 @@ except Exception as e:
def generate_mcp_server_code(self, code_str, params):
python_paths = CONFIG.get_sandbox_python_package_paths().split(',')
code = self._generate_mcp_server_code(code_str, params)
set_run_user = f'os.setgid({pwd.getpwnam(self.user).pw_gid});os.setuid({pwd.getpwnam(self.user).pw_uid});' if self.sandbox else ''
return f"""
import os, sys, logging
logging.basicConfig(level=logging.WARNING)
@ -194,6 +195,7 @@ logging.getLogger("mcp.server").setLevel(logging.ERROR)
path_to_exclude = ['/opt/py3/lib/python3.11/site-packages', '/opt/maxkb-app/apps']
sys.path = [p for p in sys.path if p not in path_to_exclude]
sys.path += {python_paths}
{set_run_user}
os.environ.clear()
exec({dedent(code)!a})
"""
@ -202,30 +204,17 @@ exec({dedent(code)!a})
_code = self.generate_mcp_server_code(code, params)
maxkb_logger.debug(f"Python code of mcp tool: {_code}")
compressed_and_base64_encoded_code_str = base64.b64encode(gzip.compress(_code.encode())).decode()
if self.sandbox:
tool_config = {
'command': 'su',
'args': [
'-s', sys.executable,
'-c',
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
self.user,
],
'cwd': self.sandbox_path,
'env': {
'LD_PRELOAD': self.sandbox_so_path,
},
'transport': 'stdio',
}
else:
tool_config = {
'command': sys.executable,
'args': [
'-c',
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
],
'transport': 'stdio',
}
tool_config = {
'command': sys.executable,
'args': [
'-c',
f'import base64,gzip; exec(gzip.decompress(base64.b64decode(\'{compressed_and_base64_encoded_code_str}\')).decode())',
],
'env': {
'LD_PRELOAD': self.sandbox_so_path,
},
'transport': 'stdio',
}
return tool_config
def _exec(self, execute_file):

View File

@ -29,8 +29,6 @@ RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
mkdir -p /opt/maxkb-app/sandbox/lib && chmod -R 550 /opt/maxkb-app/sandbox && \
useradd --no-create-home --home /opt/maxkb-app/sandbox sandbox -g root && \
chmod g-xr /usr/local/bin/* /usr/bin/* /bin/* /usr/sbin/* /sbin/* /usr/lib/postgresql/17/bin/* && \
chmod g+xr /usr/bin/ld.so && \
chmod g+x /usr/local/bin/python* && \
chmod -R g-rwx /tmp /var/tmp /var/lock && \
apt-get clean all && \
rm -rf /var/lib/postgresql /var/lib/apt/lists/* /usr/share/doc/* /usr/share/man/* /usr/share/info/* /usr/share/locale/* /usr/share/lintian/* /usr/share/linda/* /var/cache/* /var/log/* /var/tmp/* /tmp/*

View File

@ -212,11 +212,6 @@ static int not_supported(const char *function_name) {
_exit(1);
return -1;
}
static pid_t ppid = 0;
// 在进程初始化时保存 PID
__attribute__((constructor)) static void init_sandbox() {
ppid = getpid();
}
#define RESOLVE_REAL(func) \
static typeof(func) *real_##func = NULL; \
if (!real_##func) { \
@ -224,22 +219,12 @@ __attribute__((constructor)) static void init_sandbox() {
}
int execv(const char *path, char *const argv[]) {
RESOLVE_REAL(execv);
// fprintf(stdout, "execv path: %s ppid=%d pid=%d\n", path, sandbox_pid, getpid());
if (!allow_create_subprocess()) {
// 只允许创建python进程但不允许python进程替换用os.execvp里又启动另一个python进程
if (strstr(path, "bin/python") == NULL || getpid() == ppid) {
return deny();
}
}
if (!allow_create_subprocess()) return deny();
return real_execv(path, argv);
}
int __execv(const char *path, char *const argv[]) {
RESOLVE_REAL(__execv);
if (!allow_create_subprocess()) {
if (strstr(path, "bin/python") == NULL || getpid() == ppid) {
return deny();
}
}
if (!allow_create_subprocess()) return deny();
return real___execv(path, argv);
}
int execve(const char *filename, char *const argv[], char *const envp[]) {
@ -259,16 +244,24 @@ int execveat(int dirfd, const char *pathname,
return real_execveat(dirfd, pathname, argv, envp, flags);
}
int execvpe(const char *file, char *const argv[], char *const envp[]) {
return not_supported("execvpe");
RESOLVE_REAL(execvpe);
if (!allow_create_subprocess()) return deny();
return real_execvpe(file, argv, envp);
}
int __execvpe(const char *file, char *const argv[], char *const envp[]) {
return not_supported("__execvpe");
RESOLVE_REAL(__execvpe);
if (!allow_create_subprocess()) return deny();
return real___execvpe(file, argv, envp);
}
int execvp(const char *file, char *const argv[]) {
return not_supported("execvp");
RESOLVE_REAL(execvp);
if (!allow_create_subprocess()) return deny();
return real_execvp(file, argv);
}
int __execvp(const char *file, char *const argv[]) {
return not_supported("__execvp");
RESOLVE_REAL(__execvp);
if (!allow_create_subprocess()) return deny();
return real___execvp(file, argv);
}
int execl(const char *path, const char *arg, ...) {
return not_supported("execl");