summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authordillon <dillon@FreeBSD.org>2003-01-20 17:46:48 +0000
committerdillon <dillon@FreeBSD.org>2003-01-20 17:46:48 +0000
commite7be7a0432de3e374a6d4cfedc0ef5c8b264a021 (patch)
tree9f8f2a306dcef88eb5da009ebff53701aaaeee2b /sys/cam
parenta752ec7b60312f295643dc7eb37ec1318d8c7412 (diff)
downloadFreeBSD-src-e7be7a0432de3e374a6d4cfedc0ef5c8b264a021.zip
FreeBSD-src-e7be7a0432de3e374a6d4cfedc0ef5c8b264a021.tar.gz
Close the remaining user address mapping races for physical
I/O, CAM, and AIO. Still TODO: streamline useracc() checks. Reviewed by: alc, tegge MFC after: 7 days
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/cam_periph.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 5bab8fb..247ebb8 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -534,7 +534,7 @@ cam_periph_unlock(struct cam_periph *periph)
int
cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
{
- int numbufs, i;
+ int numbufs, i, j;
int flags[CAM_PERIPH_MAXMAPS];
u_int8_t **data_ptrs[CAM_PERIPH_MAXMAPS];
u_int32_t lengths[CAM_PERIPH_MAXMAPS];
@@ -659,8 +659,28 @@ cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo)
/* set the direction */
mapinfo->bp[i]->b_iocmd = flags[i];
- /* map the buffer into kernel memory */
- vmapbuf(mapinfo->bp[i]);
+ /*
+ * Map the buffer into kernel memory.
+ *
+ * Note that useracc() alone is not a sufficient test.
+ * vmapbuf() can still fail due to a smaller file mapped
+ * into a larger area of VM, or if userland races against
+ * vmapbuf() after the useracc() check.
+ */
+ if (vmapbuf(mapinfo->bp[i]) < 0) {
+ printf("cam_periph_mapmem: error, "
+ "address %p, length %lu isn't "
+ "user accessible any more\n",
+ (void *)*data_ptrs[i],
+ (u_long)lengths[i]);
+ for (j = 0; j < i; ++j) {
+ *data_ptrs[j] = mapinfo->bp[j]->b_saveaddr;
+ mapinfo->bp[j]->b_flags &= ~B_PHYS;
+ relpbuf(mapinfo->bp[j], NULL);
+ }
+ PRELE(curproc);
+ return(EACCES);
+ }
/* set our pointer to the new mapped area */
*data_ptrs[i] = mapinfo->bp[i]->b_data;
OpenPOWER on IntegriCloud