On Wed, 2014-07-02 at 17:53 +0200, Stefan Klug wrote: > @@ -1471,6 +1526,57 @@ static int proc_do_submiturb(struct > usb_dev_state > *ps, struct usbdevfs_urb *uurb > } > totlen -= u; > } > + } else if(num_pages) { > + pages = kmalloc(num_pages*sizeof(struct page*), GFP_KERNEL); > + if(!pages) { > + ret = -ENOMEM; > + goto error; > + } > + > + //create the scatterlist > + as->urb->sg = kmalloc(num_pages * sizeof(struct > scatterlist), > GFP_KERNEL); > + if (!as->urb->sg) { > + ret = -ENOMEM; > + goto error; > + } > + > + ret = get_user_pages_fast((unsigned long)buf_aligned, > + num_pages, > + is_in, > + pages); > + > + if(ret < 0) { > + printk("get_user_pages failed %i\n", ret); > + goto error; > + } > + > + //did we get all pages? > + if(ret < num_pages) { > + printk("get_user_pages didn't deliver all pages %i\n", > ret); > + //free the pages and error out > + for(i=0; i<ret; i++) { > + page_cache_release(pages[i]); > + } > + ret = -ENOMEM; > + goto error; > + } > + > + as->is_user_mem = 1; > + as->urb->num_sgs = num_pages; > + sg_init_table(as->urb->sg, as->urb->num_sgs); > + > + totlen = uurb->buffer_length + buf_offset; > + o = buf_offset; > + for (i = 0; i < as->urb->num_sgs; i++) { > + u = (totlen > PAGE_SIZE) ? PAGE_SIZE : totlen; > + u-= o; > + sg_set_page(&as->urb->sg[i], pages[i], u, o); > + totlen -= u + o; > + o = 0; > + } > + > + kfree(pages); > + pages = NULL; > } else if (uurb->buffer_length > 0) { > as->urb->transfer_buffer = kmalloc(uurb->buffer_length, > GFP_KERNEL)
One more thing: Where do you check that the memory the user has passed a pointer to is actually writable? It seems to me that for zerocopy you must do the check before you submit the URB to the HCD. Regards Oliver -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/