kernel - Document bugs in sendfile that we currently punt on
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 14 Jun 2013 01:32:19 +0000 (18:32 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 14 Jun 2013 01:32:19 +0000 (18:32 -0700)
* sendfile tries to soft-busy the VM pages it backs the mbuf with.  This
  is meant to prevent the VM page's data from being modified while TCP
  is playing with it.  However, it doesn't work.  There are two issues.

* (1) The page still may be mmap()'d writable.  A simple vm_page_protect()
      would fix this.

* (2) The page may be associated with a buffer cache buffer and can be
      modified via a VOP_WRITE through that buffer regardless of whether
      soft-busy or busy is set.  This is a real problem.

      Even if we find and discard the buffer it can just be reinstantiated
      and wind up with the same problem.

From-discussion-with: jeffr, rookie on IRC

sys/kern/uipc_syscalls.c

index 55c5937..e2f84e6 100644 (file)
@@ -1669,6 +1669,20 @@ retry_lookup:
                        /*
                         * Ensure that our page is still around when the I/O 
                         * completes.
+                        *
+                        * Ensure that our page is not modified while part of
+                        * a mbuf as this could mess up tcp checksums, DMA,
+                        * etc (XXX NEEDS WORK).  The softbusy is supposed to
+                        * help here but it actually doesn't.
+                        *
+                        * XXX THIS HAS MULTIPLE PROBLEMS.  The underlying
+                        *     VM pages are not protected by the soft-busy
+                        *     unless we vm_page_protect... READ them, and
+                        *     they STILL aren't protected against
+                        *     modification via the buffer cache (VOP_WRITE).
+                        *
+                        *     Fixing the second issue is particularly
+                        *     difficult.
                         */
                        vm_page_io_start(pg);
                        vm_page_wakeup(pg);