Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 27 Apr 2020 04:47:02 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r360363 - in stable/12/sys: compat/linux kern
Message-ID:  <202004270447.03R4l2nB060579@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Mon Apr 27 04:47:02 2020
New Revision: 360363
URL: https://svnweb.freebsd.org/changeset/base/360363

Log:
  MFC 350012: Always set td_errno to the error value of a system call.
  
  Early errors prior to a system call did not set td_errno.  This commit
  sets td_errno for all errors during syscallenter().  As a result,
  syscallret() can now always use td_errno without checking TDP_NERRNO.
  
  Compared to the original commit, this change preserves the ABI of
  struct thread and instead adds explicit zero'ing of td_errno.

Modified:
  stable/12/sys/compat/linux/linux_fork.c
  stable/12/sys/kern/kern_fork.c
  stable/12/sys/kern/kern_kthread.c
  stable/12/sys/kern/kern_thr.c
  stable/12/sys/kern/subr_syscall.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/compat/linux/linux_fork.c
==============================================================================
--- stable/12/sys/compat/linux/linux_fork.c	Mon Apr 27 03:57:17 2020	(r360362)
+++ stable/12/sys/compat/linux/linux_fork.c	Mon Apr 27 04:47:02 2020	(r360363)
@@ -310,6 +310,7 @@ linux_clone_thread(struct thread *td, struct linux_clo
 	bzero(&newtd->td_startzero,
 	    __rangeof(struct thread, td_startzero, td_endzero));
 	newtd->td_pflags2 = 0;
+	newtd->td_errno = 0;
 	bcopy(&td->td_startcopy, &newtd->td_startcopy,
 	    __rangeof(struct thread, td_startcopy, td_endcopy));
 

Modified: stable/12/sys/kern/kern_fork.c
==============================================================================
--- stable/12/sys/kern/kern_fork.c	Mon Apr 27 03:57:17 2020	(r360362)
+++ stable/12/sys/kern/kern_fork.c	Mon Apr 27 04:47:02 2020	(r360363)
@@ -490,6 +490,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct
 	bzero(&td2->td_startzero,
 	    __rangeof(struct thread, td_startzero, td_endzero));
 	td2->td_pflags2 = 0;
+	td2->td_errno = 0;
 
 	bcopy(&td->td_startcopy, &td2->td_startcopy,
 	    __rangeof(struct thread, td_startcopy, td_endcopy));

Modified: stable/12/sys/kern/kern_kthread.c
==============================================================================
--- stable/12/sys/kern/kern_kthread.c	Mon Apr 27 03:57:17 2020	(r360362)
+++ stable/12/sys/kern/kern_kthread.c	Mon Apr 27 04:47:02 2020	(r360363)
@@ -284,6 +284,7 @@ kthread_add(void (*func)(void *), void *arg, struct pr
 	bzero(&newtd->td_startzero,
 	    __rangeof(struct thread, td_startzero, td_endzero));
 	newtd->td_pflags2 = 0;
+	newtd->td_errno = 0;
 	bcopy(&oldtd->td_startcopy, &newtd->td_startcopy,
 	    __rangeof(struct thread, td_startcopy, td_endcopy));
 

Modified: stable/12/sys/kern/kern_thr.c
==============================================================================
--- stable/12/sys/kern/kern_thr.c	Mon Apr 27 03:57:17 2020	(r360362)
+++ stable/12/sys/kern/kern_thr.c	Mon Apr 27 04:47:02 2020	(r360363)
@@ -236,6 +236,7 @@ thread_create(struct thread *td, struct rtprio *rtp,
 	bzero(&newtd->td_startzero,
 	    __rangeof(struct thread, td_startzero, td_endzero));
 	newtd->td_pflags2 = 0;
+	newtd->td_errno = 0;
 	bcopy(&td->td_startcopy, &newtd->td_startcopy,
 	    __rangeof(struct thread, td_startcopy, td_endcopy));
 	newtd->td_proc = td->td_proc;

Modified: stable/12/sys/kern/subr_syscall.c
==============================================================================
--- stable/12/sys/kern/subr_syscall.c	Mon Apr 27 03:57:17 2020	(r360362)
+++ stable/12/sys/kern/subr_syscall.c	Mon Apr 27 04:47:02 2020	(r360363)
@@ -85,8 +85,10 @@ syscallenter(struct thread *td)
 	    (uintptr_t)td, "pid:%d", td->td_proc->p_pid, "arg0:%p", sa->args[0],
 	    "arg1:%p", sa->args[1], "arg2:%p", sa->args[2]);
 
-	if (error != 0)
+	if (error != 0) {
+		td->td_errno = error;
 		goto retval;
+	}
 
 	STOPEVENT(p, S_SCE, sa->narg);
 	if ((p->p_flag & P_TRACED) != 0) {
@@ -105,8 +107,10 @@ syscallenter(struct thread *td)
 		if (KTRPOINT(td, KTR_SYSCALL))
 			ktrsyscall(sa->code, sa->narg, sa->args);
 #endif
-		if (error != 0)
+		if (error != 0) {
+			td->td_errno = error;
 			goto retval;
+		}
 	}
 
 #ifdef CAPABILITY_MODE
@@ -116,14 +120,16 @@ syscallenter(struct thread *td)
 	 */
 	if (IN_CAPABILITY_MODE(td) &&
 	    !(sa->callp->sy_flags & SYF_CAPENABLED)) {
-		error = ECAPMODE;
+		td->td_errno = error = ECAPMODE;
 		goto retval;
 	}
 #endif
 
 	error = syscall_thread_enter(td, sa->callp);
-	if (error != 0)
+	if (error != 0) {
+		td->td_errno = error;
 		goto retval;
+	}
 
 #ifdef KDTRACE_HOOKS
 	/* Give the syscall:::entry DTrace probe a chance to fire. */
@@ -131,6 +137,9 @@ syscallenter(struct thread *td)
 		(*systrace_probe_func)(sa, SYSTRACE_ENTRY, 0);
 #endif
 
+	/* Let system calls set td_errno directly. */
+	td->td_pflags &= ~TDP_NERRNO;
+
 	AUDIT_SYSCALL_ENTER(sa->code, td);
 	error = (sa->callp->sy_call)(td, sa->args);
 	AUDIT_SYSCALL_EXIT(error, td);
@@ -162,12 +171,12 @@ syscallenter(struct thread *td)
 }
 
 static inline void
-syscallret(struct thread *td, int error)
+syscallret(struct thread *td, int error __unused)
 {
 	struct proc *p, *p2;
 	struct syscall_args *sa;
 	ksiginfo_t ksi;
-	int traced, error1;
+	int traced;
 
 	KASSERT((td->td_pflags & TDP_FORKING) == 0,
 	    ("fork() did not clear TDP_FORKING upon completion"));
@@ -176,12 +185,10 @@ syscallret(struct thread *td, int error)
 	sa = &td->td_sa;
 	if ((trap_enotcap || (p->p_flag2 & P2_TRAPCAP) != 0) &&
 	    IN_CAPABILITY_MODE(td)) {
-		error1 = (td->td_pflags & TDP_NERRNO) == 0 ? error :
-		    td->td_errno;
-		if (error1 == ENOTCAPABLE || error1 == ECAPMODE) {
+		if (td->td_errno == ENOTCAPABLE || td->td_errno == ECAPMODE) {
 			ksiginfo_init_trap(&ksi);
 			ksi.ksi_signo = SIGTRAP;
-			ksi.ksi_errno = error1;
+			ksi.ksi_errno = td->td_errno;
 			ksi.ksi_code = TRAP_CAP;
 			trapsignal(td, &ksi);
 		}
@@ -194,11 +201,9 @@ syscallret(struct thread *td, int error)
 
 #ifdef KTRACE
 	if (KTRPOINT(td, KTR_SYSRET)) {
-		ktrsysret(sa->code, (td->td_pflags & TDP_NERRNO) == 0 ?
-		    error : td->td_errno, td->td_retval[0]);
+		ktrsysret(sa->code, td->td_errno, td->td_retval[0]);
 	}
 #endif
-	td->td_pflags &= ~TDP_NERRNO;
 
 	if (p->p_flag & P_TRACED) {
 		traced = 1;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202004270447.03R4l2nB060579>