#1430 — renderSessionList() had no staleness guard. Multiple concurrent callers (message send, rename, session switch) could race, allowing a slower older API response to overwrite _allSessions with stale data. Added a generation counter that increments on each call and discards responses from superseded generations. #1470 — docker_init.bash unconditionally called groupmod/usermod even on read-only root filesystems (podman with read_only=true). Added a writability check for /etc/group and /etc/passwd. If read-only and UID/GID already match, the mod is skipped gracefully. If they don't match, a clear error message suggests setting matching IDs or disabling read_only mode.
This commit is contained in:
1 parent
25cb35ee1a
commit
21ba37c486
2 files changed
+25
No files matched your search
@@ -188,8 +188,24 @@ if [ "A${whoami}" == "Ahermeswebuitoo" ]; then
|
|||||||
# We are altering the UID/GID of the hermeswebui user to the desired ones and restarting as that user
|
# We are altering the UID/GID of the hermeswebui user to the desired ones and restarting as that user
|
||||||
# using usermod for the already create hermeswebui user, knowing it is not already in use
|
# using usermod for the already create hermeswebui user, knowing it is not already in use
|
||||||
# per usermod manual: "You must make certain that the named user is not executing any processes when this command is being executed"
|
# per usermod manual: "You must make certain that the named user is not executing any processes when this command is being executed"
|
||||||
|
# Guard for read-only root filesystem (podman with read_only=true, issue #1470).
|
||||||
|
_readonly_root=false
|
||||||
|
if [ ! -w /etc/group ] || [ ! -w /etc/passwd ]; then
|
||||||
|
_readonly_root=true
|
||||||
|
echo " !! Detected read-only root filesystem — /etc/group or /etc/passwd is not writable"
|
||||||
|
fi
|
||||||
|
if [ "A${_readonly_root}" == "Atrue" ]; then
|
||||||
|
_current_hermeswebui_gid=$(id -g hermeswebui 2>/dev/null || echo "")
|
||||||
|
_current_hermeswebui_uid=$(id -u hermeswebui 2>/dev/null || echo "")
|
||||||
|
if [ "A${_current_hermeswebui_gid}" == "A${WANTED_GID}" ] && [ "A${_current_hermeswebui_uid}" == "A${WANTED_UID}" ]; then
|
||||||
|
echo " -- Skipping groupmod/usermod — hermeswebui already has UID ${WANTED_UID} GID ${WANTED_GID} and root fs is read-only"
|
||||||
|
else
|
||||||
|
error_exit "Cannot modify /etc/group or /etc/passwd (read-only root fs). Set UID=${_current_hermeswebui_uid} and GID=${_current_hermeswebui_gid} to match, or run without read_only=true. See issue #1470."
|
||||||
|
fi
|
||||||
|
else
|
||||||
sudo groupmod -o -g ${WANTED_GID} hermeswebui || error_exit "Failed to set GID of hermeswebui user"
|
sudo groupmod -o -g ${WANTED_GID} hermeswebui || error_exit "Failed to set GID of hermeswebui user"
|
||||||
sudo usermod -o -u ${WANTED_UID} hermeswebui || error_exit "Failed to set UID of hermeswebui user"
|
sudo usermod -o -u ${WANTED_UID} hermeswebui || error_exit "Failed to set UID of hermeswebui user"
|
||||||
|
fi
|
||||||
sudo chown -R ${WANTED_UID}:${WANTED_GID} /home/hermeswebui || error_exit "Failed to set owner of /home/hermeswebui"
|
sudo chown -R ${WANTED_UID}:${WANTED_GID} /home/hermeswebui || error_exit "Failed to set owner of /home/hermeswebui"
|
||||||
save_env /tmp/hermeswebuitoo_env.txt
|
save_env /tmp/hermeswebuitoo_env.txt
|
||||||
# restart the script as hermeswebui set with the correct UID/GID this time
|
# restart the script as hermeswebui set with the correct UID/GID this time
|
||||||
|
|||||||
@@ -1359,7 +1359,14 @@ window.addEventListener('resize',()=>{
|
|||||||
if(_sessionActionMenu && _sessionActionAnchor) _positionSessionActionMenu(_sessionActionAnchor);
|
if(_sessionActionMenu && _sessionActionAnchor) _positionSessionActionMenu(_sessionActionAnchor);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Generation counter to discard stale API responses (issue #1430).
|
||||||
|
// Multiple callers (message send, rename, session switch) fire renderSessionList()
|
||||||
|
// concurrently. Without this guard, a slower older response can overwrite _allSessions
|
||||||
|
// with stale data, causing sessions to vanish from the sidebar.
|
||||||
|
let _renderSessionListGen = 0;
|
||||||
|
|
||||||
async function renderSessionList(){
|
async function renderSessionList(){
|
||||||
|
const _gen = ++_renderSessionListGen;
|
||||||
try{
|
try{
|
||||||
if(!($('sessionSearch').value||'').trim()) _contentSearchResults = [];
|
if(!($('sessionSearch').value||'').trim()) _contentSearchResults = [];
|
||||||
const allProfilesQS = _showAllProfiles ? '?all_profiles=1' : '';
|
const allProfilesQS = _showAllProfiles ? '?all_profiles=1' : '';
|
||||||
@@ -1367,6 +1374,8 @@ async function renderSessionList(){
|
|||||||
api('/api/sessions' + allProfilesQS),
|
api('/api/sessions' + allProfilesQS),
|
||||||
api('/api/projects' + allProfilesQS),
|
api('/api/projects' + allProfilesQS),
|
||||||
]);
|
]);
|
||||||
|
// Discard stale response — a newer renderSessionList() call superseded us.
|
||||||
|
if (_gen !== _renderSessionListGen) return;
|
||||||
// Server's other_profile_count tells us how many sessions exist outside the
|
// Server's other_profile_count tells us how many sessions exist outside the
|
||||||
// active profile so the "Show N from other profiles" toggle can render
|
// active profile so the "Show N from other profiles" toggle can render
|
||||||
// without a second round-trip. Stashed on the module for renderSessionListFromCache.
|
// without a second round-trip. Stashed on the module for renderSessionListFromCache.
|
||||||
|
|||||||
Reference in new issue
Block a user