Skip to content

Commit

Permalink
Add per-process flag to disable logsigexit
Browse files Browse the repository at this point in the history
I added a third value for kern.logsigexit to mean 'auto' as an abundance
of caution, but I don't know how much it matters -- that can be easily
consolidated back to boolean-ish.

This is primarily targeted towards people running test suites under CI
(e.g. buildbot, jenkins). Oftentimes tests entail segfaults that are
expected, and logs get spammed -- this can be particularly high volume
depending on the application. Per-process control of this behavior is
desirable because they may still want to be logging legitimate
segfaults, so the system-wide atomic bomb kern.logsigexit=0 is not a
great option.

This adds a process flag to disable it, controllable via
procctl(2)/proccontrol(1); the latter knows it as "sigexitlog" due to
its length, but it's referred to almost everywhere else as
"sigexit_log."

Reviewed by:	kib (earlier version), pstef
Differential Revision:	https://reviews.freebsd.org/D21903
  • Loading branch information
kevans91 committed Dec 14, 2024
1 parent 86b4df9 commit dabf006
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 6 deletions.
37 changes: 35 additions & 2 deletions lib/libsys/procctl.2
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd December 4, 2024
.Dd December 14, 2024
.Dt PROCCTL 2
.Os
.Sh NAME
Expand Down Expand Up @@ -79,7 +79,7 @@ All status query requests
require the caller to have the right to observe the target.
.Pp
The following commands are supported:
.Bl -tag -width PROC_TRAPCAP_STATUS
.Bl -tag -width PROC_LOGSIGEXIT_STATUS
.It Dv PROC_ASLR_CTL
Controls Address Space Layout Randomization (ASLR) in program
images created
Expand Down Expand Up @@ -127,6 +127,39 @@ If the currently executed image in the process itself has ASLR enabled,
the
.Dv PROC_ASLR_ACTIVE
flag is or-ed with the value listed above.
.It Dv PROC_LOGSIGEXIT_CTL
Controls the logging of exits due to signals that would normally cause a core
dump.
The
.Va arg
parameter must point to an integer variable holding one of the following values:
.Bl -tag -width PROC_LOGSIGEXIT_FORCE_DISABLE
.It Dv PROC_LOGSIGEXIT_FORCE_ENABLE
Enables logging of exits due to signals that would normally cause a core dump.
Logging is done via
.Xr log 9
with a log level of
.Dv LOG_INFO .
.It Dv PROC_LOGSIGEXIT_FORCE_DISABLE
Disables the logging of exits due to signals that would normally cause a core
dump.
.It Dv PROC_LOGSIGEXIT_NOFORCE
The logging behavior is delegated to the
.Xr sysctl 3
MIB variable
.Va kern.logsigexit .
.El
.It Dv PROC_LOGSIGEXIT_STATUS
Returns the current status of logging for the target process.
The
.Va arg
parameter must point to an integer variable, where one of the following values
is written:
.Bl -tag -width PROC_LOGSIGEXIT_FORCE_DISABLE
.It Dv PROC_LOGSIGEXIT_FORCE_ENABLE
.It Dv PROC_LOGSIGEXIT_FORCE_DISABLE
.It Dv PROC_LOGSIGEXIT_NOFORCE
.El
.It Dv PROC_PROTMAX_CTL
Controls the maximum protection used for
.Xr mmap 2
Expand Down
3 changes: 3 additions & 0 deletions sys/compat/freebsd32/freebsd32_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3860,6 +3860,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
case PROC_TRAPCAP_CTL:
case PROC_NO_NEW_PRIVS_CTL:
case PROC_WXMAP_CTL:
case PROC_LOGSIGEXIT_CTL:
error = copyin(PTRIN(uap->data), &flags, sizeof(flags));
if (error != 0)
return (error);
Expand Down Expand Up @@ -3895,6 +3896,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
case PROC_TRAPCAP_STATUS:
case PROC_NO_NEW_PRIVS_STATUS:
case PROC_WXMAP_STATUS:
case PROC_LOGSIGEXIT_STATUS:
data = &flags;
break;
case PROC_PDEATHSIG_CTL:
Expand Down Expand Up @@ -3928,6 +3930,7 @@ freebsd32_procctl(struct thread *td, struct freebsd32_procctl_args *uap)
case PROC_TRAPCAP_STATUS:
case PROC_NO_NEW_PRIVS_STATUS:
case PROC_WXMAP_STATUS:
case PROC_LOGSIGEXIT_STATUS:
if (error == 0)
error = copyout(&flags, uap->data, sizeof(flags));
break;
Expand Down
3 changes: 2 additions & 1 deletion sys/kern/kern_fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,8 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
P2_ASLR_IGNSTART | P2_NOTRACE | P2_NOTRACE_EXEC |
P2_PROTMAX_ENABLE | P2_PROTMAX_DISABLE | P2_TRAPCAP |
P2_STKGAP_DISABLE | P2_STKGAP_DISABLE_EXEC | P2_NO_NEW_PRIVS |
P2_WXORX_DISABLE | P2_WXORX_ENABLE_EXEC);
P2_WXORX_DISABLE | P2_WXORX_ENABLE_EXEC | P2_LOGSIGEXIT_CTL |
P2_LOGSIGEXIT_ENABLE);
p2->p_swtick = ticks;
if (p1->p_flag & P_PROFIL)
startprofclock(p2);
Expand Down
52 changes: 52 additions & 0 deletions sys/kern/kern_procctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,46 @@ pdeathsig_status(struct thread *td, struct proc *p, void *data)
return (0);
}

static int
logsigexit_ctl(struct thread *td, struct proc *p, void *data)
{
int state;

PROC_LOCK_ASSERT(p, MA_OWNED);
state = *(int *)data;

switch (state) {
case PROC_LOGSIGEXIT_CTL_NOFORCE:
p->p_flag2 &= ~(P2_LOGSIGEXIT_CTL | P2_LOGSIGEXIT_ENABLE);
break;
case PROC_LOGSIGEXIT_CTL_FORCE_ENABLE:
p->p_flag2 |= P2_LOGSIGEXIT_CTL | P2_LOGSIGEXIT_ENABLE;
break;
case PROC_LOGSIGEXIT_CTL_FORCE_DISABLE:
p->p_flag2 |= P2_LOGSIGEXIT_CTL;
p->p_flag2 &= ~P2_LOGSIGEXIT_ENABLE;
break;
default:
return (EINVAL);
}
return (0);
}

static int
logsigexit_status(struct thread *td, struct proc *p, void *data)
{
int state;

if ((p->p_flag2 & P2_LOGSIGEXIT_CTL) == 0)
state = PROC_LOGSIGEXIT_CTL_NOFORCE;
else if ((p->p_flag2 & P2_LOGSIGEXIT_ENABLE) != 0)
state = PROC_LOGSIGEXIT_CTL_FORCE_ENABLE;
else
state = PROC_LOGSIGEXIT_CTL_FORCE_DISABLE;
*(int *)data = state;
return (0);
}

enum {
PCTL_SLOCKED,
PCTL_XLOCKED,
Expand Down Expand Up @@ -1100,6 +1140,18 @@ static const struct procctl_cmd_info procctl_cmds_info[] = {
.need_candebug = false,
.copyin_sz = 0, .copyout_sz = sizeof(int),
.exec = wxmap_status, .copyout_on_error = false, },
[PROC_LOGSIGEXIT_CTL] =
{ .lock_tree = PCTL_SLOCKED, .one_proc = true,
.esrch_is_einval = false, .no_nonnull_data = false,
.need_candebug = true,
.copyin_sz = sizeof(int), .copyout_sz = 0,
.exec = logsigexit_ctl, .copyout_on_error = false, },
[PROC_LOGSIGEXIT_STATUS] =
{ .lock_tree = PCTL_UNLOCKED, .one_proc = true,
.esrch_is_einval = false, .no_nonnull_data = false,
.need_candebug = false,
.copyin_sz = 0, .copyout_sz = sizeof(int),
.exec = logsigexit_status, .copyout_on_error = false, },
};

int
Expand Down
8 changes: 7 additions & 1 deletion sys/kern/kern_sig.c
Original file line number Diff line number Diff line change
Expand Up @@ -3606,11 +3606,17 @@ sigexit(struct thread *td, int sig)
struct proc *p = td->td_proc;
const char *coreinfo;
int rv;
bool logexit;

PROC_LOCK_ASSERT(p, MA_OWNED);
proc_set_p2_wexit(p);

p->p_acflag |= AXSIG;
if ((p->p_flag2 & P2_LOGSIGEXIT_CTL) == 0)
logexit = kern_logsigexit != 0;
else
logexit = (p->p_flag2 & P2_LOGSIGEXIT_ENABLE) != 0;

/*
* We must be single-threading to generate a core dump. This
* ensures that the registers in the core file are up-to-date.
Expand Down Expand Up @@ -3649,7 +3655,7 @@ sigexit(struct thread *td, int sig)
coreinfo = " (no core dump - other error)";
break;
}
if (kern_logsigexit)
if (logexit)
log(LOG_INFO,
"pid %d (%s), jid %d, uid %d: exited on "
"signal %d%s\n", p->p_pid, p->p_comm,
Expand Down
3 changes: 3 additions & 0 deletions sys/sys/proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -886,6 +886,9 @@ struct proc {
#define P2_MEMBAR_GLOBE 0x00400000 /* membar global expedited
registered */

#define P2_LOGSIGEXIT_ENABLE 0x00800000 /* Disable logging on sigexit */
#define P2_LOGSIGEXIT_CTL 0x01000000 /* Override kern.logsigexit */

/* Flags protected by proctree_lock, kept in p_treeflags. */
#define P_TREE_ORPHANED 0x00000001 /* Reparented, on orphan list */
#define P_TREE_FIRST_ORPHAN 0x00000002 /* First element of orphan
Expand Down
6 changes: 6 additions & 0 deletions sys/sys/procctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@
#define PROC_NO_NEW_PRIVS_STATUS 20 /* query suid/sgid disabled status */
#define PROC_WXMAP_CTL 21 /* control W^X */
#define PROC_WXMAP_STATUS 22 /* query W^X */
#define PROC_LOGSIGEXIT_CTL 23 /* en/dis logging on sigexit */
#define PROC_LOGSIGEXIT_STATUS 24 /* query logging on sigexit */

/* Operations for PROC_SPROTECT (passed in integer arg). */
#define PPROT_OP(x) ((x) & 0xf)
Expand Down Expand Up @@ -153,6 +155,10 @@ struct procctl_reaper_kill {
#define PROC_WX_MAPPINGS_DISALLOW_EXEC 0x0002
#define PROC_WXORX_ENFORCE 0x80000000

#define PROC_LOGSIGEXIT_CTL_NOFORCE 1
#define PROC_LOGSIGEXIT_CTL_FORCE_ENABLE 2
#define PROC_LOGSIGEXIT_CTL_FORCE_DISABLE 3

#ifndef _KERNEL
__BEGIN_DECLS
int procctl(idtype_t, id_t, int, void *);
Expand Down
7 changes: 5 additions & 2 deletions usr.bin/proccontrol/proccontrol.1
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd August 23, 2024
.Dd December 14, 2024
.Dt PROCCONTROL 1
.Os
.Sh NAME
Expand Down Expand Up @@ -56,7 +56,7 @@ parameter
Possible values for
.Ar mode
are:
.Bl -tag -width trapcap
.Bl -tag -width logsigexit
.It Ar aslr
Control the Address Space Layout Randomization.
Only applicable to the new process spawned.
Expand All @@ -79,6 +79,9 @@ Controls the KPTI enable, AMD64 only.
.It Ar la48
Control limiting usermode process address space to 48 bits of address,
AMD64 only, on machines capable of 57-bit addressing.
.It Ar logsigexit
Controls the logging of exits due to a signal that would normally cause a core
dump.
.El
.Pp
The
Expand Down
24 changes: 24 additions & 0 deletions usr.bin/proccontrol/proccontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ enum mode {
MODE_LA57,
MODE_LA48,
#endif
MODE_LOGSIGEXIT,
};

static const struct {
Expand All @@ -71,6 +72,7 @@ static const struct {
{ MODE_LA57, "la57" },
{ MODE_LA48, "la48" },
#endif
{ MODE_LOGSIGEXIT, "logsigexit" },
};

static pid_t
Expand Down Expand Up @@ -194,6 +196,10 @@ main(int argc, char *argv[])
error = procctl(P_PID, pid, PROC_LA_STATUS, &arg);
break;
#endif
case MODE_LOGSIGEXIT:
error = procctl(P_PID, pid, PROC_LOGSIGEXIT_STATUS,
&arg);
break;
default:
usage();
break;
Expand Down Expand Up @@ -331,6 +337,19 @@ main(int argc, char *argv[])
printf(", la57 active\n");
break;
#endif
case MODE_LOGSIGEXIT:
switch (arg) {
case PROC_LOGSIGEXIT_CTL_NOFORCE:
printf("not forced\n");
break;
case PROC_LOGSIGEXIT_CTL_FORCE_ENABLE:
printf("force enabled\n");
break;
case PROC_LOGSIGEXIT_CTL_FORCE_DISABLE:
printf("force disabled\n");
break;
}
break;
}
} else {
switch (mode) {
Expand Down Expand Up @@ -390,6 +409,11 @@ main(int argc, char *argv[])
error = procctl(P_PID, pid, PROC_LA_CTL, &arg);
break;
#endif
case MODE_LOGSIGEXIT:
arg = enable ? PROC_LOGSIGEXIT_CTL_FORCE_ENABLE :
PROC_LOGSIGEXIT_CTL_FORCE_DISABLE;
error = procctl(P_PID, pid, PROC_LOGSIGEXIT_CTL, &arg);
break;
default:
usage();
break;
Expand Down

0 comments on commit dabf006

Please sign in to comment.