/
opt
/
cloudlinux
/
venv
/
lib
/
python3.11
/
site-packages
/
clwpos
/
/opt/cloudlinux/venv/lib/python3.11/site-packages/clwpos
mkdir
upload
Name
Size
Mode
Actions
bin/
-
0755
rm
cli_versions/
-
0755
rm
feature_suites/
-
0755
rm
hooks/
-
0755
rm
migrations/
-
0755
rm
object_cache/
-
0755
rm
optimization_features/
-
0755
rm
php/
-
0755
rm
user/
-
0755
rm
__pycache__/
-
0755
rm
billing.py
6392
0644
edit
dl
rm
cl_wpos_exceptions.py
4020
0644
edit
dl
rm
constants.py
5695
0644
edit
dl
rm
create_user_uid_dirs.py
754
0644
edit
dl
rm
cron.py
2189
0644
edit
dl
rm
daemon.py
40729
0644
edit
dl
rm
daemon_base.py
2912
0644
edit
dl
rm
daemon_config.py
621
0644
edit
dl
rm
daemon_redis_lib.py
15864
0644
edit
dl
rm
daemon_subscription_handler.py
32735
0644
edit
dl
rm
data_collector_utils.py
9644
0644
edit
dl
rm
logsetup.py
4142
0644
edit
dl
rm
papi.py
10104
0644
edit
dl
rm
parse.py
2154
0644
edit
dl
rm
redis_configuration_pid_file_cleaner.py
1037
0755
edit
dl
rm
report_generator.py
26597
0644
edit
dl
rm
scoped_cache.py
1372
0644
edit
dl
rm
socket_utils.py
6938
0644
edit
dl
rm
stats.py
12304
0644
edit
dl
rm
utils.py
77973
0644
edit
dl
rm
whmcs_utils.py
11533
0644
edit
dl
rm
wpos_admin.py
76414
0644
edit
dl
rm
wpos_hooks.py
8466
0755
edit
dl
rm
wpos_req_scanner.py
5490
0644
edit
dl
rm
wp_config.py
3636
0644
edit
dl
rm
wp_utils.py
18807
0644
edit
dl
rm
__init__.py
928
0644
edit
dl
rm
Edit:
/opt/cloudlinux/venv/lib/python3.11/site-packages/clwpos/wp_config.py
(3636B)
# coding=utf-8 # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT """Module for work with wp_config.php""" from __future__ import absolute_import, print_function import io import os import stat from pathlib import Path from typing import List WP_CONFIG_SUFFIX = 'wp-config.php' # A wp-config.php is a small PHP file (a few KiB in practice). Cap the read well # above any legitimate config so a tenant cannot make root buffer a huge/sparse # file planted at the path; this read runs as root over tenant-owned input. MAX_WP_CONFIG_BYTES = 1024 * 1024 def path(abs_wp_path: str) -> Path: """ Return path to wp-config.php file. """ return Path(abs_wp_path, WP_CONFIG_SUFFIX) def read(abs_wp_path: str) -> List[str]: """ Read wp-config.php located in specified WP path. The file is tenant-owned, so open it with O_NOFOLLOW (reject a symlinked final component) and O_NONBLOCK (open() cannot block on a FIFO with no writer), fstat the opened fd to require a regular file (reject FIFO/device/socket/dir), and bound the actual read to MAX_WP_CONFIG_BYTES. The fstat st_size is only a fast-reject of an already-oversized file; it does not bound the read, because a tenant can grow (append to) the file after the fstat but before/while the bytes are consumed, so the read itself must be hard-capped: pull at most MAX_WP_CONFIG_BYTES + 1 bytes and reject if the file yielded more than the cap (a grown/sparse file), rather than returning a truncated config that would corrupt the file on write-back. The bytes are then split into lines exactly as the previous open(errors='surrogateescape').readlines() did (universal-newline text decode), so a small regular config returns the identical list of lines. Because the type check is on the actually-opened fd it also closes the stat-vs-open TOCTOU window. A symlinked path or a non-regular/oversized file raises OSError, matching the missing/unreadable semantics of the previous bare open() so callers' error handling is intact. """ fd = os.open(path(abs_wp_path), os.O_RDONLY | os.O_NOFOLLOW | os.O_NONBLOCK) try: st = os.fstat(fd) if not stat.S_ISREG(st.st_mode): raise OSError(f'wp-config.php at {path(abs_wp_path)} is not a regular file') if st.st_size > MAX_WP_CONFIG_BYTES: raise OSError(f'wp-config.php at {path(abs_wp_path)} exceeds {MAX_WP_CONFIG_BYTES} bytes') # Bound the read itself: st_size above only fast-rejects an # already-large file, but a tenant can grow the file after the fstat, # so pull at most MAX + 1 bytes (never buffering more) and reject if the # file grew past the cap rather than returning a truncated config. limit = MAX_WP_CONFIG_BYTES + 1 chunks = [] remaining = limit while remaining > 0: chunk = os.read(fd, remaining) if not chunk: break chunks.append(chunk) remaining -= len(chunk) finally: os.close(fd) raw = b''.join(chunks) if len(raw) > MAX_WP_CONFIG_BYTES: raise OSError(f'wp-config.php at {path(abs_wp_path)} exceeds {MAX_WP_CONFIG_BYTES} bytes') # Reproduce the previous open(errors='surrogateescape').readlines() output # byte-for-byte from the bounded bytes (same universal-newline text decode). with io.TextIOWrapper(io.BytesIO(raw), errors='surrogateescape') as f: return f.readlines()
Save
cmd:
run