Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F172087223
D59034.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D59034.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D59034: sendfile(2): rework compat implementation
Attached
Detach File
Event Timeline
Log In to Comment