Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 May 2018 07:57:36 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r333162 - in stable/11: lib/libc/sys sys/compat/freebsd32 sys/kern sys/sys tests/sys/kern
Message-ID:  <201805020757.w427vaQd080376@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed May  2 07:57:36 2018
New Revision: 333162
URL: https://svnweb.freebsd.org/changeset/base/333162

Log:
  MFC r332740:
  Add PROC_PDEATHSIG_SET to procctl interface.
  
  MFC r332825:
  Rename PROC_PDEATHSIG_SET -> PROC_PDEATHSIG_CTL.
  
  MFC r333067:
  Remove redundant pipe from pdeathsig.c test.

Added:
  stable/11/tests/sys/kern/pdeathsig.c
     - copied, changed from r332740, head/tests/sys/kern/pdeathsig.c
  stable/11/tests/sys/kern/pdeathsig_helper.c
     - copied, changed from r332740, head/tests/sys/kern/pdeathsig_helper.c
Modified:
  stable/11/lib/libc/sys/procctl.2
  stable/11/sys/compat/freebsd32/freebsd32_misc.c
  stable/11/sys/kern/kern_exec.c
  stable/11/sys/kern/kern_exit.c
  stable/11/sys/kern/kern_fork.c
  stable/11/sys/kern/kern_procctl.c
  stable/11/sys/sys/proc.h
  stable/11/sys/sys/procctl.h
  stable/11/tests/sys/kern/Makefile
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/lib/libc/sys/procctl.2
==============================================================================
--- stable/11/lib/libc/sys/procctl.2	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/lib/libc/sys/procctl.2	Wed May  2 07:57:36 2018	(r333162)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd November 21, 2017
+.Dd April 20, 2018
 .Dt PROCCTL 2
 .Os
 .Sh NAME
@@ -391,6 +391,37 @@ otherwise.
 See the note about sysctl
 .Dv kern.trap_enocap
 above, which gives independent global control of signal delivery.
+.It Dv PROC_PDEATHSIG_CTL
+Request the delivery of a signal when the parent of the calling
+process exits.
+.Fa idtype
+must be
+.Dv P_PID
+and
+.Fa id
+must be the either caller's pid or zero, with no difference in effect.
+The value is cleared for child processes
+and when executing set-user-ID or set-group-ID binaries.
+.Fa arg
+must point to a value of type
+.Vt int
+indicating the signal
+that should be delivered to the caller.
+Use zero to cancel a previously requested signal delivery.
+.It Dv PROC_PDEATHSIG_STATUS
+Query the current signal number that will be delivered when the parent
+of the calling process exits.
+.Fa idtype
+must be
+.Dv P_PID
+and
+.Fa id
+must be the either caller's pid or zero, with no difference in effect.
+.Fa arg
+must point to a memory location that can hold a value of type
+.Vt int .
+If signal delivery has not been requested, it will contain zero
+on return.
 .El
 .Sh NOTES
 Disabling tracing on a process should not be considered a security
@@ -487,6 +518,15 @@ parameter for the
 or
 .Dv PROC_TRAPCAP_CTL
 request is invalid.
+.It Bq Er EINVAL
+The
+.Dv PROC_PDEATHSIG_CTL
+or
+.Dv PROC_PDEATHSIG_STATUS
+request referenced an unsupported
+.Fa id ,
+.Fa idtype
+or invalid signal number.
 .El
 .Sh SEE ALSO
 .Xr dtrace 1 ,
@@ -506,3 +546,8 @@ function appeared in
 The reaper facility is based on a similar feature of Linux and
 DragonflyBSD, and first appeared in
 .Fx 10.2 .
+The
+.Dv PROC_PDEATHSIG_CTL
+facility is based on the prctl(PR_SET_PDEATHSIG, ...) feature of Linux,
+and first appeared in
+.Fx 12.0 .

