git: 1c4dbee5dd22 - main - procctl: make it possible to specify that some operations require debug privilege over the target

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Tue, 19 Oct 2021 20:04:52 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=1c4dbee5dd224c08241c0922ff577bb226171e81

commit 1c4dbee5dd224c08241c0922ff577bb226171e81
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-10-15 20:02:06 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-10-19 20:04:34 +0000

    procctl: make it possible to specify that some operations require debug privilege over the target
    
    Reviewed by:    emaste, markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D32513
---
 sys/kern/kern_procctl.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/sys/kern/kern_procctl.c b/sys/kern/kern_procctl.c
index 387706a0cb1e..6229d2140228 100644
--- a/sys/kern/kern_procctl.c
+++ b/sys/kern/kern_procctl.c
@@ -711,6 +711,7 @@ struct procctl_cmd_info {
 	bool esrch_is_einval : 1;
 	bool copyout_on_error : 1;
 	bool no_nonnull_data : 1;
+	bool need_candebug : 1;
 	int copyin_sz;
 	int copyout_sz;
 	int (*exec)(struct thread *, struct proc *, void *);
@@ -719,114 +720,136 @@ static const struct procctl_cmd_info procctl_cmds_info[] = {
 	[PROC_SPROTECT] =
 	    { .lock_tree = SA_SLOCKED, .one_proc = false,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = protect_set, .copyout_on_error = false, },
 	[PROC_REAP_ACQUIRE] =
 	    { .lock_tree = SA_XLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = true,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = 0,
 	      .exec = reap_acquire, .copyout_on_error = false, },
 	[PROC_REAP_RELEASE] =
 	    { .lock_tree = SA_XLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = true,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = 0,
 	      .exec = reap_release, .copyout_on_error = false, },
 	[PROC_REAP_STATUS] =
 	    { .lock_tree = SA_SLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0,
 	      .copyout_sz = sizeof(struct procctl_reaper_status),
 	      .exec = reap_status, .copyout_on_error = false, },
 	[PROC_REAP_GETPIDS] =
 	    { .lock_tree = SA_SLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(struct procctl_reaper_pids),
 	      .copyout_sz = 0,
 	      .exec = reap_getpids, .copyout_on_error = false, },
 	[PROC_REAP_KILL] =
 	    { .lock_tree = SA_SLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(struct procctl_reaper_kill),
 	      .copyout_sz = sizeof(struct procctl_reaper_kill),
 	      .exec = reap_kill, .copyout_on_error = true, },
 	[PROC_TRACE_CTL] =
 	    { .lock_tree = SA_SLOCKED, .one_proc = false,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = trace_ctl, .copyout_on_error = false, },
 	[PROC_TRACE_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = trace_status, .copyout_on_error = false, },
 	[PROC_TRAPCAP_CTL] =
 	    { .lock_tree = SA_SLOCKED, .one_proc = false,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = trapcap_ctl, .copyout_on_error = false, },
 	[PROC_TRAPCAP_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = trapcap_status, .copyout_on_error = false, },
 	[PROC_PDEATHSIG_CTL] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = true, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = pdeathsig_ctl, .copyout_on_error = false, },
 	[PROC_PDEATHSIG_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = true, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = pdeathsig_status, .copyout_on_error = false, },
 	[PROC_ASLR_CTL] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = aslr_ctl, .copyout_on_error = false, },
 	[PROC_ASLR_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = aslr_status, .copyout_on_error = false, },
 	[PROC_PROTMAX_CTL] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = protmax_ctl, .copyout_on_error = false, },
 	[PROC_PROTMAX_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = protmax_status, .copyout_on_error = false, },
 	[PROC_STACKGAP_CTL] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = stackgap_ctl, .copyout_on_error = false, },
 	[PROC_STACKGAP_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = stackgap_status, .copyout_on_error = false, },
 	[PROC_NO_NEW_PRIVS_CTL] =
 	    { .lock_tree = SA_SLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = no_new_privs_ctl, .copyout_on_error = false, },
 	[PROC_NO_NEW_PRIVS_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = no_new_privs_status, .copyout_on_error = false, },
 	[PROC_WXMAP_CTL] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = sizeof(int), .copyout_sz = 0,
 	      .exec = wxmap_ctl, .copyout_on_error = false, },
 	[PROC_WXMAP_STATUS] =
 	    { .lock_tree = SA_UNLOCKED, .one_proc = true,
 	      .esrch_is_einval = false, .no_nonnull_data = false,
+	      .need_candebug = false,
 	      .copyin_sz = 0, .copyout_sz = sizeof(int),
 	      .exec = wxmap_status, .copyout_on_error = false, },
 };
@@ -913,7 +936,8 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
 				    EINVAL : ESRCH;
 				break;
 			}
-			error = p_cansee(td, p);
+			error = cmd_info->need_candebug ? p_candebug(td, p) :
+			    p_cansee(td, p);
 		}
 		if (error == 0)
 			error = kern_procctl_single(td, p, com, data);
@@ -936,7 +960,8 @@ kern_procctl(struct thread *td, idtype_t idtype, id_t id, int com, void *data)
 		first_error = 0;
 		LIST_FOREACH(p, &pg->pg_members, p_pglist) {
 			PROC_LOCK(p);
-			if (p->p_state == PRS_NEW || p_cansee(td, p) != 0) {
+			if (p->p_state == PRS_NEW || (cmd_info->need_candebug ?
+			    p_candebug(td, p) : p_cansee(td, p)) != 0) {
 				PROC_UNLOCK(p);
 				continue;
 			}