Fossil User Forum

Fossil repository list hangs when /proc mounted within directory
Login

Fossil repository list hangs when /proc mounted within directory

Fossil repository list hangs when /proc mounted within directory

(1) By andygoth on 2018-11-08 03:28:39 [link] [source]

When accessing the repository list in a chroot jail that contains a mounted proc filesystem, Fossil hangs practically forever inside vfile_scan() attempting to recursively enumerate the proc subdirectory. Eventually it dies with some SQL error.

Unmounting /proc restores repository list capability, though at the cost of not being able to limit CPU load.

This is not a new problem. I've known about it for years, though not the reason why, and I'm sorry I haven't reported it until now. Today I decided to give it another shot because I saw updates were made to the repository list code, so I groveled through the code using "gdb --args fossil test-list-page DIRNAME" and found some information on what's going on.

(2) By Christopher M. Fuhrman (cfuhrman) on 2025-06-17 15:55:36 in reply to 1 [source]

I've recently run into this bug myself so don't know if this has been fixed in a later version of fossil or if it's still around.

Software environment:

  • Debian 12 (bookworm) under amd64. Fully patched as of date of this
    post.
  • Apache 2.4.62-1~deb12u2
  • Fossil version 2.21 [3c53b6364e] 2023-02-26 19:24:24 UTC

Fossil environment:

Apache has been set up to act as a gateway via modproxy to a
fossil server. This fossil server has been set up as a systemd service
running under a 'fossil' user with the following arguments:

/usr/bin/fossil server /srv/fossil --port=8088 --repolist --files *.json,*.html,*.js,*.css,*.txt --https --errorlog fossil-server-error.log                                                                        

As this setup will chroot into /srv/fossil I had /proc mounted at
/srv/fossil/proc via the following line in /etc/fstab:

chroot_jail_proc /srv/fossil/proc proc ro 0 0                                                                                                                                                                      

This is to take advantage of the server load protections found in
fossil.

Observed behavior:

When a user navigates to the root URL of the server (e.g.,
https://fossil.example.com/), the forked fossil process will run amok
until all available memory & swap is consumed and the OS OOM reaper
terminates the process.

I hooked up the runaway fossil process to strace and saw it was spewing
the following:

newfstatat(AT_FDCWD, "/srv/fossil/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task\
/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/sel\
f/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/thread-self/fd/22/proc/122687/task/122687/fdinfo/.fslckout", 0x560623bf2f20, 0\
) = -1 ENOENT (No such file or directory)                                                                                                                                                                          
newfstatat(AT_FDCWD, "/srv/fossil/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task\
/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/sel\
f/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/thread-self/fd/22/proc/122687/task/122687/fdinfo/.fos", 0x560623bf2f20, 0) = -\
1 ENOENT (No such file or directory)                                                                                                                                                                               
openat(AT_FDCWD, "/srv/fossil/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136\
867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/ta\
sk/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/thread-self/fd/22/proc/122687/task/122687/fdinfo", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O\
_DIRECTORY) = -1 EACCES (Permission denied)                                                                                                                                                                        
newfstatat(AT_FDCWD, "/srv/fossil/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task\
/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/sel\
f/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/thread-self/fd/22/proc/122687/task/122687/ns/_FOSSIL_", 0x560623bf2f20, 0) = -\
1 ENOENT (No such file or directory)                                                                                                                                                                               
newfstatat(AT_FDCWD, "/srv/fossil/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task\
/                                                                                                                                                                                                                  
136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self\
/                                                                                                                                                                                                                  
task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/self/task/136867/fd/4/proc/thread-self/fd/22/proc/122687/task/122687/ns/.fslckout", 0x560623bf2f20, 0) = -1\
                                                                                                                                                                                                                   
ENOENT (No such file or directory)                                                                                                                                                                                 

(Note this is just sample spewage, not the full output). It looks like
it's getting trapped into a recursive deep-dive into the /proc file
system.

Workaround:

Remove /proc file system from chroot fossil directory (e.g.,
/srv/fossil).

Other Notes:

Debian recently patched their version of fossil to fix interaction with
Apache Server including a fix for CVS-2024-24795. This was released as a
part of Debian 12.11.

(3) By Stephan Beal (stephan) on 2025-06-17 16:24:08 in reply to 2 [link] [source]

It looks like it's getting trapped into a recursive deep-dive into the /proc file system.

The weird thing is that fossil does not look down directories for a checkout db (which is what your output seems to show it doing). It recurses only upwards when doing that.

This is to take advantage of the server load protections found in fossil.

That kinda backfired ;).

Remove /proc file system from chroot fossil directory (e.g., /srv/fossil).

But why does fossil do that? Is there some construct in /proc which somehow fools it from moving upwards to downwards?

Debian recently patched their version of fossil to fix interaction with Apache Server including a fix for CVS-2024-24795. This was released as a part of Debian 12.11.

That's https://security-tracker.debian.org/tracker/CVE-2024-24795, correct?

That page seems to suggest that they're referencing applicable fossil patches, not that they self-patched their version? i'm trying to figure out whether this is something we still need to patch or whether they cherry-pick patched their release with patches already in fossil.

(4) By Richard Hipp (drh) on 2025-06-17 16:44:51 in reply to 3 [link] [source]

But why does fossil do that?

Probably in order to construct a repository list. Check-in 2025-06-17T16:42Z should resolve the issue. Of course, it might create a new issue for anybody who just happens to have a real directory named "proc" that contains Fossil repositories that they want to appear in their repository list....

(5) By aitap on 2025-06-18 08:04:32 in reply to 3 [link] [source]

That page seems to suggest that they're referencing applicable fossil patches, not that they self-patched their version?

Correct. The few Debian-specific patches in the latest Fossil package are about the riscv64 integer overflow and one of the unit tests.