diff --git a/cc/metrics/shared_metrics_buffer.h b/cc/metrics/shared_metrics_buffer.h
index 6a0514fd63ece..0b51c9b4f08f5 100644
--- a/cc/metrics/shared_metrics_buffer.h
+++ b/cc/metrics/shared_metrics_buffer.h
@@ -27,7 +27,8 @@ struct SharedMetricsBuffer {
     do {
       const uint32_t kMaxReadAttempts = 32;
       version = seq_lock.ReadBegin(kMaxReadAttempts);
-      device::OneWriterSeqLock::AtomicReaderMemcpy(&out, &data, sizeof(T));
+      device::OneWriterSeqLock::AtomicReaderMemcpy<T>(
+          base::span_from_ref(out), base::span_from_ref(data));
     } while (seq_lock.ReadRetry(version) && ++retries < kMaxRetries);
 
     // Consider the number of retries less than kMaxRetries as success.
@@ -36,7 +37,8 @@ struct SharedMetricsBuffer {
 
   void Write(const T& in) {
     seq_lock.WriteBegin();
-    device::OneWriterSeqLock::AtomicWriterMemcpy(&data, &in, sizeof(T));
+    device::OneWriterSeqLock::AtomicWriterMemcpy<T>(base::span_from_ref(data),
+                                                  base::span_from_ref(in));
     seq_lock.WriteEnd();
   }
 };
diff --git a/device/base/synchronization/one_writer_seqlock.h b/device/base/synchronization/one_writer_seqlock.h
index c7ef7fccdd1f2..14249207928e1 100644
--- a/device/base/synchronization/one_writer_seqlock.h
+++ b/device/base/synchronization/one_writer_seqlock.h
@@ -2,10 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifdef UNSAFE_BUFFERS_BUILD
-// TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
-#pragma allow_unsafe_buffers
-#endif
+#include "base/containers/span.h"
+
+
 
 #ifndef DEVICE_BASE_SYNCHRONIZATION_ONE_WRITER_SEQLOCK_H_
 #define DEVICE_BASE_SYNCHRONIZATION_ONE_WRITER_SEQLOCK_H_
@@ -52,11 +51,11 @@ class OneWriterSeqLock {
   // Copies data from src into dest using atomic stores. This should be used by
   // writer of SeqLock. Data must be 4-byte aligned.
   template <typename T>
-  static void AtomicWriterMemcpy(T* dest, const T* src, size_t size);
+  static void AtomicWriterMemcpy(base::span<T> dest, base::span<const T> src);
   // Copies data from src into dest using atomic loads. This should be used by
   // readers of SeqLock. Data must be 4-byte aligned.
   template <typename T>
-  static void AtomicReaderMemcpy(T* dest, const T* src, size_t size);
+  static void AtomicReaderMemcpy(base::span<T> dest, base::span<const T> src);
   // ReadBegin returns |sequence_| when it is even, or when it has retried
   // |max_retries| times. Omitting |max_retries| results in ReadBegin not
   // returning until |sequence_| is even.
@@ -71,33 +70,52 @@ class OneWriterSeqLock {
 
 // static
 template <typename T>
-void OneWriterSeqLock::AtomicReaderMemcpy(T* dest, const T* src, size_t size) {
+void OneWriterSeqLock::AtomicReaderMemcpy(base::span<T> dest,
+                                          base::span<const T> src) {
+  // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be
+  // redundant in M143.
+  CHECK(src.size() == dest.size(), base::NotFatalUntil::M143);
   static_assert(std::is_trivially_copyable<T>::value,
                 "AtomicReaderMemcpy requires a trivially copyable type");
 
-  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(dest) % 4, 0U);
-  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(src) % 4, 0U);
-  DCHECK_EQ(size % 4, 0U);
-  for (size_t i = 0; i < size / 4; ++i) {
-    reinterpret_cast<int32_t*>(dest)[i] =
-        reinterpret_cast<const std::atomic<int32_t>*>(src)[i].load(
-            std::memory_order_relaxed);
-  }
+  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(dest.data()) % 4, 0U);
+  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(src.data()) % 4, 0U);
+  DCHECK_EQ(dest.size_bytes() % 4, 0U);
+  // SAFETY: The caller guarantees that the destination and source buffers are
+  // valid and have the same size. The size is checked to be a multiple of 4.
+  // The pointers are also checked to be 4-byte aligned.
+  UNSAFE_BUFFERS({
+    for (size_t i = 0; i < dest.size_bytes() / 4; ++i) {
+      reinterpret_cast<int32_t*>(dest.data())[i] =
+          reinterpret_cast<const std::atomic<int32_t>*>(src.data())[i].load(
+              std::memory_order_relaxed);
+    }
+  });
 }
 
 // static
 template <typename T>