Modified: stable/11/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/11/sys/compat/freebsd32/freebsd32_misc.c	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/sys/compat/freebsd32/freebsd32_misc.c	Wed May  2 07:57:36 2018	(r333162)
@@ -3057,7 +3057,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_
 	union {
 		struct procctl_reaper_pids32 rp;
 	} x32;
-	int error, error1, flags;
+	int error, error1, flags, signum;
 
 	switch (uap->com) {
 	case PROC_SPROTECT:
@@ -3095,6 +3095,15 @@ freebsd32_procctl(struct thread *td, struct freebsd32_
 	case PROC_TRAPCAP_STATUS:
 		data = &flags;
 		break;
+	case PROC_PDEATHSIG_CTL:
+		error = copyin(uap->data, &signum, sizeof(signum));
+		if (error != 0)
+			return (error);
+		data = &signum;
+		break;
+	case PROC_PDEATHSIG_STATUS:
+		data = &signum;
+		break;
 	default:
 		return (EINVAL);
 	}
@@ -3114,6 +3123,10 @@ freebsd32_procctl(struct thread *td, struct freebsd32_
 	case PROC_TRAPCAP_STATUS:
 		if (error == 0)
 			error = copyout(&flags, uap->data, sizeof(flags));
+		break;
+	case PROC_PDEATHSIG_STATUS:
+		if (error == 0)
+			error = copyout(&signum, uap->data, sizeof(signum));
 		break;
 	}
 	return (error);

Modified: stable/11/sys/kern/kern_exec.c
==============================================================================
--- stable/11/sys/kern/kern_exec.c	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/sys/kern/kern_exec.c	Wed May  2 07:57:36 2018	(r333162)
@@ -520,6 +520,10 @@ interpret:
 	credential_changing |= will_transition;
 #endif
 
+	/* Don't inherit PROC_PDEATHSIG_CTL value if setuid/setgid. */
+	if (credential_changing)
+		imgp->proc->p_pdeathsig = 0;
+
 	if (credential_changing &&
 #ifdef CAPABILITY_MODE
 	    ((oldcred->cr_flags & CRED_FLAG_CAPMODE) == 0) &&

Modified: stable/11/sys/kern/kern_exit.c
==============================================================================
--- stable/11/sys/kern/kern_exit.c	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/sys/kern/kern_exit.c	Wed May  2 07:57:36 2018	(r333162)
@@ -479,6 +479,12 @@ exit1(struct thread *td, int rval, int signo)
 				PROC_LOCK(q->p_reaper);
 				pksignal(q->p_reaper, SIGCHLD, ksi1);
 				PROC_UNLOCK(q->p_reaper);
+			} else if (q->p_pdeathsig > 0) {
+				/*
+				 * The child asked to received a signal
+				 * when we exit.
+				 */
+				kern_psignal(q, q->p_pdeathsig);
 			}
 		} else {
 			/*
@@ -519,6 +525,13 @@ exit1(struct thread *td, int rval, int signo)
 	 */
 	while ((q = LIST_FIRST(&p->p_orphans)) != NULL) {
 		PROC_LOCK(q);
+		/*
+		 * If we are the real parent of this process
+		 * but it has been reparented to a debugger, then
+		 * check if it asked for a signal when we exit.
+		 */
+		if (q->p_pdeathsig > 0)
+			kern_psignal(q, q->p_pdeathsig);
 		CTR2(KTR_PTRACE, "exit: pid %d, clearing orphan %d", p->p_pid,
 		    q->p_pid);
 		clear_orphan(q);

Modified: stable/11/sys/kern/kern_fork.c
==============================================================================
--- stable/11/sys/kern/kern_fork.c	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/sys/kern/kern_fork.c	Wed May  2 07:57:36 2018	(r333162)
@@ -425,6 +425,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct
 	bzero(&p2->p_startzero,
 	    __rangeof(struct proc, p_startzero, p_endzero));
 	p2->p_ptevents = 0;
+	p2->p_pdeathsig = 0;
 
 	/* Tell the prison that we exist. */
 	prison_proc_hold(p2->p_ucred->cr_prison);

Modified: stable/11/sys/kern/kern_procctl.c
==============================================================================
--- stable/11/sys/kern/kern_procctl.c	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/sys/kern/kern_procctl.c	Wed May  2 07:57:36 2018	(r333162)
@@ -431,7 +431,7 @@ sys_procctl(struct thread *td, struct procctl_args *ua
 		struct procctl_reaper_pids rp;
 		struct procctl_reaper_kill rk;
 	} x;
-	int error, error1, flags;
+	int error, error1, flags, signum;
 
 	switch (uap->com) {
 	case PROC_SPROTECT:
@@ -467,6 +467,15 @@ sys_procctl(struct thread *td, struct procctl_args *ua
 	case PROC_TRAPCAP_STATUS:
 		data = &flags;
 		break;
+	case PROC_PDEATHSIG_CTL:
+		error = copyin(uap->data, &signum, sizeof(signum));
+		if (error != 0)
+			return (error);
+		data = &signum;
+		break;
+	case PROC_PDEATHSIG_STATUS:
+		data = &signum;
+		break;
 	default:
 		return (EINVAL);
 	}
@@ -486,6 +495,10 @@ sys_procctl(struct thread *td, struct procctl_args *ua
 		if (error == 0)
 			error = copyout(&flags, uap->data, sizeof(flags));
 		break;
+	case PROC_PDEATHSIG_STATUS:
+		if (error == 0)
+			error = copyout(&signum, uap->data, sizeof(signum));
+		break;
 	}
 	return (error);
 }
@@ -527,6 +540,7 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t 
 	struct pgrp *pg;
 	struct proc *p;
 	int error, first_error, ok;
+	int signum;
 	bool tree_locked;
 
 	switch (com) {
@@ -537,8 +551,31 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t 
 	case PROC_REAP_KILL:
 	case PROC_TRACE_STATUS:
 	case PROC_TRAPCAP_STATUS:
+	case PROC_PDEATHSIG_CTL:
+	case PROC_PDEATHSIG_STATUS:
 		if (idtype != P_PID)
 			return (EINVAL);
+	}
+
+	switch (com) {
+	case PROC_PDEATHSIG_CTL:
+		signum = *(int *)data;
+		p = td->td_proc;
+		if ((id != 0 && id != p->p_pid) ||
+		    (signum != 0 && !_SIG_VALID(signum)))
+			return (EINVAL);
+		PROC_LOCK(p);
+		p->p_pdeathsig = signum;
+		PROC_UNLOCK(p);
+		return (0);
+	case PROC_PDEATHSIG_STATUS:
+		p = td->td_proc;
+		if (id != 0 && id != p->p_pid)
+			return (EINVAL);
+		PROC_LOCK(p);
+		*(int *)data = p->p_pdeathsig;
+		PROC_UNLOCK(p);
+		return (0);
 	}
 
 	switch (com) {

Modified: stable/11/sys/sys/proc.h
==============================================================================
--- stable/11/sys/sys/proc.h	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/sys/sys/proc.h	Wed May  2 07:57:36 2018	(r333162)
@@ -674,6 +674,7 @@ struct proc {
 	uint64_t	p_elf_flags;	/* (x) ELF flags */
 	sigqueue_t	p_sigqueue;	/* (c) Sigs not delivered to a td. */
 #define p_siglist	p_sigqueue.sq_signals
+	int		p_pdeathsig;	/* (c) Signal from parent on exit. */
 };
 
 #define	p_session	p_pgrp->pg_session

Modified: stable/11/sys/sys/procctl.h
==============================================================================
--- stable/11/sys/sys/procctl.h	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/sys/sys/procctl.h	Wed May  2 07:57:36 2018	(r333162)
@@ -49,6 +49,8 @@
 #define	PROC_TRACE_STATUS	8	/* query tracing status */
 #define	PROC_TRAPCAP_CTL	9	/* trap capability errors */
 #define	PROC_TRAPCAP_STATUS	10	/* query trap capability status */
+#define	PROC_PDEATHSIG_CTL	11	/* set parent death signal */
+#define	PROC_PDEATHSIG_STATUS	12	/* get parent death signal */
 
 /* Operations for PROC_SPROTECT (passed in integer arg). */
 #define	PPROT_OP(x)	((x) & 0xf)

Modified: stable/11/tests/sys/kern/Makefile
==============================================================================
--- stable/11/tests/sys/kern/Makefile	Wed May  2 07:42:47 2018	(r333161)
+++ stable/11/tests/sys/kern/Makefile	Wed May  2 07:57:36 2018	(r333162)
@@ -15,6 +15,9 @@ ATF_TESTS_C+=	unix_seqpacket_test
 ATF_TESTS_C+=	unix_passfd_test
 TEST_METADATA.unix_seqpacket_test+=	timeout="15"
 ATF_TESTS_C+=	waitpid_nohang
+ATF_TESTS_C+=	pdeathsig
+
+PROGS+=		pdeathsig_helper
 
 LIBADD.ptrace_test+=			pthread
 LIBADD.unix_seqpacket_test+=		pthread

Copied and modified: stable/11/tests/sys/kern/pdeathsig.c (from r332740, head/tests/sys/kern/pdeathsig.c)
==============================================================================
--- head/tests/sys/kern/pdeathsig.c	Wed Apr 18 21:31:13 2018	(r332740, copy source)
+++ stable/11/tests/sys/kern/pdeathsig.c	Wed May  2 07:57:36 2018	(r333162)
@@ -53,42 +53,42 @@ ATF_TC_BODY(arg_validation, tc)
 
 	/* bad signal */
 	signum = 8888;
-	rc = procctl(P_PID, 0, PROC_PDEATHSIG_SET, &signum);
+	rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
 	ATF_CHECK_EQ(-1, rc);
 	ATF_CHECK_EQ(EINVAL, errno);
 
 	/* bad id type */
 	signum = SIGINFO;
-	rc = procctl(8888, 0, PROC_PDEATHSIG_SET, &signum);
+	rc = procctl(8888, 0, PROC_PDEATHSIG_CTL, &signum);
 	ATF_CHECK_EQ(-1, rc);
 	ATF_CHECK_EQ(EINVAL, errno);
 
 	/* bad id (pid that doesn't match mine or zero) */
 	signum = SIGINFO;
 	rc = procctl(P_PID, (((getpid() + 1) % 10) + 100),
-		     PROC_PDEATHSIG_SET, &signum);
+	    PROC_PDEATHSIG_CTL, &signum);
 	ATF_CHECK_EQ(-1, rc);
 	ATF_CHECK_EQ(EINVAL, errno);
 
 	/* null pointer */
 	signum = SIGINFO;
-	rc = procctl(P_PID, 0, PROC_PDEATHSIG_SET, NULL);
+	rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, NULL);
 	ATF_CHECK_EQ(-1, rc);
 	ATF_CHECK_EQ(EFAULT, errno);
 
 	/* good (pid == 0) */
 	signum = SIGINFO;
-	rc = procctl(P_PID, 0, PROC_PDEATHSIG_SET, &signum);
+	rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
 	ATF_CHECK_EQ(0, rc);
 
 	/* good (pid == my pid) */
 	signum = SIGINFO;
-	rc = procctl(P_PID, getpid(), PROC_PDEATHSIG_SET, &signum);
+	rc = procctl(P_PID, getpid(), PROC_PDEATHSIG_CTL, &signum);
 	ATF_CHECK_EQ(0, rc);
 
 	/* check that we can read the signal number back */
 	signum = 0xdeadbeef;
-	rc = procctl(P_PID, 0, PROC_PDEATHSIG_GET, &signum);
+	rc = procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &signum);
 	ATF_CHECK_EQ(0, rc);
 	ATF_CHECK_EQ(SIGINFO, signum);
 }
