Page MenuHomeFreeBSD

D59034.id.diff
No OneTemporary

D59034.id.diff

diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -2198,83 +2198,20 @@
};
static int
-freebsd32_do_sendfile(struct thread *td,
- struct freebsd32_sendfile_args *uap, int compat)
+freebsd32_copyin_hdtr(const void *uhdtr, struct sf_hdtr *hdtr)
{
struct sf_hdtr32 hdtr32;
- struct sf_hdtr hdtr;
- struct uio *hdr_uio, *trl_uio;
- struct file *fp;
- cap_rights_t rights;
- struct iovec32 *iov32;
- off_t offset, sbytes;
int error;
- offset = PAIR32TO64(off_t, uap->offset);
- if (offset < 0)
- return (EINVAL);
-
- hdr_uio = trl_uio = NULL;
-
- if (uap->hdtr != NULL) {
- error = copyin(uap->hdtr, &hdtr32, sizeof(hdtr32));
- if (error)
- goto out;
- PTRIN_CP(hdtr32, hdtr, headers);
- CP(hdtr32, hdtr, hdr_cnt);
- PTRIN_CP(hdtr32, hdtr, trailers);
- CP(hdtr32, hdtr, trl_cnt);
-
- if (hdtr.headers != NULL) {
- iov32 = PTRIN(hdtr32.headers);
- error = freebsd32_copyinuio(iov32,
- hdtr32.hdr_cnt, &hdr_uio);
- if (error)
- goto out;
-#ifdef COMPAT_FREEBSD4
- /*
- * In FreeBSD < 5.0 the nbytes to send also included
- * the header. If compat is specified subtract the
- * header size from nbytes.
- */
- if (compat) {
- if (uap->nbytes > hdr_uio->uio_resid)
- uap->nbytes -= hdr_uio->uio_resid;
- else
- uap->nbytes = 0;
- }
-#endif
- }
- if (hdtr.trailers != NULL) {
- iov32 = PTRIN(hdtr32.trailers);
- error = freebsd32_copyinuio(iov32,
- hdtr32.trl_cnt, &trl_uio);
- if (error)
- goto out;
- trl_uio->uio_rw = UIO_WRITE;
- trl_uio->uio_td = td;
- }
- }
-
- AUDIT_ARG_FD(uap->fd);
-
- if ((error = fget_read(td, uap->fd,
- cap_rights_init_one(&rights, CAP_PREAD), &fp)) != 0)
- goto out;
-
- error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset,
- uap->nbytes, &sbytes, uap->flags, td);
- fdrop(fp, td);
-
- if (uap->sbytes != NULL)
- (void)copyout(&sbytes, uap->sbytes, sizeof(off_t));
+ error = copyin(uhdtr, &hdtr32, sizeof(hdtr32));
+ if (error != 0)
+ return (error);
+ hdtr->headers = PTRIN(hdtr32.headers);
+ hdtr->hdr_cnt = hdtr32.hdr_cnt;
+ hdtr->trailers = PTRIN(hdtr32.trailers);
+ hdtr->trl_cnt = hdtr32.trl_cnt;
-out:
- if (hdr_uio)
- freeuio(hdr_uio);
- if (trl_uio)
- freeuio(trl_uio);
- return (error);
+ return (0);
}
#ifdef COMPAT_FREEBSD4
@@ -2282,16 +2219,32 @@
freebsd4_freebsd32_sendfile(struct thread *td,
struct freebsd4_freebsd32_sendfile_args *uap)
{
- return (freebsd32_do_sendfile(td,
- (struct freebsd32_sendfile_args *)uap, 1));
+ return (kern_sendfile(td, &(struct sendfile_args){
+ .fd = uap->fd,
+ .s = uap->s,
+ .offset = PAIR32TO64(off_t, uap->offset),
+ .nbytes = uap->nbytes,
+ .hdtr = (struct sf_hdtr *)uap->hdtr,
+ .sbytes = uap->sbytes,
+ .flags = uap->flags,
+ }, true, freebsd32_copyin_hdtr,
+ (copyinuio_t *)freebsd32_copyinuio));
}
#endif
int
freebsd32_sendfile(struct thread *td, struct freebsd32_sendfile_args *uap)
{
-
- return (freebsd32_do_sendfile(td, uap, 0));
+ return (kern_sendfile(td, &(struct sendfile_args){
+ .fd = uap->fd,
+ .s = uap->s,
+ .offset = PAIR32TO64(off_t, uap->offset),
+ .nbytes = uap->nbytes,
+ .hdtr = (struct sf_hdtr *)uap->hdtr,
+ .sbytes = uap->sbytes,
+ .flags = uap->flags,
+ }, false, freebsd32_copyin_hdtr,
+ (copyinuio_t *)freebsd32_copyinuio));
}
static void
diff --git a/sys/kern/kern_sendfile.c b/sys/kern/kern_sendfile.c
--- a/sys/kern/kern_sendfile.c
+++ b/sys/kern/kern_sendfile.c
@@ -1209,7 +1209,14 @@
}
static int
-sendfile(struct thread *td, struct sendfile_args *uap, int compat)
+copyin_hdtr(const struct sf_hdtr *uhdtr, struct sf_hdtr *hdtr)
+{
+ return (copyin(uhdtr, hdtr, sizeof(*hdtr)));
+}
+
+int
+kern_sendfile(struct thread *td, struct sendfile_args *uap, bool compat,
+ copyin_hdtr_t *copyin_hdtr_f, copyinuio_t *copyinuio_f)
{
struct sf_hdtr hdtr;
struct uio *hdr_uio, *trl_uio;
@@ -1228,11 +1235,11 @@
hdr_uio = trl_uio = NULL;
if (uap->hdtr != NULL) {
- error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
+ error = copyin_hdtr_f(uap->hdtr, &hdtr);
if (error != 0)
goto out;
if (hdtr.headers != NULL) {
- error = copyinuio(hdtr.headers, hdtr.hdr_cnt,
+ error = copyinuio_f(hdtr.headers, hdtr.hdr_cnt,
&hdr_uio);
if (error != 0)
goto out;
@@ -1251,7 +1258,7 @@
#endif
}
if (hdtr.trailers != NULL) {
- error = copyinuio(hdtr.trailers, hdtr.trl_cnt,
+ error = copyinuio_f(hdtr.trailers, hdtr.trl_cnt,
&trl_uio);
if (error != 0)
goto out;
@@ -1297,23 +1304,22 @@
sys_sendfile(struct thread *td, struct sendfile_args *uap)
{
- return (sendfile(td, uap, 0));
+ return (kern_sendfile(td, uap, false, (copyin_hdtr_t *)copyin_hdtr,
+ (copyinuio_t *)copyinuio));
}
#ifdef COMPAT_FREEBSD4
int
freebsd4_sendfile(struct thread *td, struct freebsd4_sendfile_args *uap)
{
- struct sendfile_args args;
-
- args.fd = uap->fd;
- args.s = uap->s;
- args.offset = uap->offset;
- args.nbytes = uap->nbytes;
- args.hdtr = uap->hdtr;
- args.sbytes = uap->sbytes;
- args.flags = uap->flags;
-
- return (sendfile(td, &args, 1));
+ return (kern_sendfile(td, &(struct sendfile_args){
+ .fd = uap->fd,
+ .s = uap->s,
+ .offset = uap->offset,
+ .nbytes = uap->nbytes,
+ .hdtr = uap->hdtr,
+ .sbytes = uap->sbytes,
+ .flags = uap->flags,
+ }, true, (copyin_hdtr_t *)copyin_hdtr, (copyinuio_t *)copyinuio));
}
#endif /* COMPAT_FREEBSD4 */
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -59,6 +59,7 @@
struct rusage;
struct sched_param;
struct sembuf;
+struct sendfile_args;
union semun;
struct shmfd;
struct sockaddr;
@@ -82,6 +83,20 @@
mmap_check_fp_fn mr_check_fp_fn;
};
+/*
+ * A copyin_hdtr_t takes a pointer to a sendfile header/trailer in
+ * userspace and storage for on in the kernel and copies it in.
+ */
+typedef int (copyin_hdtr_t)(const void *hdtrp, struct sf_hdtr *hdtr);
+
+/*
+ * A copyinuio_t takes a pointer to an iovec in userspace along with a
+ * count and allocates a struct uio containing a copy of the iovec.
+ * The uio should be freed with freeuio().
+ */
+typedef int (copyinuio_t)(const void *iovp, unsigned int iovcnt,
+ struct uio **iov);
+
uint64_t at2cnpflags(u_int at_flags, u_int mask);
int kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg,
size_t buflen, size_t path_max);
@@ -334,6 +349,8 @@
struct timespec *ts);
int kern_semctl(struct thread *td, int semid, int semnum, int cmd,
union semun *arg, register_t *rval);
+int kern_sendfile(struct thread *td, struct sendfile_args *uap, bool compat,
+ copyin_hdtr_t *copyin_hdtr_f, copyinuio_t *copyinuio_f);
int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou,
fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits);
int kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags,

File Metadata

Mime Type
text/plain
Expires
Thu, Aug 27, 10:39 AM (3 h, 22 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37314007
Default Alt Text
D59034.id.diff (6 KB)

Event Timeline