[zircon] Add resizable vmo flag where necessary

This change is split out from a previous attempt to change the default
resize behavior. Once this change fully propagates, a second kernel-only
change can be submitted to flip the default behavior.

ZX-2357 #comment [zircon] Add resizable vmo flag where necessary

Change-Id: Ia4765cf19b0fcd60f2a6f8a7aa821542ae9f9df2
diff --git a/garnet/public/rust/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs b/garnet/public/rust/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs
index 84c701a..da73341 100644
--- a/garnet/public/rust/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs
+++ b/garnet/public/rust/fuchsia-zircon/fuchsia-zircon-sys/src/lib.rs
@@ -81,6 +81,7 @@
 
 multiconst!(u32, [
     ZX_VMO_NON_RESIZABLE = 1;
+    ZX_VMO_RESIZABLE = 1 << 1;
 ]);
 
 // TODO: add an alias for this type in the C headers.
@@ -343,6 +344,7 @@
 // VM Object clone flags
 pub const ZX_VMO_CHILD_COPY_ON_WRITE: u32 = 1;
 pub const ZX_VMO_CHILD_NON_RESIZEABLE: u32 = 1 << 1;
+pub const ZX_VMO_CHILD_RESIZABLE: u32 = 1 << 2;
 
 // channel write size constants
 pub const ZX_CHANNEL_MAX_MSG_HANDLES: u32 = 64;
diff --git a/garnet/public/rust/fuchsia-zircon/src/vmo.rs b/garnet/public/rust/fuchsia-zircon/src/vmo.rs
index 19a7dd8..ee0e316 100644
--- a/garnet/public/rust/fuchsia-zircon/src/vmo.rs
+++ b/garnet/public/rust/fuchsia-zircon/src/vmo.rs
@@ -146,6 +146,7 @@
     #[repr(transparent)]
     pub struct VmoOptions: u32 {
         const NON_RESIZABLE = sys::ZX_VMO_NON_RESIZABLE;
+        const RESIZABLE = sys::ZX_VMO_RESIZABLE;
     }
 }
 
@@ -155,6 +156,7 @@
     pub struct VmoChildOptions: u32 {
         const COPY_ON_WRITE = sys::ZX_VMO_CHILD_COPY_ON_WRITE;
         const NON_RESIZABLE = sys::ZX_VMO_CHILD_NON_RESIZEABLE;
+        const RESIZABLE = sys::ZX_VMO_CHILD_RESIZABLE;
     }
 }
 
@@ -199,7 +201,7 @@
     fn vmo_set_size() {
         // Use a multiple of page size to match VMOs page aligned size
         let start_size = 4096;
-        let vmo = Vmo::create(start_size).unwrap();
+        let vmo = Vmo::create_with_opts(VmoOptions::RESIZABLE, start_size).unwrap();
         assert_eq!(start_size, vmo.get_size().unwrap());
 
         // Change the size and make sure the new size is reported
diff --git a/garnet/public/rust/mapped-vmo/src/lib.rs b/garnet/public/rust/mapped-vmo/src/lib.rs
index 893f5a5..20fe32f 100644
--- a/garnet/public/rust/mapped-vmo/src/lib.rs
+++ b/garnet/public/rust/mapped-vmo/src/lib.rs
@@ -130,7 +130,7 @@
         let flags = zx::VmarFlags::PERM_READ | zx::VmarFlags::PERM_WRITE;
         {
             // Requires NON_RESIZEABLE
-            let vmo = zx::Vmo::create(size as u64).unwrap();
+            let vmo = zx::Vmo::create_with_opts(zx::VmoOptions::RESIZABLE, size as u64).unwrap();
             let status = Mapping::create_from_vmo(&vmo, size, flags).unwrap_err();
             assert_eq!(status, zx::Status::NOT_SUPPORTED);
         }
diff --git a/zircon/system/dev/block/ramdisk/ramdisk-controller.cpp b/zircon/system/dev/block/ramdisk/ramdisk-controller.cpp
index 9ddf16e..3e82b86 100644
--- a/zircon/system/dev/block/ramdisk/ramdisk-controller.cpp
+++ b/zircon/system/dev/block/ramdisk/ramdisk-controller.cpp
@@ -63,7 +63,7 @@
     };
 
     zx::vmo vmo;
