mirror of
https://git.freebsd.org/src.git
synced 2026-01-11 19:57:22 +00:00
Add per-process flag to disable logsigexit
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
This commit is contained in:
parent
86b4df97d0
commit
dabf006a63
9 changed files with 137 additions and 6 deletions
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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:
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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 *);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ enum mode {
|
|||
MODE_LA57,
|
||||
MODE_LA48,
|
||||
#endif
|
||||
MODE_LOGSIGEXIT,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
|
|
@ -71,6 +72,7 @@ static const struct {
|
|||
{ MODE_LA57, "la57" },
|
||||
{ MODE_LA48, "la48" },
|
||||
#endif
|
||||
{ MODE_LOGSIGEXIT, "logsigexit" },
|
||||
};
|
||||
|
||||
static pid_t
|
||||
|
|
@ -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;
|
||||
|
|
@ -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) {
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue