Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/iscsi avoid the use of UVM internals in the iscsi io...



details:   https://anonhg.NetBSD.org/src/rev/897a4c8d7ac5
branches:  trunk
changeset: 934993:897a4c8d7ac5
user:      chs <chs%NetBSD.org@localhost>
date:      Sun Jun 21 23:08:16 2020 +0000

description:
avoid the use of UVM internals in the iscsi ioctl code.
copyin/out are fine in this context.

diffstat:

 sys/dev/iscsi/iscsi_globals.h |    6 +-
 sys/dev/iscsi/iscsi_ioctl.c   |  124 ++++++++---------------------------------
 2 files changed, 25 insertions(+), 105 deletions(-)

diffs (185 lines):

diff -r f6c87f0750fe -r 897a4c8d7ac5 sys/dev/iscsi/iscsi_globals.h
--- a/sys/dev/iscsi/iscsi_globals.h     Sun Jun 21 22:17:35 2020 +0000
+++ b/sys/dev/iscsi/iscsi_globals.h     Sun Jun 21 23:08:16 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: iscsi_globals.h,v 1.25 2019/04/21 11:45:08 maya Exp $  */
+/*     $NetBSD: iscsi_globals.h,v 1.26 2020/06/21 23:08:16 chs Exp $   */
 
 /*-
  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
@@ -651,10 +651,6 @@
 void handle_connection_error(connection_t *, uint32_t, int);
 void add_connection_cleanup(connection_t *);
 
-#ifndef ISCSI_MINIMAL
-uint32_t map_databuf(struct proc *, void **, uint32_t);
-void unmap_databuf(struct proc *, void *, uint32_t);
-#endif
 int iscsiioctl(struct file *, u_long, void *);
 
 session_t *find_session(uint32_t);
diff -r f6c87f0750fe -r 897a4c8d7ac5 sys/dev/iscsi/iscsi_ioctl.c
--- a/sys/dev/iscsi/iscsi_ioctl.c       Sun Jun 21 22:17:35 2020 +0000
+++ b/sys/dev/iscsi/iscsi_ioctl.c       Sun Jun 21 23:08:16 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: iscsi_ioctl.c,v 1.31 2020/05/26 00:50:54 kamil Exp $   */
+/*     $NetBSD: iscsi_ioctl.c,v 1.32 2020/06/21 23:08:16 chs Exp $     */
 
 /*-
  * Copyright (c) 2004,2005,2006,2011 The NetBSD Foundation, Inc.
@@ -34,11 +34,7 @@
 #include <sys/file.h>
 #include <sys/filedesc.h>
 #include <sys/proc.h>
-
-#ifndef ISCSI_MINIMAL
-#include <uvm/uvm.h>
-#include <uvm/uvm_pmap.h>
-#endif
+#include <sys/kmem.h>
 
 static kmutex_t iscsi_cleanup_mtx;
 static kcondvar_t iscsi_cleanup_cv;
@@ -1278,92 +1274,6 @@
 #ifndef ISCSI_MINIMAL
 
 /*
- * map_databuf:
- *    Map user-supplied data buffer into kernel space.
- *
- *    Parameter:
- *          p        IN: The proc pointer of the caller
- *          buf      IN/OUT: The virtual address of the buffer, modified
- *                   on exit to reflect kernel VA.
- *          datalen  IN: The size of the data buffer
- *
- *    Returns:
- *          An ISCSI status code on error, else 0.
- */
-
-uint32_t
-map_databuf(struct proc *p, void **buf, uint32_t datalen)
-{
-       vaddr_t kva, databuf, offs;
-       int error;
-
-       /* page align address */
-       databuf = (vaddr_t) * buf & ~PAGE_MASK;
-       /* offset of VA into page */
-       offs = (vaddr_t) * buf & PAGE_MASK;
-       /* round to full page including offset */
-       datalen = (datalen + offs + PAGE_MASK) & ~PAGE_MASK;
-
-       /* Do some magic to the vm space reference count (copied from "copyin_proc") */
-       if ((p->p_sflag & PS_WEXIT) || (p->p_vmspace->vm_refcnt < 1)) {
-               return ISCSI_STATUS_NO_RESOURCES;
-       }
-       uvmspace_addref(p->p_vmspace);
-
-       /* this is lifted from uvm_io */
-       error = uvm_map_extract(&p->p_vmspace->vm_map, databuf, datalen,
-                       kernel_map, &kva,
-                       UVM_EXTRACT_QREF | UVM_EXTRACT_CONTIG |
-                               UVM_EXTRACT_FIXPROT);
-       if (error) {
-               DEBOUT(("uvm_map_extract failed, error = %d\n", error));
-               return ISCSI_STATUS_NO_RESOURCES;
-       }
-       /* add offset back into kernel VA */
-       *buf = (void *) (kva + offs);
-
-       return 0;
-}
-
-
-/*
- * unmap_databuf:
- *    Remove kernel space mapping of data buffer.
- *
- *    Parameter:
- *          p        IN: The proc pointer of the caller
- *          buf      IN: The kernel virtual address of the buffer
- *          datalen  IN: The size of the data buffer
- *
- *    Returns:
- *          An ISCSI status code on error, else 0.
- */
-
-void
-unmap_databuf(struct proc *p, void *buf, uint32_t datalen)
-{
-       struct vm_map_entry *dead_entries;
-       vaddr_t databuf;
-
-       /* round to full page */
-       datalen = (datalen + ((uintptr_t) buf & PAGE_MASK) + PAGE_MASK) & ~PAGE_MASK;
-       /* page align address */
-       databuf = (vaddr_t) buf & ~PAGE_MASK;
-
-       /* following code lifted almost verbatim from uvm_io.c */
-       vm_map_lock(kernel_map);
-       uvm_unmap_remove(kernel_map, databuf, databuf + datalen, &dead_entries,
-           0);
-       vm_map_unlock(kernel_map);
-       if (dead_entries != NULL) {
-               uvm_unmap_detach(dead_entries, AMAP_REFALL);
-       }
-       /* this apparently reverses the magic to the vm ref count, from copyin_proc */
-       uvmspace_free(p->p_vmspace);
-}
-
-
-/*
  * io_command:
  *    Handle the io_command ioctl.
  *
@@ -1376,8 +1286,9 @@
 io_command(iscsi_iocommand_parameters_t *par, struct lwp *l)
 {
        uint32_t datalen = par->req.datalen;
-       void *databuf = par->req.databuf;
        session_t *session;
+       void *kbuf = NULL;
+       int error;
 
        DEB(9, ("ISCSI: io_command, SID=%d, lun=%" PRIu64 "\n", par->session_id, par->lun));
        mutex_enter(&iscsi_cleanup_mtx);
@@ -1400,18 +1311,31 @@
                return;
        }
 
-       if (datalen && (par->status = map_databuf(l->l_proc,
-                       &par->req.databuf, datalen)) != 0) {
-               return;
+       if (datalen) {
+               /* Arbitrarily limit datalen to 8k. */
+               if (datalen > 8192) {
+                       par->status = ISCSI_STATUS_PARAMETER_INVALID;
+                       return;
+               }
+               kbuf = kmem_zalloc(datalen, KM_SLEEP);
+               if ((par->req.flags & SCCMD_WRITE) != 0) {
+                       error = copyin(par->req.databuf, kbuf, datalen);
+                       if (error) {
+                               kmem_free(kbuf, datalen);
+                               par->status = ISCSI_STATUS_PARAMETER_INVALID;
+                               return;
+                       }
+               }
        }
        par->status = send_io_command(session, par->lun, &par->req,
                                                                  par->options.immediate, par->connection_id);
 
-       if (datalen) {
-               unmap_databuf(l->l_proc, par->req.databuf, datalen);
-               par->req.databuf = databuf;     /* restore original addr */
+       if (kbuf) {
+               if ((par->req.flags & SCCMD_READ) != 0) {
+                       (void) copyout(kbuf, par->req.databuf, datalen);
+               }
+               kmem_free(kbuf, datalen);
        }
-
        switch (par->status) {
        case ISCSI_STATUS_SUCCESS:
                par->req.retsts = SCCMD_OK;



Home | Main Index | Thread Index | Old Index