aboutsummaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_jail.c2
-rw-r--r--sys/kern/kern_loginclass.c2
-rw-r--r--sys/kern/kern_prot.c23
-rw-r--r--sys/kern/kern_racct.c19
-rw-r--r--sys/kern/subr_syscall.c10
-rw-r--r--sys/kern/sys_generic.c32
-rw-r--r--sys/kern/vfs_aio.c10
-rw-r--r--sys/kern/vfs_bio.c17
8 files changed, 90 insertions, 25 deletions
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 267b60ffb5bc..523b7e314a10 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -3047,6 +3047,8 @@ do_jail_attach(struct thread *td, struct prison *pr, int drflags)
setsugid(p);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
+#endif
+#ifdef RCTL
crhold(newcred);
#endif
PROC_UNLOCK(p);
diff --git a/sys/kern/kern_loginclass.c b/sys/kern/kern_loginclass.c
index 55db6c28a1db..0c111c4f78d8 100644
--- a/sys/kern/kern_loginclass.c
+++ b/sys/kern/kern_loginclass.c
@@ -225,6 +225,8 @@ sys_setloginclass(struct thread *td, struct setloginclass_args *uap)
proc_set_cred(p, newcred);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
+#endif
+#ifdef RCTL
crhold(newcred);
#endif
PROC_UNLOCK(p);
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index a4c5bcc52529..3c145851b683 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -696,7 +696,7 @@ kern_setcred(struct thread *const td, const u_int flags,
gid_t *groups = NULL;
gid_t smallgroups[CRED_SMALLGROUPS_NB];
int error;
- bool cred_set;
+ bool cred_set = false;
/* Bail out on unrecognized flags. */
if (flags & ~SETCREDF_MASK)
@@ -839,17 +839,32 @@ kern_setcred(struct thread *const td, const u_int flags,
if (cred_set) {
setsugid(p);
to_free_cred = old_cred;
+#ifdef RACCT
+ racct_proc_ucred_changed(p, old_cred, new_cred);
+#endif
+#ifdef RCTL
+ crhold(new_cred);
+#endif
MPASS(error == 0);
} else
error = EAGAIN;
unlock_finish:
PROC_UNLOCK(p);
+
/*
* Part 3: After releasing the process lock, we perform cleanups and
* finishing operations.
*/
+#ifdef RCTL
+ if (cred_set) {
+ rctl_proc_ucred_changed(p, new_cred);
+ /* Paired with the crhold() just above. */
+ crfree(new_cred);
+ }
+#endif
+
#ifdef MAC
if (mac_set_proc_data != NULL)
mac_set_proc_finish(td, proc_label_set, mac_set_proc_data);
@@ -982,6 +997,8 @@ sys_setuid(struct thread *td, struct setuid_args *uap)
proc_set_cred(p, newcred);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
+#endif
+#ifdef RCTL
crhold(newcred);
#endif
PROC_UNLOCK(p);
@@ -1390,6 +1407,8 @@ sys_setreuid(struct thread *td, struct setreuid_args *uap)
proc_set_cred(p, newcred);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
+#endif
+#ifdef RCTL
crhold(newcred);
#endif
PROC_UNLOCK(p);
@@ -1536,6 +1555,8 @@ sys_setresuid(struct thread *td, struct setresuid_args *uap)
proc_set_cred(p, newcred);
#ifdef RACCT
racct_proc_ucred_changed(p, oldcred, newcred);
+#endif
+#ifdef RCTL
crhold(newcred);
#endif
PROC_UNLOCK(p);
diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c
index 2aab151aba08..17b64ad00bb5 100644
--- a/sys/kern/kern_racct.c
+++ b/sys/kern/kern_racct.c
@@ -1236,16 +1236,20 @@ racct_updatepcpu_containers(void)
racct_updatepcpu_post, NULL, NULL);
}
+static bool
+racct_proc_to_skip(const struct proc *p)
+{
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ return (p->p_state != PRS_NORMAL || (p->p_flag & P_IDLEPROC) != 0);
+}
+
static void
racctd(void)
{
struct proc *p;
- struct proc *idle;
ASSERT_RACCT_ENABLED();
- idle = STAILQ_FIRST(&cpuhead)->pc_idlethread->td_proc;
-
for (;;) {
racct_decay();
@@ -1253,12 +1257,7 @@ racctd(void)
FOREACH_PROC_IN_SYSTEM(p) {
PROC_LOCK(p);
- if (p == idle) {
- PROC_UNLOCK(p);
- continue;
- }
- if (p->p_state != PRS_NORMAL ||
- (p->p_flag & P_IDLEPROC) != 0) {
+ if (racct_proc_to_skip(p)) {
PROC_UNLOCK(p);
continue;
}
@@ -1284,7 +1283,7 @@ racctd(void)
*/
FOREACH_PROC_IN_SYSTEM(p) {
PROC_LOCK(p);
- if (p->p_state != PRS_NORMAL) {
+ if (racct_proc_to_skip(p)) {
PROC_UNLOCK(p);
continue;
}
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
index d5b3b62f0821..48896529f685 100644
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -55,8 +55,8 @@ syscallenter(struct thread *td)
struct proc *p;
struct syscall_args *sa;
struct sysent *se;
- int error, traced;
- bool sy_thr_static;
+ int error;
+ bool sy_thr_static, traced;
VM_CNT_INC(v_syscall);
p = td->td_proc;
@@ -219,7 +219,7 @@ syscallret(struct thread *td)
struct proc *p;
struct syscall_args *sa;
ksiginfo_t ksi;
- int traced;
+ bool traced;
KASSERT(td->td_errno != ERELOOKUP,
("ERELOOKUP not consumed syscall %d", td->td_sa.code));
@@ -250,9 +250,9 @@ syscallret(struct thread *td)
}
#endif
- traced = 0;
+ traced = false;
if (__predict_false(p->p_flag & P_TRACED)) {
- traced = 1;
+ traced = true;
PROC_LOCK(p);
td->td_dbgflags |= TDB_SCX;
PROC_UNLOCK(p);
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 7d666da9f88b..b84f675d1dcb 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -2345,3 +2345,35 @@ exterr_set(int eerror, int category, const char *mmsg, uintptr_t pp1,
}
return (eerror);
}
+
+int
+exterr_set_from(const struct kexterr *ke)
+{
+ struct thread *td;
+
+ td = curthread;
+ if ((td->td_pflags2 & TDP2_UEXTERR) != 0) {
+ td->td_pflags2 |= TDP2_EXTERR;
+ td->td_kexterr = *ke;
+ }
+ return (td->td_kexterr.error);
+}
+
+void
+exterr_clear(struct kexterr *ke)
+{
+ memset(ke, 0, sizeof(*ke));
+}
+
+#include "opt_ddb.h"
+#ifdef DDB
+#include <ddb/ddb.h>
+
+void
+exterr_db_print(struct kexterr *ke)
+{
+ db_printf("errno %d cat %d msg %s p1 %#jx p2 %#jx line %d\n",
+ ke->error, ke->cat, ke->msg == NULL ? "<none>" : ke->msg,
+ (uintmax_t)ke->p1, (uintmax_t)ke->p2, ke->src_line);
+}
+#endif
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 60916a9fbd32..02d4b8426757 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -2487,7 +2487,7 @@ aio_biowakeup(struct bio *bp)
long bcount = bp->bio_bcount;
long resid = bp->bio_resid;
int opcode, nblks;
- int bio_error = bp->bio_error;
+ int abio_error = bp->bio_error;
uint16_t flags = bp->bio_flags;
opcode = job->uaiocb.aio_lio_opcode;
@@ -2503,16 +2503,16 @@ aio_biowakeup(struct bio *bp)
* error of whichever failed bio completed last.
*/
if (flags & BIO_ERROR)
- atomic_store_int(&job->error, bio_error);
+ atomic_store_int(&job->error, abio_error);
if (opcode & LIO_WRITE)
atomic_add_int(&job->outblock, nblks);
else
atomic_add_int(&job->inblock, nblks);
if (refcount_release(&job->nbio)) {
- bio_error = atomic_load_int(&job->error);
- if (bio_error != 0)
- aio_complete(job, -1, bio_error);
+ abio_error = atomic_load_int(&job->error);
+ if (abio_error != 0)
+ aio_complete(job, -1, abio_error);
else
aio_complete(job, atomic_load_long(&job->nbytes), 0);
}
diff --git a/sys/kern/vfs_bio.c b/sys/kern/vfs_bio.c
index 19c39e42bafa..880cc6b99951 100644
--- a/sys/kern/vfs_bio.c
+++ b/sys/kern/vfs_bio.c
@@ -44,6 +44,7 @@
* see man buf(9) for more info.
*/
+#define EXTERR_CATEGORY EXTERR_CAT_VFSBIO
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/asan.h>
@@ -55,6 +56,7 @@
#include <sys/counter.h>
#include <sys/devicestat.h>
#include <sys/eventhandler.h>
+#include <sys/exterrvar.h>
#include <sys/fail.h>
#include <sys/ktr.h>
#include <sys/limits.h>
@@ -1775,7 +1777,6 @@ buf_alloc(struct bufdomain *bd)
bp->b_blkno = bp->b_lblkno = 0;
bp->b_offset = NOOFFSET;
bp->b_iodone = 0;
- bp->b_error = 0;
bp->b_resid = 0;
bp->b_bcount = 0;
bp->b_npages = 0;
@@ -1785,6 +1786,7 @@ buf_alloc(struct bufdomain *bd)
bp->b_fsprivate1 = NULL;
bp->b_fsprivate2 = NULL;
bp->b_fsprivate3 = NULL;
+ exterr_clear(&bp->b_exterr);
LIST_INIT(&bp->b_dep);
return (bp);
@@ -2276,7 +2278,7 @@ breadn_flags(struct vnode *vp, daddr_t blkno, daddr_t dblkno, int size,
}
if ((flags & GB_CVTENXIO) != 0)
bp->b_xflags |= BX_CVTENXIO;
- bp->b_ioflags &= ~BIO_ERROR;
+ bp->b_ioflags &= ~(BIO_ERROR | BIO_EXTERR);
if (bp->b_rcred == NOCRED && cred != NOCRED)
bp->b_rcred = crhold(cred);
vfs_busy_pages(bp, 0);
@@ -2353,7 +2355,7 @@ bufwrite(struct buf *bp)
bundirty(bp);
bp->b_flags &= ~B_DONE;
- bp->b_ioflags &= ~BIO_ERROR;
+ bp->b_ioflags &= ~(BIO_ERROR | BIO_EXTERR);
bp->b_flags |= B_CACHE;
bp->b_iocmd = BIO_WRITE;
@@ -4520,8 +4522,11 @@ biowait(struct bio *bp, const char *wmesg)
while ((bp->bio_flags & BIO_DONE) == 0)
msleep(bp, mtxp, PRIBIO, wmesg, 0);
mtx_unlock(mtxp);
- if (bp->bio_error != 0)
+ if (bp->bio_error != 0) {
+ if ((bp->bio_flags & BIO_EXTERR) != 0)
+ return (exterr_set_from(&bp->bio_exterr));
return (bp->bio_error);
+ }
if (!(bp->bio_flags & BIO_ERROR))
return (0);
return (EIO);
@@ -4568,6 +4573,8 @@ bufwait(struct buf *bp)
return (EINTR);
}
if (bp->b_ioflags & BIO_ERROR) {
+ if ((bp->b_ioflags & BIO_EXTERR) != 0)
+ exterr_set_from(&bp->b_exterr);
return (bp->b_error ? bp->b_error : EIO);
} else {
return (0);
@@ -5522,6 +5529,8 @@ DB_SHOW_COMMAND(buffer, db_show_buffer)
db_printf("\n");
}
BUF_LOCKPRINTINFO(bp);
+ if ((bp->b_ioflags & BIO_EXTERR) != 0)
+ exterr_db_print(&bp->b_exterr);
#if defined(FULL_BUF_TRACKING)
db_printf("b_io_tracking: b_io_tcnt = %u\n", bp->b_io_tcnt);