-void OneWriterSeqLock::AtomicWriterMemcpy(T* dest, const T* src, size_t size) {
+void OneWriterSeqLock::AtomicWriterMemcpy(base::span<T> dest,
+                                          base::span<const T> src) {
+  // TODO(crbug.com/431824301): Remove unneeded parameter once validated to be
+  // redundant in M143.
+  CHECK(src.size() == dest.size(), base::NotFatalUntil::M143);
   static_assert(std::is_trivially_copyable<T>::value,
                 "AtomicWriterMemcpy requires a trivially copyable type");
 
-  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(dest) % 4, 0U);
-  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(src) % 4, 0U);
-  DCHECK_EQ(size % 4, 0U);
-  for (size_t i = 0; i < size / 4; ++i) {
-    reinterpret_cast<std::atomic<int32_t>*>(dest)[i].store(
-        reinterpret_cast<const int32_t*>(src)[i], std::memory_order_relaxed);
-  }
+  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(dest.data()) % 4, 0U);
+  DCHECK_EQ(reinterpret_cast<std::uintptr_t>(src.data()) % 4, 0U);
+  DCHECK_EQ(dest.size_bytes() % 4, 0U);
+  // SAFETY: The caller guarantees that the destination and source buffers are
+  // valid and have the same size. The size is checked to be a multiple of 4.
+  // The pointers are also checked to be 4-byte aligned.
+  UNSAFE_BUFFERS({
+    for (size_t i = 0; i < dest.size_bytes() / 4; ++i) {
+      reinterpret_cast<std::atomic<int32_t>*>(dest.data())[i].store(
+          reinterpret_cast<const int32_t*>(src.data())[i],
+          std::memory_order_relaxed);
+    }
+  });
 }
 
 }  // namespace device
diff --git a/device/base/synchronization/one_writer_seqlock_unittest.cc b/device/base/synchronization/one_writer_seqlock_unittest.cc
index b5eac00749530..c877def88270f 100644
--- a/device/base/synchronization/one_writer_seqlock_unittest.cc
+++ b/device/base/synchronization/one_writer_seqlock_unittest.cc
@@ -49,8 +49,8 @@ class BasicSeqLockTestThread : public base::PlatformThread::Delegate {
       int32_t version;
       do {
         version = seqlock_->ReadBegin();
-        OneWriterSeqLock::AtomicReaderMemcpy(&copy, data_.get(),
-                                             sizeof(TestData));
+        OneWriterSeqLock::AtomicReaderMemcpy<TestData>(
+            base::span_from_ref(copy), base::span_from_ref(*data_));
       } while (seqlock_->ReadRetry(version));
 
       for (unsigned j = 1; j < 32; ++j)
@@ -128,7 +128,8 @@ TEST(OneWriterSeqLockTest, MAYBE_ManyThreads) {
       new_data.buffer[i] = new_data.buffer[0] + new_data.buffer[i - 1];
     }
     seqlock.WriteBegin();
-    OneWriterSeqLock::AtomicWriterMemcpy(&data, &new_data, sizeof(TestData));
+    OneWriterSeqLock::AtomicWriterMemcpy<TestData>(
+        base::span_from_ref(data), base::span_from_ref(new_data));
     seqlock.WriteEnd();
 
     if (counter == 1)
diff --git a/services/device/generic_sensor/platform_sensor.cc b/services/device/generic_sensor/platform_sensor.cc
index d99624a0becc1..b55a04541a609 100644
--- a/services/device/generic_sensor/platform_sensor.cc
+++ b/services/device/generic_sensor/platform_sensor.cc
@@ -183,8 +183,9 @@ void PlatformSensor::ResetSharedBuffer() {
 void PlatformSensor::WriteToSharedBuffer(const SensorReading& reading) {
   CHECK(is_active_);
   reading_buffer_->seqlock.value().WriteBegin();
-  device::OneWriterSeqLock::AtomicWriterMemcpy(&reading_buffer_->reading,
-                                               &reading, sizeof(reading));
+  device::OneWriterSeqLock::AtomicWriterMemcpy<SensorReading>(
+      base::span_from_ref(reading_buffer_->reading),
+      base::span_from_ref(reading));
   reading_buffer_->seqlock.value().WriteEnd();
 }
 
diff --git a/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.cc b/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.cc
index 2442ac71de2f7..d84bfe5ae6502 100644
--- a/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.cc
+++ b/services/device/public/cpp/generic_sensor/sensor_reading_shared_buffer_reader.cc
@@ -58,8 +58,8 @@ bool SensorReadingSharedBufferReader::GetReading(
   int32_t version;
   do {
     version = buffer->seqlock.value().ReadBegin();
-    device::OneWriterSeqLock::AtomicReaderMemcpy(result, &buffer->reading,
-                                                 sizeof(SensorReading));
+    device::OneWriterSeqLock::AtomicReaderMemcpy<SensorReading>(
+        base::span_from_ref(*result), base::span_from_ref(buffer->reading));
   } while (buffer->seqlock.value().ReadRetry(version) &&
            ++retries < kMaxReadAttemptsCount);
 
