Skip to content

Commit 841aaf1

Browse files
committed
Add more information to debug logs.
1 parent 0f29797 commit 841aaf1

File tree

4 files changed

+152
-99
lines changed

4 files changed

+152
-99
lines changed

.vscode/settings.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
"getegid",
2525
"geteuid",
2626
"getpid",
27+
"getresgid",
28+
"getresuid",
29+
"gids",
2730
"gotmp",
2831
"gvisor",
2932
"iputils",
@@ -85,9 +88,11 @@
8588
"submounts",
8689
"syscall",
8790
"tmpfs",
91+
"uids",
8892
"UNSTARTED",
8993
"updatecheck",
9094
"urandom",
95+
"userns",
9196
"userspace",
9297
"webui",
9398
"yfinance",

open-webui/functions/run_code.py

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,8 @@ class Sandbox:
12511251
"/proc/cgroups",
12521252
"/proc/mounts",
12531253
"/proc/version",
1254+
"/proc/sys/kernel/unprivileged_userns_clone",
1255+
"/proc/sys/kernel/unprivileged_userns_apparmor_policy",
12541256
)
12551257

12561258
# Other commands worth running when dumping debug logs.
@@ -1372,8 +1374,9 @@ def __init__(self, libc, log_path, max_sandbox_ram_bytes, do_resource_limiting):
13721374
self._log_path = log_path
13731375
self._max_sandbox_ram_bytes = max_sandbox_ram_bytes
13741376
self._do_resource_limiting = do_resource_limiting
1375-
self._my_euid = None
1376-
self._my_egid = None
1377+
self._my_uids = None
1378+
self._my_gids = None
1379+
self._initial_status_data = None
13771380
self._checkpoint = None
13781381
self._cgroup_controllers = None
13791382
self._needed_controllers = set()
@@ -1386,6 +1389,7 @@ def __init__(self, libc, log_path, max_sandbox_ram_bytes, do_resource_limiting):
13861389
# Save EUID and EGID before we move to a new user namespace.
13871390
("save_euid", self._save_euid),
13881391
("save_egid", self._save_egid),
1392+
("save_proc_self_status", self._save_proc_self_status),
13891393
("unshare_user", self._unshare_user),
13901394
# Map our current user as being root in the new user namespace.
13911395
("write_uid_map", self._write_uid_map),
@@ -1530,19 +1534,8 @@ def __init__(self, libc, log_path, max_sandbox_ram_bytes, do_resource_limiting):
15301534
)
15311535
)
15321536

