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 1094aadbd6f149f65d801cc785ba9e97d97da29c..23888a4046e4927d2bde09fcd753b940c6c94944 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
@@ -27,6 +27,8 @@ pub type zx_koid_t = u64;
 pub type zx_object_info_topic_t = u32;
 pub type zx_guest_trap_t = u32;
 
+pub const ZX_MAX_NAME_LEN: usize = 32;
+
 // TODO: combine these macros with the bitflags and assoc consts macros below
 // so that we only have to do one macro invocation.
 // The result would look something like:
diff --git a/garnet/public/rust/fuchsia-zircon/src/handle.rs b/garnet/public/rust/fuchsia-zircon/src/handle.rs
index c4a59e54d73f378b2b054eee4a2931b89086764f..78ba8ffa77fb82470a798d9a7878b0cabca25774 100644
--- a/garnet/public/rust/fuchsia-zircon/src/handle.rs
+++ b/garnet/public/rust/fuchsia-zircon/src/handle.rs
@@ -5,9 +5,12 @@
 //! Type-safe bindings for Zircon handles.
 //!
 use crate::{
-    object_get_info, ok, ObjectQuery, Port, Rights, Signals, Status, Time, Topic, WaitAsyncOpts,
+    object_get_info, object_get_property, object_set_property, ok, ObjectQuery, Port, Property,
+    PropertyQuery, PropertyQueryGet, PropertyQuerySet, Rights, Signals, Status, Time, Topic,
+    WaitAsyncOpts,
 };
 use fuchsia_zircon_sys as sys;
+use std::ffi::{CStr, CString};
 use std::marker::PhantomData;
 use std::mem::{self, ManuallyDrop};
 use std::ops::Deref;
@@ -72,7 +75,16 @@ impl Handle {
         let status = unsafe { sys::zx_handle_replace(handle, rights.bits(), &mut out) };
         ok(status).map(|()| Handle(out))
     }
+
+}
+
+struct NameProperty();
+unsafe impl PropertyQuery for NameProperty {
+    const PROPERTY: Property = Property::NAME;
+    type PropTy = [u8; sys::ZX_MAX_NAME_LEN];
 }
+unsafe impl PropertyQueryGet for NameProperty {}
+unsafe impl PropertyQuerySet for NameProperty {}
 
 /// A borrowed value of type `T`.
 ///
@@ -193,6 +205,38 @@ pub trait AsHandleRef {
     {
         self.as_handle_ref().wait_async(port, key, signals, options)
     }
+
+    /// Get the [Property::NAME] property for this object.
+    ///
+    /// Wraps a call to the
+    /// [zx_object_get_property](https://fuchsia.googlesource.com/fuchsia/+/master/zircon/docs/syscalls/object_get_property.md)
+    /// syscall for the ZX_PROP_NAME property.
+    fn get_name(&self) -> Result<CString, Status> {
+        let buf = object_get_property::<NameProperty>(self.as_handle_ref())?;
+        let nul_pos = buf.iter().position(|&x| x == b'\0').ok_or(Status::INTERNAL)?;
+        // We already checked for nul bytes, so simply unwrap.
+        Ok(CString::new(&buf[..nul_pos]).unwrap())
+    }
+
+    /// Set the [Property::NAME] property for this object.
+    ///
+    /// The name's length must be less than [sys::ZX_MAX_NAME_LEN], i.e.
+    /// name.[to_bytes_with_nul()](CStr::to_bytes_with_nul()).len() <= [sys::ZX_MAX_NAME_LEN], or
+    /// Err([Status::INVALID_ARGS]) will be returned.
+    ///
+    /// Wraps a call to the
+    /// [zx_object_get_property](https://fuchsia.googlesource.com/fuchsia/+/master/zircon/docs/syscalls/object_get_property.md)
+    /// syscall for the ZX_PROP_NAME property.
+    fn set_name(&self, name: &CStr) -> Result<(), Status> {
+        let bytes = name.to_bytes_with_nul();
+        if bytes.len() > sys::ZX_MAX_NAME_LEN {
+            return Err(Status::INVALID_ARGS);
+        }
+
+        let mut buf = [0u8; sys::ZX_MAX_NAME_LEN];
+        buf[..bytes.len()].copy_from_slice(bytes);
+        object_set_property::<NameProperty>(self.as_handle_ref(), &buf)
+    }
 }
 
 impl<'a, T: HandleBased> AsHandleRef for Unowned<'a, T> {
@@ -298,3 +342,35 @@ unsafe impl ObjectQuery for HandleBasicInfo {
     const TOPIC: Topic = Topic::HANDLE_BASIC;
     type InfoTy = HandleBasicInfo;
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::Vmo;
+
+    #[test]
+    fn set_get_name() {
+        // We need some concrete object to exercise the AsHandleRef set/get_name functions.
+        let vmo = Vmo::create(1).unwrap();
+        let short_name = CStr::from_bytes_with_nul(b"v\0").unwrap();
+        assert!(vmo.set_name(short_name).is_ok());
+        assert_eq!(vmo.get_name(), Ok(short_name.to_owned()));
+    }
+
+    #[test]
+    fn set_get_max_len_name() {
+        let vmo = Vmo::create(1).unwrap();
+        let max_len_name =
+            CStr::from_bytes_with_nul(b"a_great_maximum_length_vmo_name\0").unwrap(); // 32 bytes
+        assert!(vmo.set_name(max_len_name).is_ok());
+        assert_eq!(vmo.get_name(), Ok(max_len_name.to_owned()));
+    }
+
+    #[test]
+    fn set_get_too_long_name() {
+        let vmo = Vmo::create(1).unwrap();
+        let too_long_name =
+            CStr::from_bytes_with_nul(b"bad_really_too_too_long_vmo_name\0").unwrap(); // 33 bytes
+        assert_eq!(vmo.set_name(too_long_name), Err(Status::INVALID_ARGS));
+    }
+}