Date: Mon, 20 Jul 2026 20:53:24 +0000 From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: e19778bd3e98 - stable/15 - sendfile: stop abusing kern_writev() Message-ID: <6a5e8ac4.1e402.33041c6c@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=e19778bd3e98e46021271f7a95c9647b0ec6e95e commit e19778bd3e98e46021271f7a95c9647b0ec6e95e Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-07-04 02:29:56 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-07-20 20:26:03 +0000 sendfile: stop abusing kern_writev() (cherry picked from commit dfad790c8ccad05ff603ceaa5b2efe4205b38e1c) --- sys/kern/kern_sendfile.c | 25 +++++++++++++------------ sys/kern/sys_generic.c | 41 ++++++++++++++++++++++++++++++----------- sys/sys/syscallsubr.h | 2 ++ 3 files changed, 45 insertions(+), 23 deletions(-) diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c index 588bdea229e0..9d08f9626d45 100644 --- a/sys/kern/kern_sendfile.c +++ b/sys/kern/kern_sendfile.c @@ -1225,14 +1225,17 @@ prepend_header: } /* - * Send trailers. Wimp out and use writev(2). + * Send trailers. */ if (trl_uio != NULL) { + ssize_t cnt; + SOCK_IO_SEND_UNLOCK(so); CURVNET_RESTORE(); - error = kern_writev(td, sockfd, trl_uio); + error = kern_filewrite(td, sockfd, sock_fp, trl_uio, + (off_t)-1, 0, &cnt); if (error == 0) - sbytes += td->td_retval[0]; + sbytes += cnt; goto out; } @@ -1240,15 +1243,8 @@ done: SOCK_IO_SEND_UNLOCK(so); CURVNET_RESTORE(); out: - /* - * If there was no error we have to clear td->td_retval[0] - * because it may have been set by writev. - */ - if (error == 0) { - td->td_retval[0] = 0; - if (sbytes > 0 && vp != NULL) - INOTIFY(vp, IN_ACCESS); - } + if (error == 0 && sbytes > 0 && vp != NULL) + INOTIFY(vp, IN_ACCESS); if (sent != NULL) { (*sent) = sbytes; } @@ -1329,6 +1325,11 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat) &trl_uio); if (error != 0) goto out; + if (trl_uio->uio_rw != UIO_WRITE) { + error = EINVAL; + goto out; + } + trl_uio->uio_td = td; } } diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index b84f675d1dcb..07b98613e087 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -549,21 +549,16 @@ dofilewrite(struct thread *td, int fd, struct file *fp, struct uio *auio, { ssize_t cnt; int error; -#ifdef KTRACE - struct uio *ktruio = NULL; -#endif AUDIT_ARG_FD(fd); + auio->uio_rw = UIO_WRITE; auio->uio_td = td; auio->uio_offset = offset; -#ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) - ktruio = cloneuio(auio); -#endif - cnt = auio->uio_resid; - error = fo_write(fp, auio, td->td_ucred, flags, td); + error = kern_filewrite(td, fd, fp, auio, offset, flags, &cnt); + /* + * Handle short writes and generate SIGPIPE if needed. * Socket layer is responsible for special error handling, * see sousrsend(). */ @@ -577,15 +572,39 @@ dofilewrite(struct thread *td, int fd, struct file *fp, struct uio *auio, PROC_UNLOCK(td->td_proc); } } - cnt -= auio->uio_resid; + + if (error == 0) + td->td_retval[0] = cnt; + return (error); +} + +/* + * Write io request specified by auio into the file fp. If fd != -1, + * might generate the ktrace io point. + */ +int +kern_filewrite(struct thread *td, int fd, struct file *fp, struct uio *auio, + off_t offset, int flags, ssize_t *cntp) +{ + ssize_t cnt; + int error; +#ifdef KTRACE + struct uio *ktruio; + + ktruio = fd != -1 && KTRPOINT(td, KTR_GENIO) ? cloneuio(auio) : NULL; +#endif + cnt = auio->uio_resid; + error = fo_write(fp, auio, td->td_ucred, flags, td); #ifdef KTRACE if (ktruio != NULL) { + cnt -= auio->uio_resid; if (error == 0) ktruio->uio_resid = cnt; ktrgenio(fd, UIO_WRITE, ktruio, error); } #endif - td->td_retval[0] = cnt; + + *cntp = cnt; return (error); } diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index 23fa6a74f16f..439edb427ada 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -172,6 +172,8 @@ int kern_fcntl_freebsd(struct thread *td, int fd, int cmd, intptr_t arg); int kern_fhopen(struct thread *td, const struct fhandle *u_fhp, int flags); int kern_fhstat(struct thread *td, fhandle_t fh, struct stat *buf); int kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf); +int kern_filewrite(struct thread *td, int fd, struct file *fp, + struct uio *auio, off_t offset, int flags, ssize_t *cntp); int kern_fpathconf(struct thread *td, int fd, int name, long *valuep); int kern_freebsd11_getfsstat(struct thread *td, struct freebsd11_statfs *ubuf, long bufsize, int mode);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a5e8ac4.1e402.33041c6c>
