Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148174972
D30257.id89433.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
26 KB
Referenced Files
None
Subscribers
None
D30257.id89433.diff
View Options
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -141,7 +141,6 @@
static int acct_suspended;
static struct vnode *acct_vp;
static struct ucred *acct_cred;
-static struct plimit *acct_limit;
static int acct_flags;
static struct sx acct_sx;
@@ -206,7 +205,7 @@
sys_acct(struct thread *td, struct acct_args *uap)
{
struct nameidata nd;
- int error, flags, i, replacing;
+ int error, flags, replacing;
error = priv_check(td, PRIV_ACCT);
if (error)
@@ -276,15 +275,6 @@
return (error);
}
- /*
- * Create our own plimit object without limits. It will be assigned
- * to exiting processes.
- */
- acct_limit = lim_alloc();
- for (i = 0; i < RLIM_NLIMITS; i++)
- acct_limit->pl_rlimit[i].rlim_cur =
- acct_limit->pl_rlimit[i].rlim_max = RLIM_INFINITY;
-
/*
* Save the new accounting file vnode, and schedule the new
* free space watcher.
@@ -328,7 +318,6 @@
sx_assert(&acct_sx, SX_XLOCKED);
error = vn_close(acct_vp, acct_flags, acct_cred, td);
crfree(acct_cred);
- lim_free(acct_limit);
acct_configured = 0;
acct_vp = NULL;
acct_cred = NULL;
@@ -349,7 +338,6 @@
{
struct acctv3 acct;
struct timeval ut, st, tmp;
- struct plimit *oldlim;
struct proc *p;
struct rusage ru;
int t, ret;
@@ -374,6 +362,7 @@
}
p = td->td_proc;
+ td->td_pflags2 |= TDP2_ACCT;
/*
* Get process accounting information.
@@ -426,20 +415,14 @@
/* (8) The boolean flags that tell how the process terminated, etc. */
acct.ac_flagx = p->p_acflag;
+ PROC_UNLOCK(p);
+
/* Setup ancillary structure fields. */
acct.ac_flagx |= ANVER;
acct.ac_zero = 0;
acct.ac_version = 3;
acct.ac_len = acct.ac_len2 = sizeof(acct);
- /*
- * Eliminate rlimits (file size limit in particular).
- */
- oldlim = p->p_limit;
- p->p_limit = lim_hold(acct_limit);
- PROC_UNLOCK(p);
- lim_free(oldlim);
-
/*
* Write the accounting information to the file.
*/
@@ -447,6 +430,7 @@
(off_t)0, UIO_SYSSPACE, IO_APPEND|IO_UNIT, acct_cred, NOCRED,
NULL, td);
sx_sunlock(&acct_sx);
+ td->td_pflags2 &= ~TDP2_ACCT;
return (ret);
}
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -79,9 +79,7 @@
#include <sys/unistd.h>
#include <sys/user.h>
#include <sys/vnode.h>
-#ifdef KTRACE
#include <sys/ktrace.h>
-#endif
#include <net/vnet.h>
@@ -4363,9 +4361,7 @@
PROC_LOCK_ASSERT(p, MA_OWNED);
/* ktrace vnode */
- tracevp = p->p_tracevp;
- if (tracevp != NULL)
- vrefact(tracevp);
+ tracevp = ktr_get_tracevp(p, true);
/* text vnode */
textvp = p->p_textvp;
if (textvp != NULL)
@@ -4405,17 +4401,20 @@
/* working directory */
if (pwd->pwd_cdir != NULL) {
vrefact(pwd->pwd_cdir);
- export_vnode_to_sb(pwd->pwd_cdir, KF_FD_TYPE_CWD, FREAD, efbuf);
+ export_vnode_to_sb(pwd->pwd_cdir, KF_FD_TYPE_CWD,
+ FREAD, efbuf);
}
/* root directory */
if (pwd->pwd_rdir != NULL) {
vrefact(pwd->pwd_rdir);
- export_vnode_to_sb(pwd->pwd_rdir, KF_FD_TYPE_ROOT, FREAD, efbuf);
+ export_vnode_to_sb(pwd->pwd_rdir, KF_FD_TYPE_ROOT,
+ FREAD, efbuf);
}
/* jail directory */
if (pwd->pwd_jdir != NULL) {
vrefact(pwd->pwd_jdir);
- export_vnode_to_sb(pwd->pwd_jdir, KF_FD_TYPE_JAIL, FREAD, efbuf);
+ export_vnode_to_sb(pwd->pwd_jdir, KF_FD_TYPE_JAIL,
+ FREAD, efbuf);
}
}
PWDDESC_XUNLOCK(pdp);
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -373,8 +373,7 @@
struct pargs *oldargs = NULL, *newargs = NULL;
struct sigacts *oldsigacts = NULL, *newsigacts = NULL;
#ifdef KTRACE
- struct vnode *tracevp = NULL;
- struct ucred *tracecred = NULL;
+ struct ktr_io_params *kiop;
#endif
struct vnode *oldtextvp = NULL, *newtextvp;
int credential_changing;
@@ -390,6 +389,7 @@
static const char fexecv_proc_title[] = "(fexecv)";
imgp = &image_params;
+ kiop = NULL;
/*
* Lock the process and set the P_INEXEC flag to indicate that
@@ -779,11 +779,10 @@
* we do not regain any tracing during a possible block.
*/
setsugid(p);
+ kiop = NULL;
#ifdef KTRACE
- if (p->p_tracecred != NULL &&
- priv_check_cred(p->p_tracecred, PRIV_DEBUG_DIFFCRED))
- ktrprocexec(p, &tracecred, &tracevp);
+ kiop = ktrprocexec(p);
#endif
/*
* Close any file descriptors 0..2 that reference procfs,
@@ -938,12 +937,7 @@
*/
if (oldtextvp != NULL)
vrele(oldtextvp);
-#ifdef KTRACE
- if (tracevp != NULL)
- vrele(tracevp);
- if (tracecred != NULL)
- crfree(tracecred);
-#endif
+ ktr_io_params_free(kiop);
pargs_drop(oldargs);
pargs_drop(newargs);
if (oldsigacts != NULL)
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -504,8 +504,9 @@
}
} else {
/*
- * Traced processes are killed since their existence
- * means someone is screwing up.
+ * Traced processes are killed by default
+ * since their existence means someone is
+ * screwing up.
*/
t = proc_realparent(q);
if (t == p) {
@@ -522,14 +523,18 @@
* orphan link for q now while q is locked.
*/
proc_clear_orphan(q);
- q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
q->p_flag2 &= ~P2_PTRACE_FSTP;
q->p_ptevents = 0;
FOREACH_THREAD_IN_PROC(q, tdt) {
tdt->td_dbgflags &= ~(TDB_SUSPEND | TDB_XSIG |
TDB_FSTP);
}
- kern_psignal(q, SIGKILL);
+ if (kern_kill_on_dbg_exit) {
+ q->p_flag &= ~(P_TRACED | P_STOPPED_TRACE);
+ kern_psignal(q, SIGKILL);
+ } else {
+ ptrace_unsuspend(q);
+ }
}
PROC_UNLOCK(q);
if (ksi != NULL)
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -51,6 +51,7 @@
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
+#include <sys/resourcevar.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/socket.h>
@@ -141,24 +142,42 @@
SYSCTL_UINT(_kern_ktrace, OID_AUTO, genio_size, CTLFLAG_RWTUN, &ktr_geniosize,
0, "Maximum size of genio event payload");
+/*
+ * Allow to not to send signal to traced process, in which context the
+ * ktr record is written. The limit is applied from the process that
+ * set up ktrace, so killing the traced process is not completely fair.
+ */
+int ktr_filesize_limit_signal = 0;
+SYSCTL_INT(_kern_ktrace, OID_AUTO, filesize_limit_signal, CTLFLAG_RWTUN,
+ &ktr_filesize_limit_signal, 0,
+ "Send SIGXFSZ to traced process on ktrace.out limit exceeding");
+
static int print_message = 1;
static struct mtx ktrace_mtx;
static struct sx ktrace_sx;
+struct ktr_io_params {
+ struct vnode *vp;
+ struct ucred *cr;
+ off_t lim;
+ u_int refs;
+};
+
static void ktrace_init(void *dummy);
static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS);
static u_int ktrace_resize_pool(u_int oldsize, u_int newsize);
static struct ktr_request *ktr_getrequest_entered(struct thread *td, int type);
static struct ktr_request *ktr_getrequest(int type);
static void ktr_submitrequest(struct thread *td, struct ktr_request *req);
-static void ktr_freeproc(struct proc *p, struct ucred **uc,
- struct vnode **vp);
+static struct ktr_io_params *ktr_freeproc(struct proc *p);
static void ktr_freerequest(struct ktr_request *req);
static void ktr_freerequest_locked(struct ktr_request *req);
static void ktr_writerequest(struct thread *td, struct ktr_request *req);
static int ktrcanset(struct thread *,struct proc *);
-static int ktrsetchildren(struct thread *,struct proc *,int,int,struct vnode *);
-static int ktrops(struct thread *,struct proc *,int,int,struct vnode *);
+static int ktrsetchildren(struct thread *, struct proc *, int, int,
+ struct ktr_io_params *);
+static int ktrops(struct thread *, struct proc *, int, int,
+ struct ktr_io_params *);
static void ktrprocctor_entered(struct thread *, struct proc *);
/*
@@ -421,28 +440,87 @@
STAILQ_INSERT_HEAD(&ktr_free, req, ktr_list);
}
+static void
+ktr_io_params_ref(struct ktr_io_params *kiop)
+{
+ mtx_assert(&ktrace_mtx, MA_OWNED);
+ kiop->refs++;
+}
+
+static struct ktr_io_params *
+ktr_io_params_rele(struct ktr_io_params *kiop)
+{
+ mtx_assert(&ktrace_mtx, MA_OWNED);
+ if (kiop == NULL)
+ return (NULL);
+ KASSERT(kiop->refs > 0, ("kiop ref == 0 %p", kiop));
+ return (--(kiop->refs) == 0 ? kiop : NULL);
+}
+
+void
+ktr_io_params_free(struct ktr_io_params *kiop)
+{
+ if (kiop == NULL)
+ return;
+
+ MPASS(kiop->refs == 0);
+ vrele(kiop->vp);
+ crfree(kiop->cr);
+ free(kiop, M_KTRACE);
+}
+
+static struct ktr_io_params *
+ktr_io_params_alloc(struct thread *td, struct vnode *vp)
+{
+ struct ktr_io_params *res;
+
+ res = malloc(sizeof(struct ktr_io_params), M_KTRACE, M_WAITOK);
+ res->vp = vp;
+ vref(vp);
+ res->cr = crhold(td->td_ucred);
+ res->lim = lim_cur(td, RLIMIT_FSIZE);
+ res->refs = 0;
+ return (res);
+}
+
/*
* Disable tracing for a process and release all associated resources.
* The caller is responsible for releasing a reference on the returned
* vnode and credentials.
*/
-static void
-ktr_freeproc(struct proc *p, struct ucred **uc, struct vnode **vp)
+static struct ktr_io_params *
+ktr_freeproc(struct proc *p)
{
+ struct ktr_io_params *kiop;
struct ktr_request *req;
PROC_LOCK_ASSERT(p, MA_OWNED);
mtx_assert(&ktrace_mtx, MA_OWNED);
- *uc = p->p_tracecred;
- p->p_tracecred = NULL;
- if (vp != NULL)
- *vp = p->p_tracevp;
- p->p_tracevp = NULL;
+ kiop = ktr_io_params_rele(p->p_ktrioparms);
+ p->p_ktrioparms = NULL;
p->p_traceflag = 0;
while ((req = STAILQ_FIRST(&p->p_ktr)) != NULL) {
STAILQ_REMOVE_HEAD(&p->p_ktr, ktr_list);
ktr_freerequest_locked(req);
}
+ return (kiop);
+}
+
+struct vnode *
+ktr_get_tracevp(struct proc *p, bool ref)
+{
+ struct vnode *vp;
+
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ if (p->p_ktrioparms != NULL) {
+ vp = p->p_ktrioparms->vp;
+ if (ref)
+ vrefact(vp);
+ } else {
+ vp = NULL;
+ }
+ return (vp);
}
void
@@ -501,14 +579,21 @@
*
* XXX: We toss any pending asynchronous records.
*/
-void
-ktrprocexec(struct proc *p, struct ucred **uc, struct vnode **vp)
+struct ktr_io_params *
+ktrprocexec(struct proc *p)
{
+ struct ktr_io_params *kiop;
PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ kiop = p->p_ktrioparms;
+ if (kiop == NULL || priv_check_cred(kiop->cr, PRIV_DEBUG_DIFFCRED))
+ return (NULL);
+
mtx_lock(&ktrace_mtx);
- ktr_freeproc(p, uc, vp);
+ kiop = ktr_freeproc(p);
mtx_unlock(&ktrace_mtx);
+ return (kiop);
}
/*
@@ -520,8 +605,7 @@
{
struct ktr_request *req;
struct proc *p;
- struct ucred *cred;
- struct vnode *vp;
+ struct ktr_io_params *kiop;
p = td->td_proc;
if (p->p_traceflag == 0)
@@ -536,13 +620,10 @@
sx_xunlock(&ktrace_sx);
PROC_LOCK(p);
mtx_lock(&ktrace_mtx);
- ktr_freeproc(p, &cred, &vp);
+ kiop = ktr_freeproc(p);
mtx_unlock(&ktrace_mtx);
PROC_UNLOCK(p);
- if (vp != NULL)
- vrele(vp);
- if (cred != NULL)
- crfree(cred);
+ ktr_io_params_free(kiop);
ktrace_exit(td);
}
@@ -583,7 +664,7 @@
ktrprocfork(struct proc *p1, struct proc *p2)
{
- MPASS(p2->p_tracevp == NULL);
+ MPASS(p2->p_ktrioparms == NULL);
MPASS(p2->p_traceflag == 0);
if (p1->p_traceflag == 0)
@@ -593,12 +674,8 @@
mtx_lock(&ktrace_mtx);
if (p1->p_traceflag & KTRFAC_INHERIT) {
p2->p_traceflag = p1->p_traceflag;
- if ((p2->p_tracevp = p1->p_tracevp) != NULL) {
- VREF(p2->p_tracevp);
- KASSERT(p1->p_tracecred != NULL,
- ("ktrace vnode with no cred"));
- p2->p_tracecred = crhold(p1->p_tracecred);
- }
+ if ((p2->p_ktrioparms = p1->p_ktrioparms) != NULL)
+ p1->p_ktrioparms->refs++;
}
mtx_unlock(&ktrace_mtx);
PROC_UNLOCK(p1);
@@ -932,7 +1009,7 @@
int nfound, ret = 0;
int flags, error = 0;
struct nameidata nd;
- struct ucred *cred;
+ struct ktr_io_params *kiop, *old_kiop;
/*
* Need something to (un)trace.
@@ -940,6 +1017,7 @@
if (ops != KTROP_CLEARFILE && facs == 0)
return (EINVAL);
+ kiop = NULL;
ktrace_enter(td);
if (ops != KTROP_CLEAR) {
/*
@@ -960,34 +1038,35 @@
ktrace_exit(td);
return (EACCES);
}
+ kiop = ktr_io_params_alloc(td, vp);
+ kiop->refs++;
}
/*
* Clear all uses of the tracefile.
*/
if (ops == KTROP_CLEARFILE) {
- int vrele_count;
-
- vrele_count = 0;
+restart:
sx_slock(&allproc_lock);
FOREACH_PROC_IN_SYSTEM(p) {
+ old_kiop = NULL;
PROC_LOCK(p);
- if (p->p_tracevp == vp) {
+ if (p->p_ktrioparms != NULL &&
+ p->p_ktrioparms->vp == vp) {
if (ktrcanset(td, p)) {
mtx_lock(&ktrace_mtx);
- ktr_freeproc(p, &cred, NULL);
+ old_kiop = ktr_freeproc(p);
mtx_unlock(&ktrace_mtx);
- vrele_count++;
- crfree(cred);
} else
error = EPERM;
}
PROC_UNLOCK(p);
+ if (old_kiop != NULL) {
+ sx_sunlock(&allproc_lock);
+ ktr_io_params_free(old_kiop);
+ goto restart;
+ }
}
sx_sunlock(&allproc_lock);
- if (vrele_count > 0) {
- while (vrele_count-- > 0)
- vrele(vp);
- }
goto done;
}
/*
@@ -1019,9 +1098,9 @@
}
nfound++;
if (descend)
- ret |= ktrsetchildren(td, p, ops, facs, vp);
+ ret |= ktrsetchildren(td, p, ops, facs, kiop);
else
- ret |= ktrops(td, p, ops, facs, vp);
+ ret |= ktrops(td, p, ops, facs, kiop);
}
if (nfound == 0) {
sx_sunlock(&proctree_lock);
@@ -1044,16 +1123,20 @@
goto done;
}
if (descend)
- ret |= ktrsetchildren(td, p, ops, facs, vp);
+ ret |= ktrsetchildren(td, p, ops, facs, kiop);
else
- ret |= ktrops(td, p, ops, facs, vp);
+ ret |= ktrops(td, p, ops, facs, kiop);
}
sx_sunlock(&proctree_lock);
if (!ret)
error = EPERM;
done:
- if (vp != NULL)
- (void) vn_close(vp, FWRITE, td->td_ucred, td);
+ if (kiop != NULL) {
+ mtx_lock(&ktrace_mtx);
+ kiop = ktr_io_params_rele(kiop);
+ mtx_unlock(&ktrace_mtx);
+ ktr_io_params_free(kiop);
+ }
ktrace_exit(td);
return (error);
#else /* !KTRACE */
@@ -1097,10 +1180,10 @@
#ifdef KTRACE
static int
-ktrops(struct thread *td, struct proc *p, int ops, int facs, struct vnode *vp)
+ktrops(struct thread *td, struct proc *p, int ops, int facs,
+ struct ktr_io_params *new_kiop)
{
- struct vnode *tracevp = NULL;
- struct ucred *tracecred = NULL;
+ struct ktr_io_params *old_kiop;
PROC_LOCK_ASSERT(p, MA_OWNED);
if (!ktrcanset(td, p)) {
@@ -1112,19 +1195,18 @@
PROC_UNLOCK(p);
return (1);
}
+ old_kiop = NULL;
mtx_lock(&ktrace_mtx);
if (ops == KTROP_SET) {
- if (p->p_tracevp != vp) {
- /*
- * if trace file already in use, relinquish below
- */
- tracevp = p->p_tracevp;
- VREF(vp);
- p->p_tracevp = vp;
+ if (p->p_ktrioparms != NULL &&
+ p->p_ktrioparms->vp != new_kiop->vp) {
+ /* if trace file already in use, relinquish below */
+ old_kiop = ktr_io_params_rele(p->p_ktrioparms);
+ p->p_ktrioparms = NULL;
}
- if (p->p_tracecred != td->td_ucred) {
- tracecred = p->p_tracecred;
- p->p_tracecred = crhold(td->td_ucred);
+ if (p->p_ktrioparms == NULL) {
+ p->p_ktrioparms = new_kiop;
+ ktr_io_params_ref(new_kiop);
}
p->p_traceflag |= facs;
if (priv_check(td, PRIV_KTRACE) == 0)
@@ -1133,23 +1215,20 @@
/* KTROP_CLEAR */
if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0)
/* no more tracing */
- ktr_freeproc(p, &tracecred, &tracevp);
+ old_kiop = ktr_freeproc(p);
}
mtx_unlock(&ktrace_mtx);
if ((p->p_traceflag & KTRFAC_MASK) != 0)
ktrprocctor_entered(td, p);
PROC_UNLOCK(p);
- if (tracevp != NULL)
- vrele(tracevp);
- if (tracecred != NULL)
- crfree(tracecred);
+ ktr_io_params_free(old_kiop);
return (1);
}
static int
ktrsetchildren(struct thread *td, struct proc *top, int ops, int facs,
- struct vnode *vp)
+ struct ktr_io_params *new_kiop)
{
struct proc *p;
int ret = 0;
@@ -1158,7 +1237,7 @@
PROC_LOCK_ASSERT(p, MA_OWNED);
sx_assert(&proctree_lock, SX_LOCKED);
for (;;) {
- ret |= ktrops(td, p, ops, facs, vp);
+ ret |= ktrops(td, p, ops, facs, new_kiop);
/*
* If this process has children, descend to them next,
* otherwise do any siblings, and if done with this level,
@@ -1183,6 +1262,7 @@
static void
ktr_writerequest(struct thread *td, struct ktr_request *req)
{
+ struct ktr_io_params *kiop;
struct ktr_header *kth;
struct vnode *vp;
struct proc *p;
@@ -1190,9 +1270,12 @@
struct uio auio;
struct iovec aiov[3];
struct mount *mp;
- int datalen, buflen, vrele_count;
+ off_t lim;
+ int datalen, buflen;
int error;
+ p = td->td_proc;
+
/*
* We hold the vnode and credential for use in I/O in case ktrace is
* disabled on the process as we write out the request.
@@ -1201,19 +1284,22 @@
* the vnode has been closed.
*/
mtx_lock(&ktrace_mtx);
- vp = td->td_proc->p_tracevp;
- cred = td->td_proc->p_tracecred;
+
+ kiop = p->p_ktrioparms;
/*
- * If vp is NULL, the vp has been cleared out from under this
- * request, so just drop it. Make sure the credential and vnode are
- * in sync: we should have both or neither.
+ * If kiop is NULL, it has been cleared out from under this
+ * request, so just drop it.
*/
- if (vp == NULL) {
- KASSERT(cred == NULL, ("ktr_writerequest: cred != NULL"));
+ if (kiop == NULL) {
mtx_unlock(&ktrace_mtx);
return;
}
+
+ vp = kiop->vp;
+ cred = kiop->cr;
+ lim = kiop->lim;
+
VREF(vp);
KASSERT(cred != NULL, ("ktr_writerequest: cred == NULL"));
crhold(cred);
@@ -1250,58 +1336,40 @@
vn_start_write(vp, &mp, V_WAIT);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ MPASS((td->td_pflags2 & TDP2_KTRWRITE) == 0);
+ td->td_pflags2 |= TDP2_KTRWRITE;
+ td->td_ktr_io_lim = lim;
#ifdef MAC
error = mac_vnode_check_write(cred, NOCRED, vp);
if (error == 0)
#endif
error = VOP_WRITE(vp, &auio, IO_UNIT | IO_APPEND, cred);
+ td->td_pflags2 &= ~TDP2_KTRWRITE;
VOP_UNLOCK(vp);
vn_finished_write(mp);
crfree(cred);
- if (!error) {
+ if (error == 0) {
vrele(vp);
return;
}
/*
- * If error encountered, give up tracing on this vnode. We defer
- * all the vrele()'s on the vnode until after we are finished walking
- * the various lists to avoid needlessly holding locks.
- * NB: at this point we still hold the vnode reference that must
- * not go away as we need the valid vnode to compare with. Thus let
- * vrele_count start at 1 and the reference will be freed
- * by the loop at the end after our last use of vp.
+ * If error encountered, give up tracing on this vnode on this
+ * process. Other processes might still be suitable for
+ * writes to this vnode.
*/
- log(LOG_NOTICE, "ktrace write failed, errno %d, tracing stopped\n",
- error);
- vrele_count = 1;
- /*
- * First, clear this vnode from being used by any processes in the
- * system.
- * XXX - If one process gets an EPERM writing to the vnode, should
- * we really do this? Other processes might have suitable
- * credentials for the operation.
- */
- cred = NULL;
- sx_slock(&allproc_lock);
- FOREACH_PROC_IN_SYSTEM(p) {
- PROC_LOCK(p);
- if (p->p_tracevp == vp) {
- mtx_lock(&ktrace_mtx);
- ktr_freeproc(p, &cred, NULL);
- mtx_unlock(&ktrace_mtx);
- vrele_count++;
- }
- PROC_UNLOCK(p);
- if (cred != NULL) {
- crfree(cred);
- cred = NULL;
- }
- }
- sx_sunlock(&allproc_lock);
+ log(LOG_NOTICE,
+ "ktrace write failed, errno %d, tracing stopped for pid %d\n",
+ error, p->p_pid);
- while (vrele_count-- > 0)
- vrele(vp);
+ PROC_LOCK(p);
+ mtx_lock(&ktrace_mtx);
+ if (p->p_ktrioparms != NULL && p->p_ktrioparms->vp == vp)
+ kiop = ktr_freeproc(p);
+ mtx_unlock(&ktrace_mtx);
+ PROC_UNLOCK(p);
+ ktr_io_params_free(kiop);
+ vrele(vp);
}
/*
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -75,6 +75,9 @@
#include <sys/user.h>
#include <sys/vnode.h>
#include <sys/wait.h>
+#ifdef KTRACE
+#include <sys/ktrace.h>
+#endif
#ifdef DDB
#include <ddb/ddb.h>
@@ -1058,7 +1061,7 @@
kp->ki_args = p->p_args;
kp->ki_textvp = p->p_textvp;
#ifdef KTRACE
- kp->ki_tracep = p->p_tracevp;
+ kp->ki_tracep = ktr_get_tracevp(p, false);
kp->ki_traceflag = p->p_traceflag;
#endif
kp->ki_fd = p->p_fd;
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -163,6 +163,11 @@
"Fetch sigfastblock word on each syscall entry for proper "
"blocking semantic");
+int kern_kill_on_dbg_exit = 1;
+SYSCTL_INT(_kern, OID_AUTO, kill_on_debugger_exit, CTLFLAG_RWTUN,
+ &kern_kill_on_dbg_exit, 0,
+ "Kill ptraced processes when debugger exits");
+
SYSINIT(signal, SI_SUB_P1003_1B, SI_ORDER_FIRST+3, sigqueue_start, NULL);
/*
diff --git a/sys/kern/kern_thread.c b/sys/kern/kern_thread.c
--- a/sys/kern/kern_thread.c
+++ b/sys/kern/kern_thread.c
@@ -96,11 +96,11 @@
"struct proc KBI p_flag");
_Static_assert(offsetof(struct proc, p_pid) == 0xc4,
"struct proc KBI p_pid");
-_Static_assert(offsetof(struct proc, p_filemon) == 0x3c0,
+_Static_assert(offsetof(struct proc, p_filemon) == 0x3b8,
"struct proc KBI p_filemon");
-_Static_assert(offsetof(struct proc, p_comm) == 0x3d8,
+_Static_assert(offsetof(struct proc, p_comm) == 0x3d0,
"struct proc KBI p_comm");
-_Static_assert(offsetof(struct proc, p_emuldata) == 0x4b8,
+_Static_assert(offsetof(struct proc, p_emuldata) == 0x4b0,
"struct proc KBI p_emuldata");
#endif
#ifdef __i386__
@@ -116,11 +116,11 @@
"struct proc KBI p_flag");
_Static_assert(offsetof(struct proc, p_pid) == 0x78,
"struct proc KBI p_pid");
-_Static_assert(offsetof(struct proc, p_filemon) == 0x26c,
+_Static_assert(offsetof(struct proc, p_filemon) == 0x268,
"struct proc KBI p_filemon");
-_Static_assert(offsetof(struct proc, p_comm) == 0x280,
+_Static_assert(offsetof(struct proc, p_comm) == 0x27c,
"struct proc KBI p_comm");
-_Static_assert(offsetof(struct proc, p_emuldata) == 0x30c,
+_Static_assert(offsetof(struct proc, p_emuldata) == 0x308,
"struct proc KBI p_emuldata");
#endif
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -610,6 +610,19 @@
p->p_ptevents = PTRACE_DEFAULT;
}
+void
+ptrace_unsuspend(struct proc *p)
+{
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+
+ PROC_SLOCK(p);
+ p->p_flag &= ~(P_STOPPED_TRACE | P_STOPPED_SIG | P_WAITED);
+ thread_unsuspend(p);
+ PROC_SUNLOCK(p);
+ itimer_proc_continue(p);
+ kqtimer_proc_continue(p);
+}
+
static int
proc_can_ptrace(struct thread *td, struct proc *p)
{
@@ -1164,12 +1177,7 @@
* suspended, use PT_SUSPEND to suspend it before
* continuing the process.
*/
- PROC_SLOCK(p);
- p->p_flag &= ~(P_STOPPED_TRACE | P_STOPPED_SIG | P_WAITED);
- thread_unsuspend(p);
- PROC_SUNLOCK(p);
- itimer_proc_continue(p);
- kqtimer_proc_continue(p);
+ ptrace_unsuspend(p);
break;
case PT_WRITE_I:
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -79,6 +79,7 @@
#include <sys/syslog.h>
#include <sys/unistd.h>
#include <sys/user.h>
+#include <sys/ktrace.h>
#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
@@ -2359,17 +2360,23 @@
vn_rlimit_fsize(const struct vnode *vp, const struct uio *uio,
struct thread *td)
{
+ off_t lim;
+ bool ktr_write;
- if (vp->v_type != VREG || td == NULL)
+ if (vp->v_type != VREG || td == NULL ||
+ (td->td_pflags2 & TDP2_ACCT) != 0)
return (0);
- if ((uoff_t)uio->uio_offset + uio->uio_resid >
- lim_cur(td, RLIMIT_FSIZE)) {
+ ktr_write = (td->td_pflags2 & TDP2_KTRWRITE) != 0;
+ lim = ktr_write ? td->td_ktr_io_lim : lim_cur(td, RLIMIT_FSIZE);
+ if ((uoff_t)uio->uio_offset + uio->uio_resid < lim)
+ return (0);
+
+ if (!ktr_write || ktr_filesize_limit_signal) {
PROC_LOCK(td->td_proc);
kern_psignal(td->td_proc, SIGXFSZ);
PROC_UNLOCK(td->td_proc);
- return (EFBIG);
}
- return (0);
+ return (EFBIG);
}
int
diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h
--- a/sys/sys/ktrace.h
+++ b/sys/sys/ktrace.h
@@ -265,6 +265,10 @@
#define KTRFAC_DROP 0x20000000 /* last event was dropped */
#ifdef _KERNEL
+struct ktr_io_params;
+
+struct vnode *ktr_get_tracevp(struct proc *, bool);
+void ktr_io_params_free(struct ktr_io_params *);
void ktrnamei(char *);
void ktrcsw(int, int, const char *);
void ktrpsig(int, sig_t, sigset_t *, int);
@@ -275,7 +279,7 @@
void ktrsysctl(int *name, u_int namelen);
void ktrsysret(int, int, register_t);
void ktrprocctor(struct proc *);
-void ktrprocexec(struct proc *, struct ucred **, struct vnode **);
+struct ktr_io_params *ktrprocexec(struct proc *);
void ktrprocexit(struct thread *);
void ktrprocfork(struct proc *, struct proc *);
void ktruserret(struct thread *);
@@ -295,6 +299,7 @@
#define ktrstat_error(s, error) \
ktrstruct_error("stat", (s), sizeof(struct stat), error)
extern u_int ktr_geniosize;
+extern int ktr_filesize_limit_signal;
#else
#include <sys/cdefs.h>
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -378,6 +378,7 @@
void *td_lkpi_task; /* LinuxKPI task struct pointer */
int td_pmcpend;
void *td_coredump; /* (c) coredump request. */
+ off_t td_ktr_io_lim; /* (k) limit for ktrace file size */
#ifdef EPOCH_TRACE
SLIST_HEAD(, epoch_tracker) td_epochs;
#endif
@@ -528,6 +529,8 @@
#define TDP2_SBPAGES 0x00000001 /* Owns sbusy on some pages */
#define TDP2_COMPAT32RB 0x00000002 /* compat32 ABI for robust lists */
+#define TDP2_ACCT 0x00000004 /* Doing accounting */
+#define TDP2_KTRWRITE 0x00000008 /* Doing ktrace record write */
/*
* Reasons that the current thread can not be run yet.
@@ -661,8 +664,7 @@
int p_profthreads; /* (c) Num threads in addupc_task. */
volatile int p_exitthreads; /* (j) Number of threads exiting */
int p_traceflag; /* (o) Kernel trace points. */
- struct vnode *p_tracevp; /* (c + o) Trace to vnode. */
- struct ucred *p_tracecred; /* (o) Credentials to trace with. */
+ struct ktr_io_params *p_ktrioparms; /* (c + o) Params for ktrace. */
struct vnode *p_textvp; /* (b) Vnode of executable. */
u_int p_lock; /* (c) Proclock (prevent swap) count. */
struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -240,6 +240,9 @@
int proc_read_dbregs32(struct thread *_td, struct dbreg32 *_dbreg32);
int proc_write_dbregs32(struct thread *_td, struct dbreg32 *_dbreg32);
#endif
+
+void ptrace_unsuspend(struct proc *p);
+
#else /* !_KERNEL */
#include <sys/cdefs.h>
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -274,6 +274,7 @@
#ifdef _KERNEL
extern sigset_t fastblock_mask;
extern bool sigfastblock_fetch_always;
+extern int kern_kill_on_dbg_exit;
/* Return nonzero if process p has an unmasked pending signal. */
#define SIGPENDING(td) \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 17, 6:57 AM (23 m, 59 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29813534
Default Alt Text
D30257.id89433.diff (26 KB)
Attached To
Mode
D30257: accounting: explicitly mark the exiting thread as doing accounting or ktrace record writing
Attached
Detach File
Event Timeline
Log In to Comment