@@ -102,14 +102,14 @@ ATF_TC_BODY(fork_no_inherit, tc)
 
 	/* request a signal on parent death in the parent */
 	signum = SIGINFO;
-	rc = procctl(P_PID, 0, PROC_PDEATHSIG_SET, &signum);
+	rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
 
 	rc = fork();
 	ATF_REQUIRE(rc != -1);
 	if (rc == 0) {
 		/* check that we didn't inherit the setting */
 		signum = 0xdeadbeef;
-		rc = procctl(P_PID, 0, PROC_PDEATHSIG_GET, &signum);
+		rc = procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &signum);
 		assert(rc == 0);
 		assert(signum == 0);
 		_exit(0);
@@ -138,7 +138,7 @@ ATF_TC_BODY(exec_inherit, tc)
 
 		/* request a signal on parent death and register a handler */
 		signum = SIGINFO;
-		rc = procctl(P_PID, 0, PROC_PDEATHSIG_SET, &signum);
+		rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
 		assert(rc == 0);
 
 		/* execute helper program: it asserts that it has the setting */
@@ -186,7 +186,7 @@ ATF_TC_BODY(signal_delivered, tc)
 			signal(signum, dummy_signal_handler);
 
 			/* request a signal on death of our parent B */
-			rc = procctl(P_PID, 0, PROC_PDEATHSIG_SET, &signum);
+			rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
 			assert(rc == 0);
 
 			/* tell B that we're ready for it to exit now */
@@ -229,7 +229,6 @@ ATF_TC_BODY(signal_delivered_ptrace, tc)
 	int rc;
 	int pipe_ca[2];
 	int pipe_db[2];
-	int pipe_cd[2];
 	char buffer;
 	int status;
 
@@ -237,8 +236,6 @@ ATF_TC_BODY(signal_delivered_ptrace, tc)
 	ATF_REQUIRE(rc == 0);
 	rc = pipe(pipe_db);
 	ATF_REQUIRE(rc == 0);
-	rc = pipe(pipe_cd);
-	ATF_REQUIRE(rc == 0);
 
 	rc = fork();
 	ATF_REQUIRE(rc != -1);
@@ -263,12 +260,8 @@ ATF_TC_BODY(signal_delivered_ptrace, tc)
 			signal(signum, dummy_signal_handler);
 
 			/* request a signal on parent death and register a handler */
-			rc = procctl(P_PID, 0, PROC_PDEATHSIG_SET, &signum);
+			rc = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum);
 			assert(rc == 0);
-
-			/* tell D we are ready for it to attach */
-			rc = write(pipe_cd[1], ".", 1);
-			assert(rc == 1);
 
 			/* wait for B to die and signal us... */
 			signum = 0xdeadbeef;

Copied and modified: stable/11/tests/sys/kern/pdeathsig_helper.c (from r332740, head/tests/sys/kern/pdeathsig_helper.c)
==============================================================================
--- head/tests/sys/kern/pdeathsig_helper.c	Wed Apr 18 21:31:13 2018	(r332740, copy source)
+++ stable/11/tests/sys/kern/pdeathsig_helper.c	Wed May  2 07:57:36 2018	(r333162)
@@ -38,11 +38,11 @@ int main(int argc, char **argv)
 
 	/*
 	 * This program is executed by the pdeathsig test
-	 * to check if the PROC_PDEATHSIG_SET setting was
+	 * to check if the PROC_PDEATHSIG_CTL setting was
 	 * inherited.
 	 */
         signum = 0xdeadbeef;
-        rc = procctl(P_PID, 0, PROC_PDEATHSIG_GET, &signum);
+        rc = procctl(P_PID, 0, PROC_PDEATHSIG_STATUS, &signum);
         assert(rc == 0);
         assert(signum == SIGINFO);
 



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