From 72d5fa11a8e3a0e4640da289d76ae672eb070565 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 10 Nov 2017 11:01:39 +0100 Subject: Fix reference counting for file descriptors Update #3132. --- freebsd/sys/kern/kern_event.c | 2 ++ freebsd/sys/kern/sys_pipe.c | 6 ++++++ freebsd/sys/kern/uipc_syscalls.c | 10 ++++++++++ freebsd/sys/sys/file.h | 7 +++++++ freebsd/sys/sys/filedesc.h | 5 ++++- 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/freebsd/sys/kern/kern_event.c b/freebsd/sys/kern/kern_event.c index ed1a9dab..0a64adbe 100644 --- a/freebsd/sys/kern/kern_event.c +++ b/freebsd/sys/kern/kern_event.c @@ -939,7 +939,9 @@ kern_kqueue(struct thread *td, int flags, struct filecaps *fcaps) #endif /* __rtems__ */ finit(fp, FREAD | FWRITE, DTYPE_KQUEUE, kq, &kqueueops); +#ifndef __rtems__ fdrop(fp, td); +#endif /* __rtems__ */ td->td_retval[0] = fd; return (0); diff --git a/freebsd/sys/kern/sys_pipe.c b/freebsd/sys/kern/sys_pipe.c index 1636280f..08dd619a 100755 --- a/freebsd/sys/kern/sys_pipe.c +++ b/freebsd/sys/kern/sys_pipe.c @@ -485,16 +485,22 @@ kern_pipe(struct thread *td, int fildes[2], int flags, struct filecaps *fcaps1, error = falloc_caps(td, &wf, &fd, flags, fcaps2); if (error) { fdclose(td, rf, fildes[0]); +#ifndef __rtems__ fdrop(rf, td); +#endif /* __rtems__ */ /* rpipe has been closed by fdrop(). */ pipeclose(wpipe); return (error); } /* An extra reference on `wf' has been held for us by falloc_caps(). */ finit(wf, fflags, DTYPE_PIPE, wpipe, &pipeops); +#ifndef __rtems__ fdrop(wf, td); +#endif /* __rtems__ */ fildes[1] = fd; +#ifndef __rtems__ fdrop(rf, td); +#endif /* __rtems__ */ return (0); } diff --git a/freebsd/sys/kern/uipc_syscalls.c b/freebsd/sys/kern/uipc_syscalls.c index 3c6d7efd..62101b5e 100644 --- a/freebsd/sys/kern/uipc_syscalls.c +++ b/freebsd/sys/kern/uipc_syscalls.c @@ -214,7 +214,9 @@ kern_socket(struct thread *td, int domain, int type, int protocol) (void) fo_ioctl(fp, FIONBIO, &fflag, td->td_ucred, td); td->td_retval[0] = fd; } +#ifndef __rtems__ fdrop(fp, td); +#endif /* __rtems__ */ return (error); } #ifdef __rtems__ @@ -616,8 +618,10 @@ done: } else *fp = NULL; } +#ifndef __rtems__ if (nfp != NULL) fdrop(nfp, td); +#endif /* __rtems__ */ fdrop(headfp, td); return (error); } @@ -840,15 +844,21 @@ kern_socketpair(struct thread *td, int domain, int type, int protocol, (void) fo_ioctl(fp1, FIONBIO, &fflag, td->td_ucred, td); (void) fo_ioctl(fp2, FIONBIO, &fflag, td->td_ucred, td); } +#ifndef __rtems__ fdrop(fp1, td); fdrop(fp2, td); +#endif /* __rtems__ */ return (0); free4: fdclose(td, fp2, rsv[1]); +#ifndef __rtems__ fdrop(fp2, td); +#endif /* __rtems__ */ free3: fdclose(td, fp1, rsv[0]); +#ifndef __rtems__ fdrop(fp1, td); +#endif /* __rtems__ */ free2: if (so2 != NULL) (void)soclose(so2); diff --git a/freebsd/sys/sys/file.h b/freebsd/sys/sys/file.h index 18274d67..2adbd0af 100644 --- a/freebsd/sys/sys/file.h +++ b/freebsd/sys/sys/file.h @@ -413,6 +413,13 @@ rtems_bsd_fdrop(struct file *fp) rtems_libio_iop_drop(&fp->f_io); } +/* + * WARNING: fdalloc() and falloc_caps() do not increment the reference count of + * the file descriptor in contrast to FreeBSD. We must not call the fdrop() + * corresponding to a fdalloc() or falloc_caps(). The reason for this is that + * FreeBSD performs a lazy cleanup once the reference count reaches zero. + * RTEMS uses the reference count to determine if a cleanup is allowed. + */ #define fdrop(fp, td) rtems_bsd_fdrop(fp) #endif /* __rtems__ */ diff --git a/freebsd/sys/sys/filedesc.h b/freebsd/sys/sys/filedesc.h index b1c3e24b..457898ef 100644 --- a/freebsd/sys/sys/filedesc.h +++ b/freebsd/sys/sys/filedesc.h @@ -202,7 +202,6 @@ falloc_caps(struct thread *td, struct file **resultfp, int *resultfd, *resultfp = rtems_bsd_iop_to_fp(iop); if (iop != NULL) { - rtems_libio_iop_hold(iop); iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry; rtems_filesystem_location_add_to_mt_entry(&iop->pathinfo); *resultfd = rtems_libio_iop_to_descriptor(iop); @@ -223,6 +222,10 @@ int fdcheckstd(struct thread *td); #ifndef __rtems__ void fdclose(struct thread *td, struct file *fp, int idx); #else /* __rtems__ */ +/* + * WARNING: Use of fdrop() after fclose() corrupts the file descriptor. See + * fdrop() comment. + */ static inline void fdclose(struct thread *td, struct file *fp, int idx) { -- cgit v1.2.3