Module Name:    src
Committed By:   thorpej
Date:           Wed Apr 29 01:55:18 UTC 2020

Modified Files:
        src/sys/compat/linux/common: linux_sched.c

Log Message:
Fix proc / lwp lookup processing in linux_sys_sched_getaffinity()
and linux_sys_sched_setaffinity().  They were incorrect even before
the LWP ID changes, but those changes exposed the latent bugs.


To generate a diff of this commit:
cvs rdiff -u -r1.75 -r1.76 src/sys/compat/linux/common/linux_sched.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/compat/linux/common/linux_sched.c
diff -u src/sys/compat/linux/common/linux_sched.c:1.75 src/sys/compat/linux/common/linux_sched.c:1.76
--- src/sys/compat/linux/common/linux_sched.c:1.75	Fri Apr 24 03:22:06 2020
+++ src/sys/compat/linux/common/linux_sched.c	Wed Apr 29 01:55:18 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_sched.c,v 1.75 2020/04/24 03:22:06 thorpej Exp $	*/
+/*	$NetBSD: linux_sched.c,v 1.76 2020/04/29 01:55:18 thorpej Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2019 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.75 2020/04/24 03:22:06 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.76 2020/04/29 01:55:18 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/mount.h>
@@ -608,6 +608,7 @@ linux_sys_sched_getaffinity(struct lwp *
 		syscallarg(unsigned int) len;
 		syscallarg(unsigned long *) mask;
 	} */
+	struct proc *p;
 	struct lwp *t;
 	kcpuset_t *kcset;
 	size_t size;
@@ -618,15 +619,23 @@ linux_sys_sched_getaffinity(struct lwp *
 	if (SCARG(uap, len) < size)
 		return EINVAL;
 
-	/* Lock the LWP */
-	t = lwp_find2(SCARG(uap, pid), l->l_lid);
-	if (t == NULL)
-		return ESRCH;
+	if (SCARG(uap, pid) == 0) {
+		p = curproc;
+		mutex_enter(p->p_lock);
+		t = curlwp;
+	} else {
+		t = lwp_find2(-1, SCARG(uap, pid));
+		if (__predict_false(t == NULL)) {
+			return ESRCH;
+		}
+		p = t->l_proc;
+		KASSERT(mutex_owned(p->p_lock));
+	}
 
 	/* Check the permission */
 	if (kauth_authorize_process(l->l_cred,
-	    KAUTH_PROCESS_SCHEDULER_GETAFFINITY, t->l_proc, NULL, NULL, NULL)) {
-		mutex_exit(t->l_proc->p_lock);
+	    KAUTH_PROCESS_SCHEDULER_GETAFFINITY, p, NULL, NULL, NULL)) {
+		mutex_exit(p->p_lock);
 		return EPERM;
 	}
 
@@ -644,7 +653,7 @@ linux_sys_sched_getaffinity(struct lwp *
 			kcpuset_set(kcset, i);
 	}
 	lwp_unlock(t);
-	mutex_exit(t->l_proc->p_lock);
+	mutex_exit(p->p_lock);
 	error = kcpuset_copyout(kcset, (cpuset_t *)SCARG(uap, mask), size);
 	kcpuset_unuse(kcset, NULL);
 	*retval = size;
@@ -661,13 +670,28 @@ linux_sys_sched_setaffinity(struct lwp *
 	} */
 	struct sys__sched_setaffinity_args ssa;
 	size_t size;
+	pid_t pid;
 
 	size = LINUX_CPU_MASK_SIZE;
 	if (SCARG(uap, len) < size)
 		return EINVAL;
 
-	SCARG(&ssa, pid) = SCARG(uap, pid);
-	SCARG(&ssa, lid) = l->l_lid;
+	if (SCARG(uap, pid) != 0) {
+		/* Get the canonical PID for the process. */
+		mutex_enter(proc_lock);
+		struct proc *p = proc_find_lwpid(SCARG(uap, pid));
+		if (p == NULL) {
+			mutex_exit(proc_lock);
+			return ESRCH;
+		}
+		pid = p->p_pid;
+		mutex_exit(proc_lock);
+	} else {
+		pid = 0;
+	}
+
+	SCARG(&ssa, pid) = pid;
+	SCARG(&ssa, lid) = SCARG(uap, pid);
 	SCARG(&ssa, size) = size;
 	SCARG(&ssa, cpuset) = (cpuset_t *)SCARG(uap, mask);
 

Reply via email to