Extending Trinity
SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, struct timespec __user *, utime, u32 __user *, uaddr2, u32, val3)
-- just imagine if mmap.2 were barely documented and stale.
- FUTEX_CLOCK_RT: When set, the kernel treats the timeout as an absolute time based on CLOCK_REALTIME as opposed to CLOCK_MONOTONIC. This is only affected by FUTEX_WAIT_BITSET and FUTEX_REQUEUE_PI commands.
- FUTEX_PRIVATE_FLAG: Refers to the user address space mapping, and applies to all operations. The main benefit is that kernel can directly use the virtual address without having to do any lookups or other overhead (vmas, gup, thp, etc.) imposed by shared mappings.
Ever-changing task priorities
Fault/error injections
Feeding user-addresses
So this has been reworked such that trinity now creates a number of locks in shared memory at startup, which has the owner PID and the actual futex. Upon a call, both fields of uaddr get either a random lock or a random address from the mmap playground, each with a 50% chance. The locks follow very simple semantics, where a successful cmpxchg will allow the caller to acquire the lock without the kernel being involved (fastpath), otherwise we need to wait/block through the futex call.
Because of how trinity is structured with callbacks for pre/post syscall invocation, there are a number of racy windows between when the lock is dealt (ie considered contended) with and when the fuzzer actually calls futex(2). As such, this must be taken with a grain of salt, but does exercise lots of real world situations, nonetheless.
Choosing operations
The idea is to randomly perform different operations on the selected futex, such that combinations of wake, wait, requeue are done (both for regular and PI futexes). While passing informed, not-so-random, parameters to the system call reduces the chance of shallow fuzzing, choosing the futex operation will determine the kind of work to be done on the uaddress. As such this part can further determine the usefulness of trinity regarding futexes. However, one cannot get too strict here as reducing the randomness will also limit the usefulness. For now the layout is a 25% chance when performing lock operations. Oh the other hand, for the case of mmap selected uaddress, the operation is left up to trinity to decide.Evaluation and future work
One immediate way of evaluating the changes to trinity is to see the number of successful calls. While this can be a misleading metric, it does at least indicate whether or not many of the bogus parameter passing have been mitigated and replaced with smarter, more informed calls. Tests show that these changes have in fact boosted the amount of successful futex(2) returns; within a trinity run of 10,000 calls with 4 threads, we were able to go from ~470 to nearly ~4300, which is around a 10x improvement. This also means that it takes more time to run trinity as the kernel is doing actual work now with our futexes, not simply returning immediately due to bogus parameters and trivial error checks.
In the future, it would be good to fuzz futexes with memory-back file (uaddress), instead of always relying on anonymous memory. While is perhaps not so interesting from a futex standpoint (with the exception of hashing), it would be good when combining with other memory related calls which actually do things with the file. Another useful direction would be to further investigate operation selection policies. Different models will fuzz different parts of the futex subsystem, and perhaps (very probably, actually) I have not found the best one yet.
SOCIAL SHARE CARD GENERATOR