Check in 1.8.4.1

This commit is contained in:
George Wang
2025-11-09 15:51:52 -05:00
parent c4ed2e1aea
commit e9397b58a9
22 changed files with 306 additions and 194 deletions
+1 -1
View File
@@ -96,7 +96,7 @@ if (CMAKE_C_COMPILER MATCHES "clang")
unset(LIBSAN)
endif()
set(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-unused-function")
set(MY_CMAKE_FLAGS "${MY_CMAKE_FLAGS} -DHAVE_BORINGSSL -Wall -Wextra -Wno-unused-parameter -Wno-unused-function")
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Suppress gcc warnings about BoringSSL's openssl/stack.h
+6 -17
View File
@@ -254,23 +254,12 @@ prepareLinux()
{
OSTYPE=unknownlinux
if [ -f /etc/redhat-release ] ; then
OSTYPE=CENTOS
${FULL_APP_MGR_CMD} update -y
${FULL_APP_MGR_CMD} install -y epel-release
output=$(cat /etc/redhat-release)
if echo $output | grep " 7."; then
OSTYPE=CENTOS7
elif echo $output | grep " 8."; then
OSTYPE=CENTOS8
elif echo $output | grep " release 8"; then
OSTYPE=CENTOS8
elif echo $output | grep " 9."; then
OSTYPE=CENTOS9
elif echo $output | grep " release 9"; then
OSTYPE=CENTOS9
fi
if [ "${OSTYPE}" = "CENTOS7" ] ; then
output=$(rpm -E %{rhel})
OSTYPE="CENTOS$output"
if [ "${output}" -eq "7" ] ; then
if [ ! -f ./installing ] ; then
${FULL_APP_MGR_CMD} -y install centos-release-scl
which yum-config-manager
@@ -285,11 +274,11 @@ prepareLinux()
exit 0
fi
elif [ "${OSTYPE}" = "CENTOS8" ] || [ "${OSTYPE}" = "CENTOS9" ] ; then
elif [ "$output" -ge "8" ] ; then
$DOSUDO dnf -y groupinstall "Development Tools"
else
echo This script only works on 7/8/9 for centos family._Static_assert
echo This script only works on 7+ for centos family._Static_assert
exit 1
fi
+2 -8
View File
@@ -397,12 +397,6 @@ EOF
DIR_OWN=$WS_USER:$WS_GROUP
CONF_OWN=$WS_USER:$WS_GROUP
if [ $INST_USER = "root" ]; then
if [ $SUCC -eq "1" ]; then
chown -R "$DIR_OWN" "$LSWS_HOME"
fi
fi
}
stopLshttpd()
@@ -940,8 +934,8 @@ installation_lscpd()
install_missing_packages()
{
if [ -f /etc/redhat-release ] ; then
output=$(cat /etc/redhat-release)
if echo $output | grep " 9."; then
output=$(rpm -E %{rhel})
if [ "$output" -ge "9" ] ; then
yum -y install libxcrypt-compat libnsl
fi
if [ "${ARCH}" = "aarch64" ]; then
+15
View File
@@ -107,6 +107,21 @@ def get_min_uid():
logging.debug('Using min uid: %d' % this.min_uid)
return this.min_uid
def getpwall():
uid_dict = {}
final_users = []
users = pwd.getpwall()
for user in users:
if user.pw_uid < get_min_uid():
continue
if user.pw_uid in uid_dict:
continue
if user.pw_name == 'nobody':
continue
uid_dict[user.pw_uid] = user
final_users.append(user)
return final_users
def container_file():
return server_root() + "/lsns/conf/lscntr.txt"
+10 -17
View File
@@ -155,11 +155,9 @@ def command_list(users):
for user in users:
list_user(user, dict)
else:
users = pwd.getpwall()
min_uid = common.get_min_uid()
users = common.getpwall()
for listuser in users:
if listuser.pw_uid >= min_uid and listuser.pw_name != 'nobody':
list_user(listuser, dict)
list_user(listuser, dict)
print(json.dumps(dict, indent=4))
return 0
@@ -215,20 +213,18 @@ def reset_user(args, user, reload):
args.iops = '-1';
args.mem = '-1'
args.tasks = '-1'
return set_user(args, user, reload)
users = [user]
return set_user(args, users, reload)
def command_reset(args, users):
if args.command == 'reset' or args.command == 'reset-user':
for user in users:
reset_user(args, user, True)
else:
users = pwd.getpwall()
min_uid = common.get_min_uid()
need_reload = False
users = common.getpwall()
need_reload = len(users) > 0
for listuser in users:
if listuser.pw_uid >= min_uid:
need_reload = True
reset_user(args, listuser)
reset_user(args, listuser)
if need_reload:
systemctl_daemon_reload()
if not args.quiet:
@@ -259,13 +255,10 @@ def command_set(args, users):
if args.command == 'set' or args.command == 'set-user':
set_user(args, users, True)
else:
users = pwd.getpwall()
min_uid = common.get_min_uid()
need_reload = False
users = common.getpwall()
need_reload = len(users) > 0
for listuser in users:
if listuser.pw_uid >= min_uid:
need_reload = True
set_user(args, listuser, False)
set_user(args, listuser, False)
if need_reload:
systemctl_daemon_reload()
if not args.quiet:
+5 -5
View File
@@ -165,10 +165,9 @@ def command_list(args, pkg_sizes, single_list=False):
def plesk_home_dict():
home_dict = {}
for user in pwd.getpwall():
if user.pw_uid >= common.get_min_uid():
logging.debug('home_dict key: ' + user.pw_dir)
home_dict[user.pw_dir] = user
for user in common.getpwall():
logging.debug('home_dict key: ' + user.pw_dir)
home_dict[user.pw_dir] = user
return home_dict
def read_pleskplans(plans):
@@ -203,7 +202,8 @@ def read_pleskplans(plans):
logging.debug(match)
common.fatal_error("Expected 3 matches in %s and got %d" % (line, len(matches)))
if not matches[1] in home_dict:
common.fatal_error("%s in user dictionary from %s" % (matches[1], line))
logging.debug("Missing expected home directory %s; verify it in /etc/passwd (from %s)" % (matches[1], line))
continue
plan = matches[2]
user = home_dict[matches[1]]
logging.debug(" add to %s: %s (%d)" % (plan, user.pw_name, user.pw_uid))
+66 -39
View File
@@ -28,12 +28,12 @@ def systemctl_daemon_reload():
logging.debug("Do daemon-reload")
run_program(['systemctl', 'daemon-reload'])
def validate_environment():
if not os.path.exists('/sys/fs/cgroup/cgroup.controllers'):
def validate_environment(args):
if not args.namespace_only and not args.disable and not os.path.exists('/sys/fs/cgroup/cgroup.controllers'):
common.fatal_error("cgroups is not v2 on this machine")
if os.getuid() != 0:
common.fatal_error("this program must be run as root")
if not os.path.isfile('/etc/systemd/system.control/user.slice.d/50-IOAccounting.conf'):
if not args.namespace_only and not args.disable and not os.path.isfile('/etc/systemd/system.control/user.slice.d/50-IOAccounting.conf'):
logging.debug('Activate accounting')
run_program(['systemctl', 'set-property', 'user.slice', 'IOAccounting=yes', 'MemoryAccounting=yes', 'TasksAccounting=yes'])
systemctl_daemon_reload()
@@ -45,14 +45,16 @@ def init_pgm():
parser.add_argument('-l', '--log', type=int, help='set logging level, 10=Debug, 20=Info, 30=Warning, 40=Error. Default is Info')
parser.add_argument('-q', '--quiet', action='store_true', help='turns off all logging and only outputs what is requested.')
parser.add_argument('-s', '--server_root', default=common.server_root(), help='the LiteSpeed SERVER_ROOT')
parser.add_argument('-c', '--cgroups', type=int, default=1, help='The minimum value for cgroups')
parser.add_argument('-c', '--cgroups', type=int, default=2, help='The minimum value for cgroups')
parser.add_argument('-i', '--cgroups-init', type=int, default=2, help='The cgroups value if not set currently')
parser.add_argument('-n', '--namespace', type=int, default=1, help='The minimum value for namespace')
parser.add_argument('-n', '--namespace', type=int, default=2, help='The minimum value for namespace')
parser.add_argument('-m', '--namespace-init', type=int, default=2, help='The namespace value if not set currently')
parser.add_argument('-g', '--no-config', action='store_true', help='Skips checking of LiteSpeed Config')
parser.add_argument('-t', '--no-subtree_control', action='store_true', help='Skips checking of system cgroup.subtree_control file')
parser.add_argument('-u', '--no-upgrade', action='store_true', help='Does not check the version of LiteSpeed')
parser.add_argument('-r', '--revert-config', action='store_true', help='Reverts modified LiteSpeed config file')
parser.add_argument('-o', '--namespace-only', action='store_true', help='No cgroups, namespaces only')
parser.add_argument('-d', '--disable', action='store_true', help='LiteSpeed Containers Disable')
args = parser.parse_args()
if not args.quiet or args.log != None:
if args.log != None:
@@ -61,7 +63,7 @@ def init_pgm():
logging.getLogger().setLevel(logging.INFO)
logging.debug("Entering setup")
common.set_server_root(args.server_root)
validate_environment()
validate_environment(args)
return args
def config_filename(lsws):
@@ -84,17 +86,26 @@ def copy_file_details(source, dest):
shutil.copystat(source, dest)
os.chown(dest, s.st_uid, s.st_gid)
def set_cgroups(root, val, init):
def set_cgroups(root, disable, val, init):
valSet = False
findLimit = root.find('./security/CGIRLimit')
if findLimit == None:
common.fatal_error('Unexpected missing element CGIRLimit in configuration file')
cgroups = findLimit.find('cgroups')
if cgroups == None:
if disable:
if cgroups != None and int(cgroups.text) > 0:
logging.debug('cgroups needs disabling')
cgroups.text = str(0)
valset = True
elif cgroups == None:
logging.debug('cgroups not in LSWS file')
cgroups = ET.SubElement(findLimit, 'cgroups')
cgroups.text = str(init)
valSet = True
elif disable and int(cgroups.text) > 0:
logging.debug('cgroups needs disabling')
cgroups.text = str(0)
valset = True
elif int(cgroups.text) < val:
logging.debug('cgroups bad value in LSWS file')
cgroups.text = str(val)
@@ -106,13 +117,18 @@ def set_cgroups(root, val, init):
return valSet
def set_namespace(root, val, init):
def set_namespace(root, disable, val, init):
valSet = False
findSecurity = root.find('./security')
if findSecurity == None:
common.fatal_error('Unexpected missing element Security in configuration file')
namespace = findSecurity.find('namespace')
if namespace == None:
if disable:
if namespace != None and int(namespace.text) > 0:
logging.debug('namespace needs disabling')
namespace.text = str(0)
valSet = True
elif namespace == None:
logging.debug('namespace not in LSWS file')
namespace = ET.SubElement(findSecurity, 'namespace')
namespace.text = str(init)
@@ -148,8 +164,9 @@ def lsws_config(args):
revert = config_filename_revert(True)
shutil.copy2(file, revert)
copy_file_details(file, revert)
valSet = set_cgroups(tree.getroot(), args.cgroups, args.cgroups_init)
if set_namespace(tree.getroot(), args.namespace, args.namespace_init):
if not args.namespace_only:
valSet = set_cgroups(tree.getroot(), args.disable, args.cgroups, args.cgroups_init)
if set_namespace(tree.getroot(), args.disable, args.namespace, args.namespace_init):
valSet = True
if valSet:
try:
@@ -163,6 +180,34 @@ def lsws_validate(args):
lsws_config(args)
def rewrite_ols_config(args, cgroupsAt, pastCGIRLimit, cgroupsVal, namespaceAt, lineNo, namespaceVal):
stop1 = 0
replace1 = False
if not args.namespace_only:
if cgroupsAt != 0:
if (args.disable and int(cgroupsVal) > 0) or (not args.disable and int(cgroupsVal) <= args.cgroups):
stop1 = cgroupsAt
replace1 = True
if args.disable:
setCgroups = 0
else:
setCgroups = args.cgroups
elif not args.disable:
stop1 = pastCGIRLimit
setCgroups = args.cgroups_init
stop2 = 0
replace2 = False
if namespaceAt != 0:
if (args.disable and int(namespaceVal) > 0) or (not args.disable and int(namespaceVal) <= args.namespace):
stop2 = namespaceAt
replace2 = True
if args.disable:
setNS = 0
else:
setNS = args.namespace
elif not args.disable:
stop2 = lineNo
setNS = args.namespace_init
lineNo = 0
file = config_filename(False)
try:
f = open(file, 'r')
@@ -173,33 +218,11 @@ def rewrite_ols_config(args, cgroupsAt, pastCGIRLimit, cgroupsVal, namespaceAt,
w = open(fileout, 'w')
except Exception as err:
common.fatal_error('Error opening %s: %s' % (fileout, err))
# Optimize for the do nothing case
stop1 = 0
replace1 = False
if cgroupsAt != 0:
if int(cgroupsVal) <= args.cgroups:
stop1 = cgroupsAt
replace1 = True
setCgroups = args.cgroups
else:
stop1 = pastCGIRLimit
setCgroups = args.cgroups_init
stop2 = 0
replace2 = False
if namespaceAt != 0:
if int(namespaceVal) <= args.namespace:
stop2 = namespaceAt
replace2 = True
setNS = args.namespace
else:
stop2 = lineNo
setNS = args.namespace_init
lineNo = 0
try:
for line in f:
replace = False
if lineNo > 0:
if lineNo == stop1:
if stop1 != 0 and lineNo == stop1:
w.write(' cgroups %d\n' % setCgroups)
replace = replace1
logging.debug('writing cgroups %d' % setCgroups)
@@ -244,7 +267,7 @@ def ols_config(args):
inCGIRLimit = True
elif line.find('}') != -1:
pastCGIRLimit = lineNo
elif line.startswith(' cgroups'):
elif not args.namespace_only and line.startswith(' cgroups'):
cgroupsLine = line
cgroupsAt = lineNo
elif line.startswith('namespace'):
@@ -255,13 +278,17 @@ def ols_config(args):
break
lineNo += 1
f.close()
if cgroupsLine != '':
if not args.namespace_only and cgroupsLine != '':
cgroupsVal = re.search(r'[\d]+', cgroupsLine).group()
logging.debug('OLS cgroups val: %d' % int(cgroupsVal))
if namespaceLine != '':
namespaceVal = re.search(r'[\d]+', namespaceLine).group()
logging.debug('OLS namespace val: %d' % int(namespaceVal))
if cgroupsLine != '' and int(cgroupsVal) >= args.cgroups and namespaceLine != '' and int(namespaceVal) >= args.namespace:
if args.disable:
if (args.namespace_only or cgroupsLine == '' or int(cgroupsVal) == 0) and (namespaceLine == '' or int(namespaceVal) == 0):
logging.debug('OLS config file needs no mod')
return
elif (args.namespace_only or (cgroupsLine != '' and int(cgroupsVal) >= args.cgroups)) and namespaceLine != '' and int(namespaceVal) >= args.namespace:
logging.debug('OLS config file needs no mod')
return
logging.debug('OLS config file needs mod')
@@ -377,7 +404,7 @@ def do_pgm(args):
ols_validate(args)
else:
logging.debug('no-config specified')
if not args.no_subtree_control:
if not args.disable and not args.no_subtree_control and not args.namespace_only:
subtree_control()
else:
logging.debug('no-subtree_control specified')
+40 -20
View File
@@ -131,6 +131,7 @@ SetupOp s_SetupOp_default[] =
{ SETUP_BIND_MOUNT, "/opt/psa", "/opt/psa", OP_FLAG_ALLOW_NOTEXIST, -1 },
{ SETUP_BIND_MOUNT, "/var/lib/php/sessions", "/var/lib/php/sessions", OP_FLAG_ALLOW_NOTEXIST, -1},
{ SETUP_BIND_MOUNT, "/var/lib/php/session", "/var/lib/php/session", OP_FLAG_ALLOW_NOTEXIST, -1},
{ SETUP_BIND_MOUNT, "/var/cpanel/php/sessions", "/var/cpanel/php/sessions", OP_FLAG_ALLOW_NOTEXIST, -1},
{ SETUP_NOOP, NULL, NULL, OP_FLAG_LAST, -1 }
};
@@ -1555,7 +1556,7 @@ static int try_symlink_trick(const char *src, const char *dest)
return 0;
}
static int bind_mount(const char *src, const char *dest, bind_option_t options)
static int bind_mount(int flags, const char *src, const char *dest, bind_option_t options)
{
int readonly = (options & BIND_READONLY) != 0;
int devices = (options & BIND_DEVICES) != 0;
@@ -1585,6 +1586,11 @@ static int bind_mount(const char *src, const char *dest, bind_option_t options)
!nsnosandbox_symlink()) &&
!try_symlink_trick(src, dest))
return 0;
else if (flags & OP_FLAG_SUSPICIOUS_LINK)
{
DEBUG_MESSAGE("Suspicious link bind failure ignored\n");
return 0;
}
}
if (err)
{
@@ -1756,13 +1762,13 @@ static int do_copy(uint32_t flags, const char *source, const char *dest, int *fd
return -1;
}
DEBUG_MESSAGE("copy complete: %s -> %s\n", source, dest);
rc = bind_mount(temp_filename, dest, 0);
rc = bind_mount(flags, temp_filename, dest, 0);
return 0;
}
static int privileged_op(int privileged_op_socket, uint32_t op,
uint32_t flags, const char *arg1, const char *arg2, int *fd)
uint32_t flags, const char *arg1, const char *arg2, SetupOp *setupOp)
{
if (privileged_op_socket != -1)
{
@@ -1841,7 +1847,7 @@ static int privileged_op(int privileged_op_socket, uint32_t op,
break;
case PRIV_SEP_OP_REMOUNT_RO_NO_RECURSIVE:
if (bind_mount(NULL, arg2, BIND_READONLY) != 0)
if (bind_mount(setupOp->flags, NULL, arg2, BIND_READONLY) != 0)
{
ls_stderr("Namespace error in bind mount of %s: %s\n", arg2,
strerror(errno));
@@ -1852,7 +1858,7 @@ static int privileged_op(int privileged_op_socket, uint32_t op,
case PRIV_SEP_OP_BIND_MOUNT:
/* We always bind directories recursively, otherwise this would let us
access files that are otherwise covered on the host */
if (bind_mount (arg1, arg2, flags) != 0)
if (bind_mount (setupOp->flags, arg1, arg2, flags) != 0)
{
ls_stderr("Namespace error in bind mount of %s to %s: %s\n", arg1,
arg2, strerror(errno));
@@ -1938,7 +1944,7 @@ static int privileged_op(int privileged_op_socket, uint32_t op,
break;
case PRIV_SEP_OP_COPY:
return do_copy(flags, arg1, arg2, fd);
return do_copy(flags, arg1, arg2, &setupOp->fd);
default:
ls_stderr("Namespace unexpected privileged op #%d\n", op);
@@ -2325,7 +2331,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (privileged_op(privileged_op_socket, PRIV_SEP_OP_BIND_MOUNT,
(op->type == SETUP_RO_BIND_MOUNT ? BIND_READONLY : 0) |
(op->type == SETUP_DEV_BIND_MOUNT ? BIND_DEVICES : 0),
source, dest, &op->fd))
source, dest, op))
rc = -1;
*/
break;
@@ -2333,7 +2339,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
case SETUP_REMOUNT_RO_NO_RECURSIVE:
if (privileged_op(privileged_op_socket,
PRIV_SEP_OP_REMOUNT_RO_NO_RECURSIVE, 0, NULL,
dest, &op->fd))
dest, op))
rc = -1;
break;
@@ -2343,7 +2349,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_PROC_MOUNT, 0, dest, NULL,
&op->fd))
op))
rc = -1;
/* There are a bunch of weird old subdirs of /proc that could
@@ -2374,7 +2380,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_BIND_MOUNT,
BIND_READONLY | BIND_RECURSIVE, subdir, subdir,
&op->fd))
op))
rc = -1;
free(subdir);
if (rc)
@@ -2389,7 +2395,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_TMPFS_MOUNT,
0, dest, NULL, &op->fd))
0, dest, NULL, op))
rc = -1;
if (!rc)
@@ -2406,7 +2412,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_BIND_MOUNT,
BIND_DEVICES | BIND_RECURSIVE, node_src,
node_dest, &op->fd))
node_dest, op))
rc = -1;
free(node_dest);
free(node_src);
@@ -2491,7 +2497,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
}
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_DEVPTS_MOUNT, 0, pts,
NULL, &op->fd))
NULL, op))
rc = -1;
if (!rc && symlink ("pts/ptmx", ptmx) != 0)
{
@@ -2524,7 +2530,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_BIND_MOUNT,
BIND_DEVICES, src_tty_dev,
dest_console, &op->fd))
dest_console, op))
rc = -1;
free(src_tty_dev);
free(dest_console);
@@ -2538,7 +2544,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_TMPFS_MOUNT, 0, dest, NULL,
&op->fd))
op))
rc = -1;
break;
@@ -2548,7 +2554,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_MQUEUE_MOUNT, 0, dest,
NULL, &op->fd))
NULL, op))
rc = -1;
break;
@@ -2603,7 +2609,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
assert (dest != NULL);
if (privileged_op(privileged_op_socket,
PRIV_SEP_OP_SET_HOSTNAME, 0, dest, NULL,
&op->fd))
op))
rc = -1;
break;
@@ -2611,7 +2617,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
if (source != NULL && dest != NULL &&
privileged_op(privileged_op_socket,
PRIV_SEP_OP_COPY, op->flags, source, dest,
&op->fd))
op))
rc = -1;
break;
@@ -2669,7 +2675,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
(op->type == SETUP_RO_BIND_MOUNT ? BIND_READONLY : 0) |
(op->type == SETUP_DEV_BIND_MOUNT ? BIND_DEVICES : 0) |
((op->flags & OP_FLAG_NO_SANDBOX) ? 0 : BIND_RECURSIVE),
source, dest, &op->fd))
source, dest, op))
rc = -1;
break;
default: break;
@@ -2683,7 +2689,7 @@ static int setup_newroot(lscgid_t *pCGI, SetupOp *setupOp,
}
DEBUG_MESSAGE("setup_newroot, completed big loop2, rc: %d\n", rc);
if (!rc && privileged_op(privileged_op_socket,
PRIV_SEP_OP_DONE, 0, NULL, NULL, &op->fd))
PRIV_SEP_OP_DONE, 0, NULL, NULL, op))
{
ls_stderr("Namespace error completing operations\n");
rc = -1;
@@ -2741,6 +2747,20 @@ static int resolve_symlinks_in_ops (SetupOp *setupOp)
{
DEBUG_MESSAGE("Symlink resolved %s to %s\n", old_source,
op->source);
if (strcmp(old_source, op->source))
{
char linked[NOSANDBOX_MAX_FILE_LEN];
ssize_t sz = readlink(old_source, linked, sizeof(linked));
if (sz > 0)
{
linked[sz] = 0;
if (linked[0] == '.')
{
DEBUG_MESSAGE("Mark as suspicious link %s\n", linked);
op->flags |= OP_FLAG_SUSPICIOUS_LINK;
}
}
}
if (op->flags & OP_FLAG_ALLOCATED_SOURCE)
free(old_source);
op->flags |= OP_FLAG_ALLOCATED_SOURCE;
+81 -41
View File
@@ -30,6 +30,9 @@
#include "lscgid.h"
#include "use_bwrap.h"
/* Default nosandbox info if neither file exists. Must be sorted here. */
char *s_nosandbox_def[] = { "/usr/sbin/sendmail" };
char *s_nosandbox = NULL;
char **s_nosandbox_arr = NULL; /* At the end of no_sandbox and sorted. */
int s_nosandbox_count = 0;
@@ -826,12 +829,40 @@ static int read_hostexec_files(char *filename, FILE *fh, int *no_sandbox_len)
}
static int build_nosandboxpgm(char *pathname)
{
char nosandbox_pgm[NOSANDBOX_MAX_FILE_LEN];
snprintf(nosandbox_pgm, sizeof(nosandbox_pgm), NOSANDBOX_PGM, pathname);
if (access(nosandbox_pgm, X_OK) != 0)
{
ls_stderr("hostexec program (%s) is not an executable program: %s\n",
nosandbox_pgm, strerror(errno));
return -1;
}
if (!(s_nosandbox_pgm = strdup(nosandbox_pgm)))
{
ls_stderr("Insufficient memory to allocate program space\n");
return -1;
}
return 0;
}
static int nodef()
{
int count = (int)(sizeof(s_nosandbox_def) / sizeof(char **));
for (int i = 0; i < count; i++)
if (!access(s_nosandbox_def[i], 0))
return 0;
DEBUG_MESSAGE("Default entries do not exist\n")
return 1;
}
int nsnosandbox_init()
{
if (s_nosandbox)
return 0;
char pathname[NOSANDBOX_MAX_FILE_LEN / 2], filename[NOSANDBOX_MAX_FILE_LEN],
nosandbox_pgm[NOSANDBOX_MAX_FILE_LEN], nosandbox_force_symlink_file[NOSANDBOX_MAX_FILE_LEN];
nosandbox_force_symlink_file[NOSANDBOX_MAX_FILE_LEN];
ns_lsws_home(pathname, sizeof(pathname));
snprintf(nosandbox_force_symlink_file, sizeof(nosandbox_force_symlink_file),
NOSANDBOX_FORCE_SYMLINK, pathname);
@@ -842,53 +873,67 @@ int nsnosandbox_init()
}
snprintf(filename, sizeof(filename), NOSANDBOX_CONF, pathname);
FILE *fh = fopen(filename, "r");
int use_default = 0;
if (!fh)
{
int no_def1 = 0;
if (errno == ENOENT && !nodef())
no_def1 = 1;
DEBUG_MESSAGE("Error reading hostexec file: %s: %s, ok to not be there\n",
filename, strerror(errno));
snprintf(filename, sizeof(filename), NOSANDBOX2_CONF, pathname);
fh = fopen(filename, "r");
if (!fh)
{
DEBUG_MESSAGE("Error reading hostexec file: %s: %s, ok to not be there\n",
filename, strerror(errno));
return 0;
if (errno == ENOENT && no_def1)
{
DEBUG_MESSAGE("Use default hostexec!\n");
use_default = 1;
s_nosandbox = (char *)s_nosandbox_def;
s_nosandbox_arr = s_nosandbox_def;
s_nosandbox_count = sizeof(s_nosandbox_def) / sizeof(char **);
DEBUG_MESSAGE("There are %d hostexec files\n", s_nosandbox_count);
if (build_nosandboxpgm(pathname))
return -1;
}
else
{
DEBUG_MESSAGE("Error reading hostexec file: %s: %s, ok to not be there\n",
filename, strerror(errno));
return 0;
}
}
}
int no_sandbox_len = 0;
if (read_hostexec_files(filename, fh, &no_sandbox_len))
return -1;
if (s_nosandbox_count)
if (!use_default)
{
snprintf(nosandbox_pgm, sizeof(nosandbox_pgm), NOSANDBOX_PGM, pathname);
if (access(nosandbox_pgm, X_OK) != 0)
{
ls_stderr("hostexec program (%s) is not an executable program: %s\n",
nosandbox_pgm, strerror(errno));
int no_sandbox_len = 0;
if (read_hostexec_files(filename, fh, &no_sandbox_len))
return -1;
}
if (!(s_nosandbox_pgm = strdup(nosandbox_pgm)))
if (s_nosandbox_count)
{
ls_stderr("Insufficient memory to allocate program space\n");
return -1;
}
int last_len = no_sandbox_len;
no_sandbox_len += (s_nosandbox_count * sizeof(char *));
s_nosandbox = realloc(s_nosandbox, no_sandbox_len);
s_nosandbox_arr = (char **)&s_nosandbox[last_len];
int pos = 0;
for (int i = 0; i < s_nosandbox_count; i++)
{
s_nosandbox_arr[i] = &s_nosandbox[pos];
pos += (strlen(s_nosandbox_arr[i]) + 1);
DEBUG_MESSAGE("s_sandbox_arr[%d]: %s\n", i, s_nosandbox_arr[i]);
}
qsort(s_nosandbox_arr, s_nosandbox_count, sizeof(char *), compareStrings);
DEBUG_MESSAGE("After sort There are %d hostexec files\n", s_nosandbox_count);
for (int i = 0; i < s_nosandbox_count; i++)
{
DEBUG_MESSAGE("s_sandbox_arr[%d]: %s\n", i, s_nosandbox_arr[i]);
if (build_nosandboxpgm(pathname))
return -1;
int last_len = no_sandbox_len;
no_sandbox_len += (s_nosandbox_count * sizeof(char *));
s_nosandbox = realloc(s_nosandbox, no_sandbox_len);
s_nosandbox_arr = (char **)&s_nosandbox[last_len];
int pos = 0;
for (int i = 0; i < s_nosandbox_count; i++)
{
s_nosandbox_arr[i] = &s_nosandbox[pos];
pos += (strlen(s_nosandbox_arr[i]) + 1);
DEBUG_MESSAGE("s_sandbox_arr[%d]: %s\n", i, s_nosandbox_arr[i]);
}
qsort(s_nosandbox_arr, s_nosandbox_count, sizeof(char *), compareStrings);
DEBUG_MESSAGE("After sort There are %d hostexec files\n", s_nosandbox_count);
for (int i = 0; i < s_nosandbox_count; i++)
{
DEBUG_MESSAGE("s_sandbox_arr[%d]: %s\n", i, s_nosandbox_arr[i]);
}
}
}
if (s_nosandbox_count)
{
if (save_links())
return -1;
if (open_nosandbox_socket())
@@ -899,12 +944,6 @@ int nsnosandbox_init()
}
void nsnosandbox_resort()
{
qsort(s_nosandbox_arr, s_nosandbox_count, sizeof(char *), compareStrings);
}
void nsnosandbox_done()
{
DEBUG_MESSAGE("nsnosandbox_done\n");
@@ -913,7 +952,8 @@ void nsnosandbox_done()
close(s_nosandbox_socket);
s_nosandbox_socket = -1;
}
free(s_nosandbox);
if (s_nosandbox != (char *)s_nosandbox_def)
free(s_nosandbox);
s_nosandbox = NULL;
free(s_nosandbox_pgm);
s_nosandbox_pgm = NULL;
+2 -1
View File
@@ -50,7 +50,8 @@ typedef enum {
#define OP_FLAG_SOURCE_CREATE 128
#define OP_FLAG_NO_SANDBOX 256
#define OP_FLAG_DO_BIND 512
#define OP_FLAG_LAST 1024
#define OP_FLAG_SUSPICIOUS_LINK 1024
#define OP_FLAG_LAST 2048
typedef struct _SetupOp SetupOp;
+9 -3
View File
@@ -19,6 +19,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
#include <sys/file.h>
#include <sys/fsuid.h>
#include <sys/mount.h>
@@ -280,13 +281,18 @@ int is_persisted(lscgid_t *pCGI, int must_persist, int *persisted)
}
#ifndef __NR_setns
#if defined(__aarch64__)
#define __NR_setns 268
#else
#define __NR_setns 308
int setns(int fd, int nstype)
#endif
#endif
static int sys_setns(int fd, int nstype)
{
DEBUG_MESSAGE("setns, making syscall\n");
return syscall(__NR_setns, fd, nstype);
}
#endif
int nspersist_setvhost(char *vhenv)
{
@@ -1699,7 +1705,7 @@ static int persist_use_child(lscgid_t *pCGI)
ls_stderr("Namespace error opening namespace for %s: %s\n",
ns_filename, strerror(errno));
}
else if (setns(fd, 0))
else if (sys_setns(fd, 0))
{
rc = -1;
ls_stderr("Namespace error setting namespace: %s\n", strerror(errno));
+6 -3
View File
@@ -408,10 +408,13 @@ int AccessLog::appendEscape(const char *pStr, int len)
if (m_buf.available() < 10)
flush();
if ((ch < 0x20) || (ch >= 127))
if (ch == '\t')
{
m_buf.append('\\');
m_buf.append('x');
m_buf.append("\\t", 2);
}
else if ((ch < 0x20) || (ch >= 127))
{
m_buf.append("\\\\x", 3);
m_buf.append(StringTool::getHex(ch >> 4));
m_buf.append(StringTool::getHex(ch));
}
+4 -4
View File
@@ -152,7 +152,7 @@ void HttpRespHeaders::reset2()
{
if (m_KVPairindex[H_SET_COOKIE] == HRH_IDX_NONE)
{
reset();
reset(m_flags & HRH_F_LC_NAME);
return;
}
if (m_iHeaderUniqueCount == 1)
@@ -163,7 +163,7 @@ void HttpRespHeaders::reset2()
max = getHeader(H_SET_COOKIE, iov, 100);
AutoBuf tmp;
tmp.swap(m_buf);
reset();
reset(m_flags & HRH_F_LC_NAME);
pIovEnd = &iov[max];
for (pIov = iov; pIov < pIovEnd; ++pIov)
add(H_SET_COOKIE, "Set-Cookie", 10, (char *)pIov->iov_base,
@@ -171,9 +171,9 @@ void HttpRespHeaders::reset2()
}
void HttpRespHeaders::reset()
void HttpRespHeaders::reset(int flag)
{
m_flags = 0;
m_flags = flag;
m_iHeaderUniqueCount = 0;
m_buf.clear();
memset(m_KVPairindex, 0xFF, sizeof(m_KVPairindex));
+1 -1
View File
@@ -116,7 +116,7 @@ public:
HttpRespHeaders();
~HttpRespHeaders();
void reset();
void reset(int flag = 0);
void reset2();
const lsxpack_header *begin() const { return m_lsxpack.begin(); }
+16 -13
View File
@@ -218,7 +218,9 @@ const struct sockaddr *HttpSession::getPeerAddr() const
bool HttpSession::shouldIncludePeerAddr() const
{
if (getStream()->isFromLocalAddr())
if (getStream()->isFromLocalAddr()
&& (!m_request.isCfRealIpSet()
|| m_request.isHeaderSet(HttpHeader::H_X_FORWARDED_FOR)))
return false;
if (HttpServerConfig::getInstance().getUseProxyHeader() != 3)
return true;
@@ -2022,7 +2024,8 @@ bool HttpSession::shouldAvoidRecaptchaEx()
const Recaptcha *pRecaptcha = m_request.getRecaptcha(),
*pServerRecaptcha = HttpServerConfig::getInstance()
.getGlobalVHost()->getRecaptcha();
if (pServerRecaptcha == NULL)
return true;
// check bots
if (m_request.isGoodBot()
|| pServerRecaptcha->isBotWhitelisted(pUserAgent, iUserAgentLen)
@@ -4380,7 +4383,7 @@ int HttpSession::endResponse(int success)
{
// header is not sent yet, no body sent yet.
//content length = dynamic content + static send file
long size = m_sendFileInfo.getRemain();
off_t size = m_sendFileInfo.getRemain();
if (getRespBodyBuf())
size += getRespBodyBuf()->getCurWOffset();
@@ -5233,7 +5236,7 @@ void HttpSession::setSendFileBeginEnd(off_t start, off_t end)
{
m_sendFileInfo.setCurPos(start);
m_sendFileInfo.setCurEnd(end);
LS_DBG_M(getLogSession(), "setSendFileBeginEnd %ld, %ld remain %ld",
LS_DBG_M(getLogSession(), "setSendFileBeginEnd %jd, %jd remain %jd",
m_sendFileInfo.getCurPos(), m_sendFileInfo.getCurEnd(), m_sendFileInfo.getRemain());
if ((end > start) && getFlag(HSF_RESP_WAIT_FULL_BODY))
{
@@ -5298,8 +5301,8 @@ int HttpSession::writeRespBodyBlockFilterInternal(SendFileInfo *pData,
int HttpSession::postAsyncRead(SendFileInfo *pData)
{
int remain = pData->getRemain();
int len = (remain < (int)HttpServerConfig::getInstance().getAioBlockSize()) ?
off_t remain = pData->getRemain();
off_t len = (remain < (int)HttpServerConfig::getInstance().getAioBlockSize()) ?
remain : (int)HttpServerConfig::getInstance().getAioBlockSize();
struct iovec *iov = m_pAioReq->getIovec();
iov->iov_len = len;
@@ -5386,8 +5389,8 @@ int HttpSession::sendStaticFileAsync(SendFileInfo *pData)
int HttpSession::aioRead(SendFileInfo *pData, void *pBuf)
{
int remain = pData->getRemain();
int len = (remain < STATIC_FILE_BLOCK_SIZE) ? remain :
off_t remain = pData->getRemain();
off_t len = (remain < STATIC_FILE_BLOCK_SIZE) ? remain :
STATIC_FILE_BLOCK_SIZE;
if (!pBuf)
pBuf = ls_palloc(STATIC_FILE_BLOCK_SIZE);
@@ -5507,7 +5510,7 @@ int HttpSession::sendStaticFileEx(SendFileInfo *pData)
len = writeRespBodySendFile(fd, pData->getCurPos(), remain,
pData->getRemain() <= remain);
LS_DBG_M(getLogSession(), "writeRespBodySendFile() write %ld returned %zd.",
LS_DBG_M(getLogSession(), "writeRespBodySendFile() write %jd returned %zd.",
remain, len);
if (len > 0)
{
@@ -5539,7 +5542,7 @@ int HttpSession::sendStaticFileEx(SendFileInfo *pData)
{
char *block = buf;
int written = 0;
LS_DBG_M(getLogSession(), "sendStaticFileEx getStaticFileBlock, remain: %ld\n", remain);
LS_DBG_M(getLogSession(), "sendStaticFileEx getStaticFileBlock, remain: %jd\n", remain);
int ret = getStaticFileBlock(pData, remain, &block, &written);
pBuf = block;
if (ret)
@@ -5564,7 +5567,7 @@ int HttpSession::sendStaticFileEx(SendFileInfo *pData)
return 1;
}
}
LS_DBG_M(getLogSession(), "sendStaticFileEx out of loop, remain: %ld\n", remain);
LS_DBG_M(getLogSession(), "sendStaticFileEx out of loop, remain: %jd\n", remain);
return (pData->getRemain() > 0);
}
@@ -5876,7 +5879,7 @@ int HttpSession::processAsyncData(SendFileInfo *pData)
int read, ret;
ret = m_pAioReq->getRead(&pBuf, pData->getCurPos(), &read);
LS_DBG(getLogSession(), "getRead(): ret: %d, read: %d, remain: %ld\n",
LS_DBG(getLogSession(), "getRead(): ret: %d, read: %d, remain: %jd\n",
ret, read, pData->getRemain());
if (ret < 0)
return -1;
@@ -5972,7 +5975,7 @@ int HttpSession::onAioReqEvent()
{
LS_NOTICE(getLogSession(), "onAioReqEvent canceled AIO request returned, can release HttpSession now\n");
}
LS_DBG(getLogSession(), "onAioReqEvent, remain: %ld\n", m_sendFileInfo.getRemain());
LS_DBG(getLogSession(), "onAioReqEvent, remain: %jd\n", m_sendFileInfo.getRemain());
return processAsyncData(&m_sendFileInfo);
}
+1 -2
View File
@@ -1044,7 +1044,7 @@ int RewriteEngine::expandEnv(const RewriteRule *pRule,
char achBuf[REWRITE_BUF_SIZE];
if (!pEnv)
return 0;
while (pEnv)
for (; pEnv; pEnv = (RewriteSubstFormat *)pEnv->next())
{
len = REWRITE_BUF_SIZE - 1;
buildString(pEnv, pSession, achBuf, len);
@@ -1207,7 +1207,6 @@ int RewriteEngine::expandEnv(const RewriteRule *pRule,
"[REWRITE] add ENV: '%s:%s' ", pKey, pValue);
}
}
pEnv = (RewriteSubstFormat *)pEnv->next();
}
return 0;
-1
View File
@@ -217,7 +217,6 @@ int FileCacheDataEx::readyData(const char *pPath)
else
release();
}
return -1;
}
#if 0
else if (((size_t)m_lSize < s_iMaxMMapCacheSize)
+1 -1
View File
@@ -90,7 +90,7 @@
/***
* Do not change the below format, it will be set correctly while packing the code
*/
#define BUILDTIME "built: Tue Aug 5 13:09:20 UTC 2025"
#define BUILDTIME "built: Tue Nov 4 13:44:54 UTC 2025"
static const char s_pVersionFull[] = "LiteSpeed/" PACKAGE_VERSION
" Open (" LS_MODULE_VERSION_INFO_ONELINE ") BUILD (" BUILDTIME ")";
+2 -1
View File
@@ -1823,7 +1823,8 @@ void LsShmHash::lruMarkNewest(LsShmHElem *pElem, iteroffset offElem)
set_linkPrev(next, prev);
pLink->x_iLinkNext.m_iOffset = 0;
pLink->x_iLinkPrev = pLru->linkNewest;
set_linkNext(pLru->linkNewest, offElem);
if (pLru->linkNewest.m_iOffset)
set_linkNext(pLru->linkNewest, offElem);
pLru->linkNewest = offElem;
}
pLink->x_lasttime = time((time_t *)NULL);
+28 -13
View File
@@ -833,28 +833,43 @@ LsShmOffset_t LsShmPool::allocFromDataBucket(LsShmSize_t size)
if ((offset = *pBucket) != 0)
{
if (!m_pShm->isOffsetValid(offset))
m_pShm->remap();
np = (LsShmOffset_t *)offset2ptr(offset);
if (!m_pShm->isOffsetValid(*np))
{
LS_ERROR("[SHM] [%d-%d:%p] pool free bucket [%d] corruption, at "
"offset: %d, invalid value: %d, usage: alloc %d, free %d\n",
s_pid, m_pShm->getfd(), this, num, offset, *np,
getDataMap()->x_stat.m_bckt[num].m_iBkAllocated,
getDataMap()->x_stat.m_bckt[num].m_iBkReleased );
*pBucket = (LsShmOffset_t)0;
m_pShm->remap();
if (!m_pShm->isOffsetValid(offset))
{
LS_ERROR("[SHM] [%d-%d:%p] pool free bucket [%d] corruption, has "
"invalide offset: %d, usage: alloc %d, free %d\n",
s_pid, m_pShm->getfd(), this, num, offset,
getDataMap()->x_stat.m_bckt[num].m_iBkAllocated,
getDataMap()->x_stat.m_bckt[num].m_iBkReleased );
offset = *pBucket = (LsShmOffset_t)0;
}
}
if (offset)
{
np = (LsShmOffset_t *)offset2ptr(offset);
if (!m_pShm->isOffsetValid(*np))
{
LS_ERROR("[SHM] [%d-%d:%p] pool free bucket [%d] corruption, at "
"offset: %d, invalid value: %d, usage: alloc %d, free %d\n",
s_pid, m_pShm->getfd(), this, num, offset, *np,
getDataMap()->x_stat.m_bckt[num].m_iBkAllocated,
getDataMap()->x_stat.m_bckt[num].m_iBkReleased );
*pBucket = (LsShmOffset_t)0;
}
else
*pBucket = *np;
}
else
*pBucket = *np;
}
else
if (offset == 0)
{
if (s_debug_free_bucket == num)
LS_LOGRAW("[DEBUG] [SHM] [%d-%d:%p] freebucket %d is empty for size: %d\n",
s_pid, m_pShm->getfd(), this, num, size);
if ((offset = fillDataBucket(num, size)) == 0)
return 0;
}
}
incrCheck(&getDataMap()->x_stat.m_bckt[num].m_iBkAllocated, 1);
if (s_debug_free_bucket == num)
LS_LOGRAW("[DEBUG] [SHM] [%d-%d:%p] allocate from freebucket, "
+9 -2
View File
@@ -341,14 +341,21 @@ SslContext *SslContext::configOneCert(SslContext *pContext, const char * key_fil
SSL_CTX_get0_chain_certs(pNewContext->get(), &sk);
if (!sk)
{
if (!bundle_file && pConfig->m_sCAFile.c_str())
bundle_file = pConfig->m_sCAFile.c_str();
if (!bundle_file)
{
if (pConfig->m_sCaChainFile.c_str())
bundle_file = pConfig->m_sCaChainFile.c_str();
else if (pConfig->m_sCAFile.c_str())
bundle_file = pConfig->m_sCAFile.c_str();
}
if (bundle_file)
{
if (strcmp(cert_file, bundle_file) == 0)
bundle_file = NULL;
else
{
LS_DBG_L("[SSL:%p] Set CA Chain file: %s for cert: %s\n",
pNewContext, bundle_file, cert_file);
if (pNewContext->setCertificateChainFile(bundle_file) <= 0)
{
LS_ERROR("[SSL] Vhost %s: failed to set Certificate Chain file: %s"
+1 -1
View File
@@ -190,7 +190,7 @@ int main(int argc, char *argv[])
case 's':
vhost = strdup(optarg);
snprintf(env, sizeof(env), "LS_NS_VHOST=%s", cfg2file);
snprintf(env, sizeof(env), "LS_NS_VHOST=%s", vhost);
putenv(env);
break;