1533-
def _status(self):
1534-
"""
1535-
Return the current switcheroo status.
1536-
1537-
:return: The last successful operation name, "UNSTARTED" if unstarted, or "OK" if all done, and some information.
1538-
"""
1539-
main_status = self._checkpoint
1540-
if self._checkpoint is None:
1541-
main_status = "UNSTARTED"
1542-
if self._checkpoint == self._operations[-1][0]:
1543-
main_status = "OK"
1544-
my_pid = os.getpid()
1545-
status_line = f"{main_status} (euid={self._my_euid} egid={self._my_egid} pid={my_pid} do_resource_limiting={self._do_resource_limiting} initial_cgroup_name={self._initial_cgroup_name} codeeval_cgroup_name={self._codeeval_cgroup_name} controllers={self._cgroup_controllers})"
1537+
def _read_proc_self_status(self):
1538+
"""Read /proc/self/status and return some of it as a dictionary."""
15461539
want_headers = (
15471540
"Name",
15481541
"Umask",
@@ -1562,20 +1555,35 @@ def _status(self):
15621555
"Seccomp",
15631556
"Seccomp_filters",
15641557
)
1565-
got_headers = {}
1558+
status_data = {}
1559+
with self._open("/proc/self/status", "rb") as status_f:
1560+
for line in status_f.read().decode("utf-8").splitlines():
1561+
for header in want_headers:
1562+
if line.startswith(f"{header}:"):
1563+
status_data[header] = line.split(":")[1].strip()
1564+
break
1565+
return status_data
1566+
1567+
def _status(self):
1568+
"""
1569+
Return the current switcheroo status.
1570+
1571+
:return: The last successful operation name, "UNSTARTED" if unstarted, or "OK" if all done, and some information.
1572+
"""
1573+
main_status = self._checkpoint
1574+
if self._checkpoint is None:
1575+
main_status = "UNSTARTED"
1576+
if self._checkpoint == self._operations[-1][0]:
1577+
main_status = "OK"
1578+
my_pid = os.getpid()
1579+
status_line = f"{main_status} (uids={self._my_uids} gids={self._my_gids} pid={my_pid} initial_proc_self_status={self._initial_status_data} do_resource_limiting={self._do_resource_limiting} initial_cgroup_name={self._initial_cgroup_name} codeeval_cgroup_name={self._codeeval_cgroup_name} controllers={self._cgroup_controllers})"
15661580
try:
1567-
with self._open("/proc/self/status", "rb") as status_f:
1568-
for line in status_f.read().decode("utf-8").splitlines():
1569-
for header in want_headers:
1570-
if line.startswith(f"{header}:"):
1571-
got_headers[header] = line.split(":")[1].strip()
1572-
break
1581+
status_data = self._read_proc_self_status()
15731582
except OSError as e:
1574-
status_line += f" (error opening /proc/self/status: {e})"
1583+
status_line += f" (error parsing /proc/self/status: {e})"
15751584
else:
1576-
for header in want_headers:
1577-
got_value = got_headers.get(header)
1578-
status_line += f" {header}={got_value}"
1585+
for header, value in status_data.items():
1586+
status_line += f" {header}={value}"
15791587
if self._do_resource_limiting:
15801588
cgroupfs_data = []
15811589
for cgroup_components in (
@@ -1738,10 +1746,13 @@ def _open(self, path, mode):
17381746
raise OSError(f"opening {path} mode={mode}: {e}")
17391747

17401748
def _save_euid(self):
1741-
self._my_euid = os.geteuid()
1749+
self._my_uids = os.getresuid()
17421750

17431751
def _save_egid(self):
1744-
self._my_egid = os.getegid()
1752+
self._my_gids = os.getresgid()
1753+
1754+
def _save_proc_self_status(self):
1755+
self._initial_status_data = self._read_proc_self_status()
17451756

17461757
def _unshare_user(self):
17471758
Sandbox.unshare(
@@ -1750,15 +1761,15 @@ def _unshare_user(self):
17501761

17511762
def _write_uid_map(self):
17521763
with self._open("/proc/self/uid_map", "wb") as uid_map_f:
1753-
uid_map_f.write(f"0 {self._my_euid} 1\n".encode("ascii"))
1764+
uid_map_f.write(f"0 {self._my_uids[1]} 1\n".encode("ascii"))
17541765

17551766
def _write_setgroups(self):
17561767
with self._open("/proc/self/setgroups", "wb") as setgroups_f:
17571768
setgroups_f.write(b"deny")
17581769

17591770
def _write_gid_map(self):
17601771
with self._open("/proc/self/gid_map", "wb") as gid_map_f:
1761-
gid_map_f.write(f"0 {self._my_egid} 1\n".encode("ascii"))
1772+
gid_map_f.write(f"0 {self._my_gids[1]} 1\n".encode("ascii"))
17621773

17631774
def _find_self_in_cgroup_hierarchy(self):
17641775
my_pid = os.getpid()
@@ -3415,9 +3426,14 @@ def _run(self) -> subprocess.CompletedProcess:
34153426
logs = {}
34163427

34173428
def process_log(filename, log_line):
3418-
if self._debug or (
3419-
log_line and log_line[0] in "WEF"
3420-
): # Warning, Error, Fatal
3429+
if (
3430+
self._debug
3431+
or not filename.endswith(".txt") # Not a gVisor log file
3432+
or ( # gVisor log file
3433+
log_line
3434+
and log_line[0] in "WEF" # WEF: Warning, Error, Fatal
3435+
)
3436+
):
34213437
if filename not in logs:
34223438
logs[filename] = []
34233439
logs[filename].append(log_line)

open-webui/tools/run_code.py

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,8 @@ class Sandbox:
668668
"/proc/cgroups",
669669
"/proc/mounts",
670670
"/proc/version",
671+
"/proc/sys/kernel/unprivileged_userns_clone",
672+
"/proc/sys/kernel/unprivileged_userns_apparmor_policy",
671673
)
672674

673675
# Other commands worth running when dumping debug logs.
@@ -789,8 +791,9 @@ def __init__(self, libc, log_path, max_sandbox_ram_bytes, do_resource_limiting):
789791
self._log_path = log_path
790792
self._max_sandbox_ram_bytes = max_sandbox_ram_bytes
791793
self._do_resource_limiting = do_resource_limiting
792-
self._my_euid = None
793-
self._my_egid = None
794+
self._my_uids = None
795+
self._my_gids = None
796+
self._initial_status_data = None
794797
self._checkpoint = None
795798
self._cgroup_controllers = None
796799
self._needed_controllers = set()
@@ -803,6 +806,7 @@ def __init__(self, libc, log_path, max_sandbox_ram_bytes, do_resource_limiting):
803806
# Save EUID and EGID before we move to a new user namespace.
804807
("save_euid", self._save_euid),
805808
("save_egid", self._save_egid),
809+
("save_proc_self_status", self._save_proc_self_status),
806810
("unshare_user", self._unshare_user),
807811
# Map our current user as being root in the new user namespace.
808812
("write_uid_map", self._write_uid_map),
@@ -947,19 +951,8 @@ def __init__(self, libc, log_path, max_sandbox_ram_bytes, do_resource_limiting):
947951
)
948952
)
949953

