From nobody Sat May 31 19:52:50 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4b8rPG74Ktz5xVVl; Sat, 31 May 2025 19:52:50 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4b8rPG32bxz3J3N; Sat, 31 May 2025 19:52:50 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1748721170; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iroCqjDyzF8oHMqOSqdDW0HXEe9FQlMHHWHuN7K95Tw=; b=vHDb9+ccO3cyK7cH2GVJPSZ3UwDlHLGV/xXZlntG4/avWRkwLTNbwM2mekOvHs3gWKbQsT 2nnEcezVLAvm+s4Zsk2E28xTL/jwjQG8JK7gg4cv3ex54F+fGVIRLLfCNfAFfqYwXL+vV9 bHRJQqPoCMgVauxJzPlbpnetBYuI0vSBwGdRYnfLNnPcsqXdrVuFNpqdY4Kp0ZgEnclVxf G1gbHhp2837zsdakz6sdvQpAkuHRCk2Dxa/Qkr6mcqc79PU9M+4ABf/RlDABUaSZerxAd5 V5c46xYWFVjupELsTE7BGydhlhi0zd29wbAAxhUs1h1ZGZDP0Flj5etuhmhtuw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1748721170; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=iroCqjDyzF8oHMqOSqdDW0HXEe9FQlMHHWHuN7K95Tw=; b=BwWYBEJgCOwzwmlWAt9g3dP2ZXSp0Ce6el4mbO0F9pUelAC/+dZTCZiwP+EXS/JMNGN2tz 8sJR+sXSeOC3+P+SwVGvMXIBU0e0DlOMnfg8PiGcaYTCKU/nLg/+zPZzRUC0/YTsUtGUBL WiIuYO+irFwRZy0sx45frtLIdo7705eiKEyhNiJYKD4q7OadhuxihIv+QUWbezerGoSa4a YzMO6vqw1qDpcgLfPZGCKJBvX0EdpRwp+qmEEn4asacTbZn15FrxXFCkmLdxTbeNIObhrq tXaNrqnTnY+JaTY/6Tv+eFZrGNn1QXsP4+R/qA9fJddspYqYq6+u2WAej8xAXg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1748721170; a=rsa-sha256; cv=none; b=IRz/Ro+X3vEfu/QKrT3iir8XdkN4ddK5tyPpdxPHD3gHcGoFToXK66kcngFzN3ee6M/jxK H2fjLSgXWIdDeOiYz0iBdfa72ZrSKX1rRMKw+b+YNSMxiA1gKCMW1CUdj2BH4/Gj1tgXyf 4VEYiJ6NcjO6b8lJ7D1CncVfseMJxTsCiptGQkdFZPbpSKy2rLIEso+HchNmykNfcgz7G8 6xESqVB1V6lAu91bplAmrW9UOFjtRMEoDFY1i1mp7aVa9hqZICQjld57R1bHKAay3Sdkbh 2AbuFmNLciBXtPuHsKhqeLo0qidsl+BXbitPVELg7lijNcpTwtjOmULwm6PomQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4b8rPG2DxTzsDk; Sat, 31 May 2025 19:52:50 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 54VJqoRd029656; Sat, 31 May 2025 19:52:50 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 54VJqoDh029653; Sat, 31 May 2025 19:52:50 GMT (envelope-from git) Date: Sat, 31 May 2025 19:52:50 GMT Message-Id: <202505311952.54VJqoDh029653@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Konstantin Belousov Subject: git: 09dfe066f00c - main - kernel: copyout extended errors to userspace and add exterrctl(2) to control it List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 09dfe066f00c927e88c23265387d432e6d9f0c5e Auto-Submitted: auto-generated The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=09dfe066f00c927e88c23265387d432e6d9f0c5e commit 09dfe066f00c927e88c23265387d432e6d9f0c5e Author: Konstantin Belousov AuthorDate: 2025-05-23 05:01:39 +0000 Commit: Konstantin Belousov CommitDate: 2025-05-31 19:52:41 +0000 kernel: copyout extended errors to userspace and add exterrctl(2) to control it Reviewed by: brooks Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D50483 --- sys/kern/kern_exec.c | 1 + sys/kern/kern_fork.c | 1 + sys/kern/subr_syscall.c | 4 +++ sys/kern/sys_generic.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++- sys/kern/syscalls.master | 8 +++++- sys/sys/exterrvar.h | 13 +++++++++ sys/sys/proc.h | 2 ++ sys/sys/uio.h | 1 + 8 files changed, 101 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index a943ec339e75..cf067527237e 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -809,6 +809,7 @@ interpret: * it that it now has its own resources back */ p->p_flag |= P_EXEC; + td->td_pflags2 &= ~TDP2_UEXTERR; if ((p->p_flag2 & P2_NOTRACE_EXEC) == 0) p->p_flag2 &= ~P2_NOTRACE; if ((p->p_flag2 & P2_STKGAP_DISABLE_EXEC) == 0) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 494f06cc0621..2ab9b363f8b5 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -609,6 +609,7 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread * */ p2->p_flag |= p1->p_flag & P_SUGID; td2->td_pflags |= td->td_pflags & (TDP_ALTSTACK | TDP_SIGFASTBLOCK); + td2->td_pflags2 |= td->td_pflags2 & TDP2_UEXTERR; SESS_LOCK(p1->p_session); if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT) p2->p_flag |= P_CONTROLT; diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c index 16fa47c5605a..d5b3b62f0821 100644 --- a/sys/kern/subr_syscall.c +++ b/sys/kern/subr_syscall.c @@ -74,6 +74,8 @@ syscallenter(struct thread *td) td->td_dbgflags |= TDB_SCE; PROC_UNLOCK(p); } + if ((td->td_pflags2 & TDP2_UEXTERR) != 0) + td->td_pflags2 &= ~TDP2_EXTERR; error = (p->p_sysent->sv_fetch_syscall_args)(td); se = sa->callp; #ifdef KTRACE @@ -207,6 +209,8 @@ syscallenter(struct thread *td) PROC_UNLOCK(p); } (p->p_sysent->sv_set_syscall_retval)(td, error); + if (error != 0 && (td->td_pflags2 & TDP2_UEXTERR) != 0) + exterr_copyout(td); } static inline void diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index dd9c28e81388..91bf3e93fa7c 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -34,10 +34,10 @@ * SUCH DAMAGE. */ -#include #include "opt_capsicum.h" #include "opt_ktrace.h" +#define EXTERR_CATEGORY EXTERR_CAT_FILEDESC #include #include #include @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -2200,3 +2201,73 @@ file_kcmp_generic(struct file *fp1, struct file *fp2, struct thread *td) return (3); return (kcmp_cmp((uintptr_t)fp1->f_data, (uintptr_t)fp2->f_data)); } + +void +exterr_copyout(struct thread *td) +{ + struct uexterror ue; + ksiginfo_t ksi; + void *uloc; + size_t sz; + int error; + + MPASS((td->td_pflags2 & TDP2_UEXTERR) != 0); + + uloc = (char *)td->td_exterr_ptr + __offsetof(struct uexterror, + error); + if ((td->td_pflags2 & TDP2_EXTERR) == 0) { + ue.error = 0; + sz = sizeof(ue.error); + } else { + memset(&ue, 0, sizeof(ue)); + ue.error = td->td_kexterr.error; + ue.cat = td->td_kexterr.cat; + ue.src_line = td->td_kexterr.src_line; + ue.p1 = td->td_kexterr.p1; + ue.p2 = td->td_kexterr.p2; + if (td->td_kexterr.msg != NULL) + strlcpy(ue.msg, td->td_kexterr.msg, sizeof(ue.msg)); + sz = sizeof(ue) - __offsetof(struct uexterror, error); + } + error = copyout(&ue.error, uloc, sz); + if (error != 0) { + td->td_pflags2 &= ~TDP2_UEXTERR; + ksiginfo_init_trap(&ksi); + ksi.ksi_signo = SIGSEGV; + ksi.ksi_code = SEGV_ACCERR; + ksi.ksi_addr = uloc; + trapsignal(td, &ksi); + } +} + +int +sys_exterrctl(struct thread *td, struct exterrctl_args *uap) +{ + uint32_t ver; + int error; + + if ((uap->flags & ~(EXTERRCTLF_FORCE)) != 0) + return (EINVAL); + switch (uap->op) { + case EXTERRCTL_ENABLE: + if ((td->td_pflags2 & TDP2_UEXTERR) != 0 && + (uap->flags & EXTERRCTLF_FORCE) == 0) + return (EBUSY); + td->td_pflags2 &= ~TDP2_UEXTERR; + error = copyin(uap->ptr, &ver, sizeof(ver)); + if (error != 0) + return (error); + if (ver != UEXTERROR_VER) + return (EINVAL); + td->td_pflags2 |= TDP2_UEXTERR; + td->td_exterr_ptr = uap->ptr; + return (0); + case EXTERRCTL_DISABLE: + if ((td->td_pflags2 & TDP2_UEXTERR) == 0) + return (EINVAL); + td->td_pflags2 &= ~TDP2_UEXTERR; + return (0); + default: + return (EINVAL); + } +} diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master index 67396a4cabc5..08b557a7a540 100644 --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -3349,5 +3349,11 @@ size_t size ); } - +592 AUE_NULL STD { + int exterrctl( + u_int op, + u_int flags, + _In_reads_bytes_(4) void *ptr + ); + } ; vim: syntax=off diff --git a/sys/sys/exterrvar.h b/sys/sys/exterrvar.h index 6e392ff2c18c..5afcd82b136a 100644 --- a/sys/sys/exterrvar.h +++ b/sys/sys/exterrvar.h @@ -26,6 +26,13 @@ struct uexterror { char msg[128]; }; +#define UEXTERROR_VER 0x10010001 + +#define EXTERRCTL_ENABLE 1 +#define EXTERRCTL_DISABLE 2 + +#define EXTERRCTLF_FORCE 0x00000001 + #ifdef _KERNEL #ifndef EXTERR_CATEGORY @@ -53,6 +60,12 @@ struct uexterror { #define SET_ERROR0(eerror, mmsg) SET_ERROR2(eerror, mmsg, 0, 0) #define SET_ERROR1(eerror, mmsg, pp1) SET_ERROR2(eerror, mmsg, pp1, 0) +#else /* _KERNEL */ + +__BEGIN_DECLS +int exterrctl(u_int op, u_int flags, void *ptr); +__END_DECLS + #endif /* _KERNEL */ #endif diff --git a/sys/sys/proc.h b/sys/sys/proc.h index cab487719c31..b48681420028 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -343,6 +343,7 @@ struct thread { void *td_sigblock_ptr; /* (k) uptr for fast sigblock. */ uint32_t td_sigblock_val; /* (k) fast sigblock value read at td_sigblock_ptr on kern entry */ + void *td_exterr_ptr; #define td_endcopy td_pcb /* @@ -572,6 +573,7 @@ enum { #define TDP2_ACCT 0x00000004 /* Doing accounting */ #define TDP2_SAN_QUIET 0x00000008 /* Disable warnings from K(A|M)SAN */ #define TDP2_EXTERR 0x00000010 /* Kernel reported ext error */ +#define TDP2_UEXTERR 0x00000020 /* User set ext error reporting ptr */ /* * Reasons that the current thread can not be run yet. diff --git a/sys/sys/uio.h b/sys/sys/uio.h index ec4e92d852a6..05c1ed640b63 100644 --- a/sys/sys/uio.h +++ b/sys/sys/uio.h @@ -84,6 +84,7 @@ int copyiniov(const struct iovec *iovp, u_int iovcnt, struct iovec **iov, int copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop); int copyout_map(struct thread *td, vm_offset_t *addr, size_t sz); int copyout_unmap(struct thread *td, vm_offset_t addr, size_t sz); +void exterr_copyout(struct thread *td); int physcopyin(void *src, vm_paddr_t dst, size_t len); int physcopyout(vm_paddr_t src, void *dst, size_t len); int physcopyin_vlist(struct bus_dma_segment *src, off_t offset,