Skip to content

Commit 5cd3f98

Browse files
committed
Remove check for unobstructed procfs mount.
This is no longer required as of gVisor release 20241104. Updates issue #19.
1 parent 841aaf1 commit 5cd3f98

File tree

4 files changed

+0
-152
lines changed

4 files changed

+0
-152
lines changed

docs/setup.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,6 @@ This is adequate for single-user setups not exposed to the outside Internet, whi
5151
* On **Kubernetes**: Add a [`hostPath` volume](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) with `path` set to `/sys/fs/cgroup`, then mount it in your container's `volumeMounts` with options `mountPath` set to `/sys/fs/cgroup` and `readOnly` set to `false`.
5252
* **Why**: This is needed so that gVisor can create child [cgroups](https://en.wikipedia.org/wiki/Cgroups), necessary to enforce per-sandbox resource usage limits.
5353
* If you wish to disable resource limiting on code evaluation sandboxes, you can skip this setting and not mount `cgroupfs` at all in the container. Note that this means code evaluation sandboxes will be able to take as much CPU and memory as they want.
54-
* **Mount `procfs` at `/proc2`**:
55-
* On **Docker**: Add `--mount=type=bind,source=/proc,target=/proc2,readonly=false,bind-recursive=disabled` to `docker run`.
56-
* On **Kubernetes**: Add a [`hostPath` volume](https://kubernetes.io/docs/concepts/storage/volumes/#hostpath) with `path` set to `/proc`, then mount it in your container's `volumeMounts` with options `mountPath` set to `/proc2` and `readOnly` set to `false`.
57-
* **Why**: By default, in non-privileged mode, the container runtime will mask certain sub-paths of `/proc` inside the container by creating submounts of `/proc` (e.g. `/proc/bus`, `/proc/sys`, etc.). gVisor does not really care or use anything under these sub-mounts, but *does* need to be able to mount `procfs` in the chroot environment it isolates itself in. However, its ability to mount `procfs` requires having an existing unobstructed view of `procfs` (i.e. a mount of `procfs` with no submounts). Otherwise, such mount attempts will be denied by the kernel (see the explanation for "locked" mounts on [`mount_namespaces(7)`](https://www.man7.org/linux/man-pages/man7/mount_namespaces.7.html)). Therefore, exposing an unobstructed (non-recursive) view of `/proc` elsewhere in the container filesystem (such as `/proc2`) informs the kernel that it is OK for this container to be able to mount `procfs`.
5854
* Remove the container's default **AppArmor profile**:
5955
* On **Docker**: Add `--security-opt=apparmor=unconfined` to `docker run`.
6056
* On **Kubernetes**: Set [`spec.securityContext.appArmorProfile.type`](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-apparmor-profile-for-a-container) to `Unconfined`.
@@ -213,7 +209,6 @@ $ git clone https://github.com/EtiennePerot/safe-code-execution && \
213209
--security-opt=apparmor=unconfined \
214210
--security-opt=label=type:container_engine_t \
215211
--mount=type=bind,source=/sys/fs/cgroup,target=/sys/fs/cgroup,readonly=false \
216-
--mount=type=bind,source=/proc,target=/proc2,readonly=false,bind-recursive=disabled \
217212
--mount=type=bind,source="$(pwd)",target=/test \
218213
ghcr.io/open-webui/open-webui:main \
219214
sh -c 'python3 /test/open-webui/tools/run_code.py --self_test && python3 /test/open-webui/functions/run_code.py --self_test'

open-webui/functions/run_code.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,54 +2858,6 @@ def check_cgroups(cls):
28582858
"cgroupfs does not have the 'memory' controller enabled, necessary to enforce memory limits; please enable it, or disable resource limiting if appropriate"
28592859
)
28602860

2861-
@classmethod
2862-
def check_procfs(cls):
2863-
"""
2864-
Verifies that we have an unobstructed view of procfs.
2865-
2866-
:return: Nothing.
2867-
:raises EnvironmentNeedsSetupException: If procfs is obstructed.
2868-
"""
2869-
mount_infos = []
2870-
with open("/proc/self/mountinfo", "rb") as mountinfo_f:
2871-
for line in mountinfo_f:
2872-
line = line.decode("utf-8").strip()
2873-
if not line:
2874-
continue
2875-
mount_components = line.split(" ")
2876-
if len(mount_components) < 10:
2877-
continue
2878-
hyphen_index = mount_components.index("-")
2879-
if hyphen_index < 6:
2880-
continue
2881-
mount_info = {
2882-
"mount_path": mount_components[4],
2883-
"path_within_mount": mount_components[3],
2884-
"fs_type": mount_components[hyphen_index + 1],
2885-
}
2886-
mount_infos.append(mount_info)
2887-
procfs_mounts = frozenset(
2888-
m["mount_path"]
2889-
for m in mount_infos
2890-
if m["fs_type"] == "proc" and m["path_within_mount"] == "/"
2891-
)
2892-
if len(procfs_mounts) == 0:
2893-
raise cls.EnvironmentNeedsSetupException(
2894-
"procfs is not mounted; please mount it"
2895-
)
2896-
obstructed_procfs_mounts = set()
2897-
for mount_info in mount_infos:
2898-
for procfs_mount in procfs_mounts:
2899-
if mount_info["mount_path"].startswith(procfs_mount + os.sep):
2900-
obstructed_procfs_mounts.add(procfs_mount)
2901-
for procfs_mount in procfs_mounts:
2902-
if procfs_mount not in obstructed_procfs_mounts:
2903-
return # We have at least one unobstructed procfs view.
2904-
assert len(obstructed_procfs_mounts) > 0, "Logic error"
2905-
raise cls.EnvironmentNeedsSetupException(
2906-
"procfs is obstructed; please mount a new procfs mount somewhere in the container, e.g. /proc2 (`--mount=type=bind,source=/proc,target=/proc2,readonly=false,bind-recursive=disabled`)"
2907-
)
2908-
29092861
@classmethod
29102862
def unshare(cls, flags):
29112863
"""
@@ -3033,7 +2985,6 @@ def check_setup(
30332985
cls.check_unshare()
30342986
if require_resource_limiting:
30352987
cls.check_cgroups()
3036-
cls.check_procfs()
30372988
if not auto_install_allowed and cls.get_runsc_path() is None:
30382989
raise cls.GVisorNotInstalledException(
30392990
"gVisor is not installed (runsc binary not found in $PATH); please install it or enable AUTO_INSTALL valve for auto installation"

open-webui/tools/run_code.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2275,54 +2275,6 @@ def check_cgroups(cls):
22752275
"cgroupfs does not have the 'memory' controller enabled, necessary to enforce memory limits; please enable it, or disable resource limiting if appropriate"
22762276
)
22772277

2278-
@classmethod
2279-
def check_procfs(cls):
2280-
"""
2281-
Verifies that we have an unobstructed view of procfs.
2282-
2283-
:return: Nothing.
2284-
:raises EnvironmentNeedsSetupException: If procfs is obstructed.
2285-
"""
2286-
mount_infos = []
2287-
with open("/proc/self/mountinfo", "rb") as mountinfo_f:
2288-
for line in mountinfo_f:
2289-
line = line.decode("utf-8").strip()
2290-
if not line:
2291-
continue
2292-
mount_components = line.split(" ")
2293-
if len(mount_components) < 10:
2294-
continue
2295-
hyphen_index = mount_components.index("-")
2296-
if hyphen_index < 6:
2297-
continue
2298-
mount_info = {
2299-
"mount_path": mount_components[4],
2300-
"path_within_mount": mount_components[3],
2301-
"fs_type": mount_components[hyphen_index + 1],
2302-
}
2303-
mount_infos.append(mount_info)
2304-
procfs_mounts = frozenset(
2305-
m["mount_path"]
2306-
for m in mount_infos
2307-
if m["fs_type"] == "proc" and m["path_within_mount"] == "/"
2308-
)
2309-
if len(procfs_mounts) == 0:
2310-
raise cls.EnvironmentNeedsSetupException(
2311-
"procfs is not mounted; please mount it"
2312-
)
2313-
obstructed_procfs_mounts = set()
2314-
for mount_info in mount_infos:
2315-
for procfs_mount in procfs_mounts:
2316-
if mount_info["mount_path"].startswith(procfs_mount + os.sep):
2317-
obstructed_procfs_mounts.add(procfs_mount)
2318-
for procfs_mount in procfs_mounts:
2319-
if procfs_mount not in obstructed_procfs_mounts:
2320-
return # We have at least one unobstructed procfs view.
2321-
assert len(obstructed_procfs_mounts) > 0, "Logic error"
2322-
raise cls.EnvironmentNeedsSetupException(
2323-
"procfs is obstructed; please mount a new procfs mount somewhere in the container, e.g. /proc2 (`--mount=type=bind,source=/proc,target=/proc2,readonly=false,bind-recursive=disabled`)"
2324-
)
2325-
23262278
@classmethod
23272279
def unshare(cls, flags):
23282280
"""
@@ -2450,7 +2402,6 @@ def check_setup(
24502402
cls.check_unshare()
24512403
if require_resource_limiting:
24522404
cls.check_cgroups()
2453-
cls.check_procfs()
24542405
if not auto_install_allowed and cls.get_runsc_path() is None:
24552406
raise cls.GVisorNotInstalledException(
24562407
"gVisor is not installed (runsc binary not found in $PATH); please install it or enable AUTO_INSTALL valve for auto installation"

src/safecode/sandbox.py

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1783,54 +1783,6 @@ def check_cgroups(cls):
17831783
"cgroupfs does not have the 'memory' controller enabled, necessary to enforce memory limits; please enable it, or disable resource limiting if appropriate"
17841784
)
17851785

1786-
@classmethod
1787-
def check_procfs(cls):
1788-
"""
1789-
Verifies that we have an unobstructed view of procfs.
1790-
1791-
:return: Nothing.
1792-
:raises EnvironmentNeedsSetupException: If procfs is obstructed.
1793-
"""
1794-
mount_infos = []
1795-
with open("/proc/self/mountinfo", "rb") as mountinfo_f:
1796-
for line in mountinfo_f:
1797-
line = line.decode("utf-8").strip()
1798-
if not line:
1799-
continue
1800-
mount_components = line.split(" ")
1801-
if len(mount_components) < 10:
1802-
continue
1803-
hyphen_index = mount_components.index("-")
1804-
if hyphen_index < 6:
1805-
continue
1806-
mount_info = {
1807-
"mount_path": mount_components[4],
1808-
"path_within_mount": mount_components[3],
1809-
"fs_type": mount_components[hyphen_index + 1],
1810-
}
1811-
mount_infos.append(mount_info)
1812-
procfs_mounts = frozenset(
1813-
m["mount_path"]
1814-
for m in mount_infos
1815-
if m["fs_type"] == "proc" and m["path_within_mount"] == "/"
1816-
)
1817-
if len(procfs_mounts) == 0:
1818-
raise cls.EnvironmentNeedsSetupException(
1819-
"procfs is not mounted; please mount it"
1820-
)
1821-
obstructed_procfs_mounts = set()
1822-
for mount_info in mount_infos:
1823-
for procfs_mount in procfs_mounts:
1824-
if mount_info["mount_path"].startswith(procfs_mount + os.sep):
1825-
obstructed_procfs_mounts.add(procfs_mount)
1826-
for procfs_mount in procfs_mounts:
1827-
if procfs_mount not in obstructed_procfs_mounts:
1828-
return # We have at least one unobstructed procfs view.
1829-
assert len(obstructed_procfs_mounts) > 0, "Logic error"
1830-
raise cls.EnvironmentNeedsSetupException(
1831-
"procfs is obstructed; please mount a new procfs mount somewhere in the container, e.g. /proc2 (`--mount=type=bind,source=/proc,target=/proc2,readonly=false,bind-recursive=disabled`)"
1832-
)
1833-
18341786
@classmethod
18351787
def unshare(cls, flags):
18361788
"""
@@ -1958,7 +1910,6 @@ def check_setup(
19581910
cls.check_unshare()
19591911
if require_resource_limiting:
19601912
cls.check_cgroups()
1961-
cls.check_procfs()
19621913
if not auto_install_allowed and cls.get_runsc_path() is None:
19631914
raise cls.GVisorNotInstalledException(
19641915
"gVisor is not installed (runsc binary not found in $PATH); please install it or enable AUTO_INSTALL valve for auto installation"

0 commit comments

Comments
 (0)