Fix credential locking during fork
MODIFY
include/sys/cred.h
include/sys/cred.h
@@ -35,6 +35,10 @@ int do_setgid(proc_t *p, gid_t gid);
int do_setegid(proc_t *p, gid_t egid);
int do_setregid(proc_t *p, gid_t rgid, gid_t egid);
+/* \note Must be called with from::p_lock held. Returns with form::p_lock held.
+ * (We do this only while doing fork, so to is new proc not visible for other
+ * processes.)
+ */
void cred_fork(proc_t *to, proc_t *from);
#endif /* !_KERNEL */

MODIFY
sys/kern/cred.c
sys/kern/cred.c
#include <sys/cred.h>
#include <sys/proc.h>
#include <sys/libkern.h>
+#include <sys/mutex.h>
void cred_fork(proc_t *to, proc_t *from) {
+ assert(mtx_owned(&from->p_lock));
memcpy(&to->p_cred, &from->p_cred, sizeof(cred_t));
}

MODIFY
sys/kern/fork.c
sys/kern/fork.c
@@ -53,8 +53,13 @@ int do_fork(void (*start)(void *), void *arg, pid_t *cldpidp) {
/* Now, prepare a new process. */
proc_t *child = proc_create(newtd, parent);
- /* Clone credentials. */
+ /* Clone credentials.
+ * We have to do it with parent::p_lock held.
+ * We don't need to hold child::p_lock because child is not visible yet.
+ */
+ WITH_PROC_LOCK(parent) {
cred_fork(child, parent);
+ }
/* Clone the entire process memory space. */
child->p_uspace = vm_map_clone(parent->p_uspace);

Fix credential locking during fork (#801)