Child listener blindly trusts file descriptor 3
low swesweep-fasthttp · prefork/prefork.go · Prefork.listen · run #4
Description
In non-reuseport mode the child wraps fd 3 with os.NewFile without verifying that it is the listener created by the master. If a custom CommandProducer does not pass the provided files as ExtraFiles, or if an inherited fd 3 is reused for another purpose, the child may operate on an unintended descriptor. If net.FileListener fails, the os.File wrapper is also not closed.
Triage
Not triaged.
Raw scan report for this file
```json
[
{
"severity": "medium",
"title": "Stale child signals and PID reuse can corrupt child process tracking",
"function": "Prefork.prefork",
"description": "Child exit signals are buffered in sigCh and processed asynchronously. If a replacement child is spawned before a stale signal is processed and the OS reuses that child PID, childProcs[newPid] can overwrite a stale map entry. When the stale signal is later processed, delete(childProcs, pid) may remove the active replacement child, causing the master to lose track of it. The deferred kill may then fail to terminate the orphaned process, and recovery accounting can be incorrect. An attacker who can repeatedly crash child processes, for example through malformed HTTP causing a handler panic or ServeFunc to return, may increase the likelihood of PID reuse and orphaned child processes."
},
{
"severity": "low",
"title": "Nil serve callback causes child process panic",
"function": "Prefork.ListenAndServe",
"description": "ListenAndServe, ListenAndServeTLS, and ListenAndServeTLSEmbed call p.ServeFunc, p.ServeTLSFunc, or p.ServeTLSEmbedFunc in the child branch. If a Prefork value is used without New, or if one of these fields is nil, the child process dereferences a nil function after listenAsChild and panics. This can crash the child repeatedly and lead to denial of service."
},
{
"severity": "low",
"title": "New(nil) panics due to unchecked fasthttp.Server pointer",
"function": "New",
"description": "New accesses s.Logger before checking whether s is nil. Calling New(nil) panics in the caller. A malicious or buggy caller can use this to crash the host process."
},
{
"severity": "low",
"title": "FASTHTTP_PREFORK_CHILD environment variable can force child-mode behavior",
"function": "IsChild",
"description": "IsChild trusts the FASTHTTP_PREFORK_CHILD environment variable. If an attacker can influence the process environment, a master process calling ListenAndServe will take the child path and call listen, which assumes file descriptor 3 is the prefork listener. If fd 3 is invalid or points to an arbitrary inherited descriptor, the server may fail or listen on an unintended socket. This also bypasses the normal master/child spawn path."
},
{
"severity": "low",
"title": "Child listener blindly trusts file descriptor 3",
"function": "Prefork.listen",
"description": "In non-reuseport mode the child wraps fd 3 with os.NewFile without verifying that it is the listener created by the master. If a custom CommandProducer does not pass the provided files as ExtraFiles, or if an inherited fd 3 is reused for another purpose, the child may operate on an unintended descriptor. If net.FileListener fails, the os.File wrapper is also not closed."
},
{
"severity": "low",
"title": "File descriptor and listener leaks in prefork setup",
"function": "Prefork.setTCPListenerFiles",
"description": "setTCPListenerFiles assigns the open listener to p.ln before obtaining an extra file. If tcplistener.File() fails, the already-open listener is not closed. The master also never closes the files stored in p.files after child processes are spawned. Repeated calls to ListenAndServe, especially after error paths or recovery shutdown, can leak file descriptors and eventually exhaust process resources."
},
{
"severity": "low",
"title": "RecoverThreshold can allow unbounded child respawn under child-crash conditions",
"function": "Prefork.prefork",
"description": "RecoverThreshold is used directly without validation. If it is set to a large value from untrusted configuration and an attacker can repeatedly terminate child processes, the master will keep spawning replacement processes, causing process, CPU, and descriptor exhaustion. The default threshold is bounded, but the public field allows a misconfigured or attacker-influenced value to create a denial-of-service condition."
}
]
```