-    zx_status_t status = zx::vmo::create(block_size * block_count, 0, &vmo);
+    zx_status_t status = zx::vmo::create(block_size * block_count, ZX_VMO_RESIZABLE, &vmo);
     if (status != ZX_OK) {
         return failure_response(status);
     }
diff --git a/zircon/system/ulib/bitmap/include/bitmap/storage.h b/zircon/system/ulib/bitmap/include/bitmap/storage.h
index 4e03bb1..4bde2c2 100644
--- a/zircon/system/ulib/bitmap/include/bitmap/storage.h
+++ b/zircon/system/ulib/bitmap/include/bitmap/storage.h
@@ -89,7 +89,7 @@
         Release();
         size_ = fbl::round_up(size, static_cast<size_t>(PAGE_SIZE));
         zx_status_t status;
-        if ((status = zx::vmo::create(size_, 0, &vmo_)) != ZX_OK) {
+        if ((status = zx::vmo::create(size_, ZX_VMO_RESIZABLE, &vmo_)) != ZX_OK) {
             return status;
         } else if ((status = zx_vmar_map(zx_vmar_root_self(),
                                          ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
diff --git a/zircon/system/ulib/fzl/include/lib/fzl/owned-vmo-mapper.h b/zircon/system/ulib/fzl/include/lib/fzl/owned-vmo-mapper.h
index 1c33b29..694e686 100644
--- a/zircon/system/ulib/fzl/include/lib/fzl/owned-vmo-mapper.h
+++ b/zircon/system/ulib/fzl/include/lib/fzl/owned-vmo-mapper.h
@@ -39,7 +39,8 @@
                              const char* name,
                              zx_vm_option_t map_options = ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
                              fbl::RefPtr<VmarManager> vmar_manager = nullptr,
-                             uint32_t cache_policy = 0);
+                             uint32_t cache_policy = 0,
+                             uint32_t vmo_options = 0);
 
     // See |VmoMapper::Map|.
     zx_status_t Map(zx::vmo vmo,
diff --git a/zircon/system/ulib/fzl/include/lib/fzl/vmo-mapper.h b/zircon/system/ulib/fzl/include/lib/fzl/vmo-mapper.h
index 3130c6e..f7d70b5e 100644
--- a/zircon/system/ulib/fzl/include/lib/fzl/vmo-mapper.h
+++ b/zircon/system/ulib/fzl/include/lib/fzl/vmo-mapper.h
@@ -47,12 +47,14 @@
     //                to leave the default rights.
     // cache_policy : When non-zero, indicates the cache policy to apply to the
     //                created VMO.
+    // vmo_options  : The options to use when creating the VMO.
     zx_status_t CreateAndMap(uint64_t size,
                              zx_vm_option_t map_flags,
                              fbl::RefPtr<VmarManager> vmar_manager = nullptr,
                              zx::vmo* vmo_out = nullptr,
                              zx_rights_t vmo_rights = ZX_RIGHT_SAME_RIGHTS,
-                             uint32_t cache_policy = 0);
+                             uint32_t cache_policy = 0,
+                             uint32_t vmo_options = 0);
 
     // Map an existing VMO our address space using the provided map
     // flags and optional target VMAR.
diff --git a/zircon/system/ulib/fzl/owned-vmo-mapper.cpp b/zircon/system/ulib/fzl/owned-vmo-mapper.cpp
index 9f08880..7c00c2f 100644
--- a/zircon/system/ulib/fzl/owned-vmo-mapper.cpp
+++ b/zircon/system/ulib/fzl/owned-vmo-mapper.cpp
@@ -15,14 +15,16 @@
                                          const char* name,
                                          zx_vm_option_t map_options,
                                          fbl::RefPtr<VmarManager> vmar_manager,
-                                         uint32_t cache_policy) {
+                                         uint32_t cache_policy,
+                                         uint32_t vmo_options) {
     zx::vmo temp;
     zx_status_t res = VmoMapper::CreateAndMap(size,
                                               map_options,
                                               std::move(vmar_manager),
                                               &temp,
                                               ZX_RIGHT_SAME_RIGHTS,
-                                              cache_policy);
+                                              cache_policy,
+                                              vmo_options);
 
     if (res == ZX_OK) {
         temp.set_property(ZX_PROP_NAME, name, name ? strlen(name) : 0);
diff --git a/zircon/system/ulib/fzl/resizeable-vmo-mapper.cpp b/zircon/system/ulib/fzl/resizeable-vmo-mapper.cpp
index dacfdf1..13406e5 100644
--- a/zircon/system/ulib/fzl/resizeable-vmo-mapper.cpp
+++ b/zircon/system/ulib/fzl/resizeable-vmo-mapper.cpp
@@ -39,7 +39,7 @@
                                               uint32_t cache_policy) {
     zx::vmo temp;
     zx_status_t res = OwnedVmoMapper::CreateAndMap(size, name, map_options, std::move(vmar_manager),
-                                                   cache_policy);
+                                                   cache_policy, ZX_VMO_RESIZABLE);
     if (res == ZX_OK) {
         map_options_ = map_options;
     }
diff --git a/zircon/system/ulib/fzl/vmo-mapper.cpp b/zircon/system/ulib/fzl/vmo-mapper.cpp
index 55d016f..42676af 100644
--- a/zircon/system/ulib/fzl/vmo-mapper.cpp
+++ b/zircon/system/ulib/fzl/vmo-mapper.cpp
@@ -15,7 +15,8 @@
                                     fbl::RefPtr<VmarManager> vmar_manager,
                                     zx::vmo* vmo_out,
                                     zx_rights_t vmo_rights,
-                                    uint32_t cache_policy) {
+                                    uint32_t cache_policy,
+                                    uint32_t vmo_options) {
     if (size == 0) {
         return ZX_ERR_INVALID_ARGS;
     }
@@ -26,7 +27,7 @@
     }
 
     zx::vmo vmo;
