startProcessWithUserNamespace starts a ptraced dummy process to create a user namespace. It runs a goroutine on a single thread as targetHostUID when creating the process and user namespace, ensuring that the kernel attributes user limits to targetHostUID and not containerd's user. On success it ret
(targetHostUID int, unshareFlags uintptr, uidMaps, gidMaps []syscall.SysProcIDMap)
| 123 | // attributes user limits to targetHostUID and not containerd's user. On success |
| 124 | // it returns the pid, pidfd and no error. |
| 125 | func startProcessWithUserNamespace(targetHostUID int, unshareFlags uintptr, uidMaps, gidMaps []syscall.SysProcIDMap) (int, int, error) { |
| 126 | type result struct { |
| 127 | pid int |
| 128 | pidfd int |
| 129 | err error |
| 130 | } |
| 131 | resultChan := make(chan result) |
| 132 | |
| 133 | go func() { |
| 134 | runtime.LockOSThread() |
| 135 | pid, pidfd, err := startProcessWithUsernsLocked(targetHostUID, unshareFlags, uidMaps, gidMaps) |
| 136 | |
| 137 | // If this errored out let the go runtime reap the thread by not unlocking |
| 138 | if err == nil { |
| 139 | runtime.UnlockOSThread() |
| 140 | } |
| 141 | resultChan <- result{pid, pidfd, err} |
| 142 | }() |
| 143 | |
| 144 | res := <-resultChan |
| 145 | return res.pid, res.pidfd, res.err |
| 146 | } |
| 147 | |
| 148 | // startProcessWithUsernsLocked expects the os thread to be locked already. It does |
| 149 | // 1. setresuid() to the targetHostUID user to attribute further user namespace creations to it |
no test coverage detected
searching dependent graphs…