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