-    zx_status_t ret = zx::vmo::create(size, 0, &vmo);
+    zx_status_t ret = zx::vmo::create(size, vmo_options, &vmo);
     if (ret != ZX_OK) {
         return ret;
     }
diff --git a/zircon/system/ulib/memfs/file.cpp b/zircon/system/ulib/memfs/file.cpp
index 6b5c0d9..145c9ba 100644
--- a/zircon/system/ulib/memfs/file.cpp
+++ b/zircon/system/ulib/memfs/file.cpp
@@ -102,7 +102,7 @@
     zx_status_t status;
     if (!vmo_.is_valid()) {
         // First access to the file? Allocate it.
-        if ((status = zx::vmo::create(0, 0, &vmo_)) != ZX_OK) {
+        if ((status = zx::vmo::create(0, ZX_VMO_RESIZABLE, &vmo_)) != ZX_OK) {
             return status;
         }
     }
diff --git a/zircon/system/ulib/memfs/memfs.cpp b/zircon/system/ulib/memfs/memfs.cpp
index cd3a5b2..c5fd2d5 100644
--- a/zircon/system/ulib/memfs/memfs.cpp
+++ b/zircon/system/ulib/memfs/memfs.cpp
@@ -80,7 +80,7 @@
     }
     zx_status_t status;
     if (!vmo.is_valid()) {
-        if ((status = zx::vmo::create(aligned_len, 0, &vmo)) != ZX_OK) {
+        if ((status = zx::vmo::create(aligned_len, ZX_VMO_RESIZABLE, &vmo)) != ZX_OK) {
             return status;
         }
     } else {
diff --git a/zircon/system/ulib/minfs/vnode.cpp b/zircon/system/ulib/minfs/vnode.cpp
index d8d0d1e..b938493 100644
--- a/zircon/system/ulib/minfs/vnode.cpp
+++ b/zircon/system/ulib/minfs/vnode.cpp
@@ -236,7 +236,7 @@
 
     zx_status_t status;
     const size_t vmo_size = fbl::round_up(GetSize(), kMinfsBlockSize);
-    if ((status = zx::vmo::create(vmo_size, 0, &vmo_)) != ZX_OK) {
+    if ((status = zx::vmo::create(vmo_size, ZX_VMO_RESIZABLE, &vmo_)) != ZX_OK) {
         FS_TRACE_ERROR("Failed to initialize vmo; error: %d\n", status);
         return status;
     }
diff --git a/zircon/system/ulib/zbi-bootfs/zbi-bootfs.cpp b/zircon/system/ulib/zbi-bootfs/zbi-bootfs.cpp
index abbd55d..56cbc2d 100644
--- a/zircon/system/ulib/zbi-bootfs/zbi-bootfs.cpp
+++ b/zircon/system/ulib/zbi-bootfs/zbi-bootfs.cpp
@@ -212,7 +212,7 @@
             return ZX_ERR_BUFFER_TOO_SMALL;
         }
 
-        zx_status_t status = zx::vmo::create(buf_size, 0, &vmo);
+        zx_status_t status = zx::vmo::create(buf_size, ZX_VMO_RESIZABLE, &vmo);
 
         if (status != ZX_OK) {
             fprintf(stderr, "Error creating VMO\n");
diff --git a/zircon/system/utest/core/vmo/vmo-clone.cpp b/zircon/system/utest/core/vmo/vmo-clone.cpp
index 771ebc9..9379b24 100644
--- a/zircon/system/utest/core/vmo/vmo-clone.cpp
+++ b/zircon/system/utest/core/vmo/vmo-clone.cpp
@@ -176,7 +176,7 @@
 
     // create a vmo
     const size_t size = PAGE_SIZE * 4;
-    EXPECT_EQ(ZX_OK, zx_vmo_create(size, ZX_VMO_RESIZABLE, &vmo), "vm_object_create");
+    EXPECT_EQ(ZX_OK, zx_vmo_create(size, 0, &vmo), "vm_object_create");
 
     // map it
     EXPECT_EQ(ZX_OK,
@@ -187,7 +187,8 @@
 
     // clone it
     clone_vmo[0] = ZX_HANDLE_INVALID;
-    EXPECT_EQ(ZX_OK, zx_vmo_create_child(vmo, ZX_VMO_CHILD_COPY_ON_WRITE, 0, size, &clone_vmo[0]),"vm_clone");
+    EXPECT_EQ(ZX_OK, zx_vmo_create_child(vmo, ZX_VMO_CHILD_COPY_ON_WRITE | ZX_VMO_CHILD_RESIZABLE,
+                                         0, size, &clone_vmo[0]),"vm_clone");
     EXPECT_NE(ZX_HANDLE_INVALID, clone_vmo[0], "vm_clone_handle");
 
     // Attempt a non-resizable map fails.
@@ -409,7 +410,8 @@
 
     // create a clone that extends beyond the parent by one page
     clone_vmo[0] = ZX_HANDLE_INVALID;
-    EXPECT_EQ(ZX_OK, zx_vmo_create_child(vmo, ZX_VMO_CHILD_COPY_ON_WRITE, PAGE_SIZE, size, &clone_vmo[0]), "vm_clone");
+    EXPECT_EQ(ZX_OK, zx_vmo_create_child(vmo, ZX_VMO_CHILD_COPY_ON_WRITE | ZX_VMO_CHILD_RESIZABLE,
+                                         PAGE_SIZE, size, &clone_vmo[0]), "vm_clone");
 
     // map the clone
     EXPECT_EQ(ZX_OK,
diff --git a/zircon/system/utest/core/vmo/vmo-clone2.cpp b/zircon/system/utest/core/vmo/vmo-clone2.cpp
index ae1a185..880a42a 100644
--- a/zircon/system/utest/core/vmo/vmo-clone2.cpp
+++ b/zircon/system/utest/core/vmo/vmo-clone2.cpp
@@ -40,7 +40,7 @@
 // Creates a vmo with |page_count| pages and writes (page_index + 1) to each page.
 bool init_page_tagged_vmo(uint32_t page_count, zx::vmo* vmo) {
     zx_status_t status;
-    status = zx::vmo::create(page_count * ZX_PAGE_SIZE, 0, vmo);
+    status = zx::vmo::create(page_count * ZX_PAGE_SIZE, ZX_VMO_RESIZABLE, vmo);
     if (status != ZX_OK) {
         unittest_printf_critical(" create failed %d", status);
         return false;
@@ -573,7 +573,8 @@
     ASSERT_TRUE(init_page_tagged_vmo(4, &vmo));
 
     zx::vmo clone;
-    ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2, 0, 4 * ZX_PAGE_SIZE, &clone), ZX_OK);
+    ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2 | ZX_VMO_CHILD_RESIZABLE,
+                               0, 4 * ZX_PAGE_SIZE, &clone), ZX_OK);
 
     // Write to one page in each vmo.
     ASSERT_TRUE(vmo_write(vmo, 5, ZX_PAGE_SIZE));
@@ -626,7 +627,8 @@
     ASSERT_TRUE(init_page_tagged_vmo(2, &vmo));
 
     zx::vmo clone;
-    ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2, 0, ZX_PAGE_SIZE, &clone), ZX_OK);
+    ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2 | ZX_VMO_CHILD_RESIZABLE,
+                               0, ZX_PAGE_SIZE, &clone), ZX_OK);
 
     ASSERT_TRUE(vmo_check(clone, 1));
 