950-
def _status(self):
951-
"""
952-
Return the current switcheroo status.
953-
954-
:return: The last successful operation name, "UNSTARTED" if unstarted, or "OK" if all done, and some information.
955-
"""
956-
main_status = self._checkpoint
957-
if self._checkpoint is None:
958-
main_status = "UNSTARTED"
959-
if self._checkpoint == self._operations[-1][0]:
960-
main_status = "OK"
961-
my_pid = os.getpid()
962-
status_line = f"{main_status} (euid={self._my_euid} egid={self._my_egid} pid={my_pid} do_resource_limiting={self._do_resource_limiting} initial_cgroup_name={self._initial_cgroup_name} codeeval_cgroup_name={self._codeeval_cgroup_name} controllers={self._cgroup_controllers})"
954+
def _read_proc_self_status(self):
955+
"""Read /proc/self/status and return some of it as a dictionary."""
963956
want_headers = (
964957
"Name",
965958
"Umask",
@@ -979,20 +972,35 @@ def _status(self):
979972
"Seccomp",
980973
"Seccomp_filters",
981974
)
982-
got_headers = {}
975+
status_data = {}
976+
with self._open("/proc/self/status", "rb") as status_f:
977+
for line in status_f.read().decode("utf-8").splitlines():
978+
for header in want_headers:
979+
if line.startswith(f"{header}:"):
980+
status_data[header] = line.split(":")[1].strip()
981+
break
982+
return status_data
983+
984+
def _status(self):
985+
"""
986+
Return the current switcheroo status.
987+
988+
:return: The last successful operation name, "UNSTARTED" if unstarted, or "OK" if all done, and some information.
989+
"""
990+
main_status = self._checkpoint
991+
if self._checkpoint is None:
992+
main_status = "UNSTARTED"
993+
if self._checkpoint == self._operations[-1][0]:
994+
main_status = "OK"
995+
my_pid = os.getpid()
996+
status_line = f"{main_status} (uids={self._my_uids} gids={self._my_gids} pid={my_pid} initial_proc_self_status={self._initial_status_data} do_resource_limiting={self._do_resource_limiting} initial_cgroup_name={self._initial_cgroup_name} codeeval_cgroup_name={self._codeeval_cgroup_name} controllers={self._cgroup_controllers})"
983997
try:
984-
with self._open("/proc/self/status", "rb") as status_f:
985-
for line in status_f.read().decode("utf-8").splitlines():
986-
for header in want_headers:
987-
if line.startswith(f"{header}:"):
988-
got_headers[header] = line.split(":")[1].strip()
989-
break
998+
status_data = self._read_proc_self_status()
990999
except OSError as e:
991-
status_line += f" (error opening /proc/self/status: {e})"
1000+
status_line += f" (error parsing /proc/self/status: {e})"
9921001
else:
993-
for header in want_headers:
994-
got_value = got_headers.get(header)
995-
status_line += f" {header}={got_value}"
1002+
for header, value in status_data.items():
1003+
status_line += f" {header}={value}"
9961004
if self._do_resource_limiting:
9971005
cgroupfs_data = []
9981006
for cgroup_components in (
@@ -1155,10 +1163,13 @@ def _open(self, path, mode):
11551163
raise OSError(f"opening {path} mode={mode}: {e}")
11561164

11571165
def _save_euid(self):
1158-
self._my_euid = os.geteuid()
1166+
self._my_uids = os.getresuid()
11591167

11601168
def _save_egid(self):
1161-
self._my_egid = os.getegid()
1169+
self._my_gids = os.getresgid()
1170+
1171+
def _save_proc_self_status(self):
1172+
self._initial_status_data = self._read_proc_self_status()
11621173

11631174
def _unshare_user(self):
11641175
Sandbox.unshare(
@@ -1167,15 +1178,15 @@ def _unshare_user(self):
11671178

11681179
def _write_uid_map(self):
11691180
with self._open("/proc/self/uid_map", "wb") as uid_map_f:
1170-
uid_map_f.write(f"0 {self._my_euid} 1\n".encode("ascii"))
1181+
uid_map_f.write(f"0 {self._my_uids[1]} 1\n".encode("ascii"))
11711182

11721183
def _write_setgroups(self):
11731184
with self._open("/proc/self/setgroups", "wb") as setgroups_f:
11741185
setgroups_f.write(b"deny")
11751186

11761187
def _write_gid_map(self):
11771188
with self._open("/proc/self/gid_map", "wb") as gid_map_f:
1178-
gid_map_f.write(f"0 {self._my_egid} 1\n".encode("ascii"))
1189+
gid_map_f.write(f"0 {self._my_gids[1]} 1\n".encode("ascii"))
11791190

11801191
def _find_self_in_cgroup_hierarchy(self):
11811192
my_pid = os.getpid()
@@ -2832,9 +2843,14 @@ def _run(self) -> subprocess.CompletedProcess:
28322843
logs = {}
28332844

28342845
def process_log(filename, log_line):
2835-
if self._debug or (
2836-
log_line and log_line[0] in "WEF"
2837-
): # Warning, Error, Fatal
2846+
if (
2847+
self._debug
2848+
or not filename.endswith(".txt") # Not a gVisor log file
2849+
or ( # gVisor log file
2850+
log_line
2851+
and log_line[0] in "WEF" # WEF: Warning, Error, Fatal
2852+
)
2853+
):
28382854
if filename not in logs:
28392855
logs[filename] = []
28402856
logs[filename].append(log_line)

0 commit comments

Comments
 (0)