Now comes the trickiest part, which involves moving the result of RAX to RSI before calling commit_creds().
Moving RAX to RDI for commit_creds()
This requires stringing together a collection of gadgets (which took me an age to find). See if you can find them!
I ended up combining these four gadgets:
Gadget 1 is used to set RDX to 0, so we bypass the jne in Gadget 2 and hit ret
Gadget 2 and Gadget 3 move the returned cred struct from RAX to RDX
Gadget 4 moves it from RAX to RDI, then compares RDI to RDX. We need these to be equal to bypass the jne and hit the ret
Returning to userland
Recall that we need swapgs and then iretq. Both can be found easily.
The pop rbp; ret is not important as iretq jumps away anyway.
To simulate the pushing of RIP, CS, SS, etc we just create the stack layout as it would expect - RIP|CS|RFLAGS|SP|SS, the reverse of the order they are pushed in.
If we try this now, we successfully escalate privileges!