@@ -673,7 +675,7 @@
         // Clone one clone for each page.
         zx::vmo clones[3];
         for (unsigned i = 0; i < 3; i++) {
-            ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2,
+            ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2 | ZX_VMO_CHILD_RESIZABLE,
                                        i * ZX_PAGE_SIZE, ZX_PAGE_SIZE, clones + i), ZX_OK);
             ASSERT_TRUE(vmo_check(clones[i], i + 1));
         }
@@ -703,7 +705,8 @@
 
     // Clone the vmo and fork a page into both.
     zx::vmo clone;
-    ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2, 0, 2 * ZX_PAGE_SIZE, &clone), ZX_OK);
+    ASSERT_EQ(vmo.create_child(ZX_VMO_CHILD_COPY_ON_WRITE2 | ZX_VMO_CHILD_RESIZABLE,
+                               0, 2 * ZX_PAGE_SIZE, &clone), ZX_OK);
     ASSERT_TRUE(vmo_write(vmo, 4, 0 * ZX_PAGE_SIZE));
     ASSERT_TRUE(vmo_write(clone, 5, 1 * ZX_PAGE_SIZE));
 
@@ -919,7 +922,7 @@
 
     // Repeatedly clone the vmo while simultaniously changing it.
     for (unsigned i = 1; i < kNumClones; i++) {
-        ASSERT_EQ(vmos[0].create_child(ZX_VMO_CHILD_COPY_ON_WRITE2,
+        ASSERT_EQ(vmos[0].create_child(ZX_VMO_CHILD_COPY_ON_WRITE2 | ZX_VMO_CHILD_RESIZABLE,
                                        0, kNumClones * ZX_PAGE_SIZE, vmos + i), ZX_OK);
         ASSERT_TRUE(vmo_write(vmos[i], kNumClones + 2, i * ZX_PAGE_SIZE));
     }
diff --git a/zircon/third_party/ulib/musl/ldso/dynlink.c b/zircon/third_party/ulib/musl/ldso/dynlink.c
index 1774fe5..8fa91810 100644
--- a/zircon/third_party/ulib/musl/ldso/dynlink.c
+++ b/zircon/third_party/ulib/musl/ldso/dynlink.c
@@ -1016,7 +1016,8 @@
                 }
             } else {
                 // Get a writable (lazy) copy of the portion of the file VMO.
-                status = _zx_vmo_create_child(vmo, ZX_VMO_CHILD_COPY_ON_WRITE,
+                status = _zx_vmo_create_child(vmo,
+                                              ZX_VMO_CHILD_COPY_ON_WRITE | ZX_VMO_CHILD_RESIZABLE,
                                               off_start, data_size, &map_vmo);
                 if (status == ZX_OK && map_size > data_size) {
                     // Extend the writable VMO to cover the .bss pages too.
diff --git a/zircon/third_party/ulib/scudo/fuchsia.cc b/zircon/third_party/ulib/scudo/fuchsia.cc
index 22c3801..6c9f884 100644
--- a/zircon/third_party/ulib/scudo/fuchsia.cc
+++ b/zircon/third_party/ulib/scudo/fuchsia.cc
@@ -90,7 +90,7 @@
     }
   } else {
     // Otherwise, create a Vmo and set its name.
-    Status = _zx_vmo_create(Size, 0, &Vmo);
+    Status = _zx_vmo_create(Size, ZX_VMO_RESIZABLE, &Vmo);
     if (Status != ZX_OK) {
       if (Status != ZX_ERR_NO_MEMORY || !AllowNoMem)
         dieOnMapUnmapError(Status == ZX_ERR_NO_MEMORY);