Page MenuHomeFreeBSD

D59034.diff
No OneTemporary

D59034.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
@@ -2222,83 +2222,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
@@ -2306,16 +2243,20 @@
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, uap->fd, uap->s,
+ PAIR32TO64(off_t, uap->offset), uap->nbytes,
+ (struct sf_hdtr *)uap->hdtr, uap->sbytes, 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, uap->fd, uap->s,
+ PAIR32TO64(off_t, uap->offset), uap->nbytes,
+ (struct sf_hdtr *)uap->hdtr, uap->sbytes, 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,15 @@
}
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, int fd, int s, off_t offset, size_t nbytes,
+ struct sf_hdtr *uhdtr, off_t *usbytes, int flags, bool compat,
+ copyin_hdtr_t *copyin_hdtr_f, copyinuio_t *copyinuio_f)
{
struct sf_hdtr hdtr;
struct uio *hdr_uio, *trl_uio;
@@ -1221,18 +1229,18 @@
* File offset must be positive. If it goes beyond EOF
* we send only the header/trailer and no payload data.
*/
- if (uap->offset < 0)
+ if (offset < 0)
return (EINVAL);
sbytes = 0;
hdr_uio = trl_uio = NULL;
- if (uap->hdtr != NULL) {
- error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
+ if (uhdtr != NULL) {
+ error = copyin_hdtr_f(uhdtr, &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;
@@ -1243,15 +1251,15 @@
* header size from nbytes.
*/
if (compat) {
- if (uap->nbytes > hdr_uio->uio_resid)
- uap->nbytes -= hdr_uio->uio_resid;
+ if (nbytes > hdr_uio->uio_resid)
+ nbytes -= hdr_uio->uio_resid;
else
- uap->nbytes = 0;
+ nbytes = 0;
}
#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;
@@ -1260,21 +1268,21 @@
}
}
- AUDIT_ARG_FD(uap->fd);
+ AUDIT_ARG_FD(fd);
/*
* sendfile(2) can start at any offset within a file so we require
* CAP_READ+CAP_SEEK = CAP_PREAD.
*/
- if ((error = fget_read(td, uap->fd, &cap_pread_rights, &fp)) != 0)
+ if ((error = fget_read(td, fd, &cap_pread_rights, &fp)) != 0)
goto out;
- error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset,
- uap->nbytes, &sbytes, uap->flags, td);
+ error = fo_sendfile(fp, s, hdr_uio, trl_uio, offset,
+ nbytes, &sbytes, flags, td);
fdrop(fp, td);
- if (uap->sbytes != NULL)
- (void)copyout(&sbytes, uap->sbytes, sizeof(off_t));
+ if (usbytes != NULL)
+ (void)copyout(&sbytes, usbytes, sizeof(off_t));
out:
freeuio(hdr_uio);
@@ -1296,24 +1304,17 @@
int
sys_sendfile(struct thread *td, struct sendfile_args *uap)
{
-
- return (sendfile(td, uap, 0));
+ return (kern_sendfile(td, uap->fd, uap->s, uap->offset,
+ uap->nbytes, uap->hdtr, uap->sbytes, uap->flags, 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, uap->fd, uap->s, uap->offset,
+ uap->nbytes, uap->hdtr, uap->sbytes, 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
@@ -82,6 +82,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 +348,10 @@
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, int fd, int s, off_t offset,
+ size_t nbytes, struct sf_hdtr *hdtr, off_t *sbytes, int flags,
+ 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, Sep 17, 1:44 AM (11 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39041121
Default Alt Text
D59034.diff (7 KB)

Event Timeline