diff --git a/doc/source/whatsnew/v0.24.2.rst b/doc/source/whatsnew/v0.24.2.rst
index f864fcd04e3d4..283f12361841c 100644
--- a/doc/source/whatsnew/v0.24.2.rst
+++ b/doc/source/whatsnew/v0.24.2.rst
@@ -29,6 +29,7 @@ Fixed Regressions
 - Fixed regression in subtraction between :class:`Series` objects with ``datetime64[ns]`` dtype incorrectly raising ``OverflowError`` when the ``Series`` on the right contains null values (:issue:`25317`)
 - Fixed regression in :class:`TimedeltaIndex` where ``np.sum(index)`` incorrectly returned a zero-dimensional object instead of a scalar (:issue:`25282`)
 - Fixed regression in ``IntervalDtype`` construction where passing an incorrect string with 'Interval' as a prefix could result in a ``RecursionError``. (:issue:`25338`)
+- Fixed regression in creating a period-dtype array from a read-only NumPy array of period objects. (:issue:`25403`)
 - Fixed regression in :class:`Categorical`, where constructing it from a categorical ``Series`` and an explicit ``categories=`` that differed from that in the ``Series`` created an invalid object which could trigger segfaults. (:issue:`25318`)
 
 .. _whatsnew_0242.enhancements:
diff --git a/pandas/_libs/tslibs/period.pyx b/pandas/_libs/tslibs/period.pyx
index a5a50ea59753d..c8eaa2cfd85c2 100644
--- a/pandas/_libs/tslibs/period.pyx
+++ b/pandas/_libs/tslibs/period.pyx
@@ -1438,7 +1438,9 @@ cdef accessor _get_accessor_func(int code):
 
 @cython.wraparound(False)
 @cython.boundscheck(False)
-def extract_ordinals(object[:] values, freq):
+def extract_ordinals(ndarray[object] values, freq):
+    # TODO: Change type to const object[:] when Cython supports that.
+
     cdef:
         Py_ssize_t i, n = len(values)
         int64_t[:] ordinals = np.empty(n, dtype=np.int64)
@@ -1472,7 +1474,9 @@ def extract_ordinals(object[:] values, freq):
     return ordinals.base  # .base to access underlying np.ndarray
 
 
-def extract_freq(object[:] values):
+def extract_freq(ndarray[object] values):
+    # TODO: Change type to const object[:] when Cython supports that.
+
     cdef:
         Py_ssize_t i, n = len(values)
         object p
diff --git a/pandas/tests/arrays/test_period.py b/pandas/tests/arrays/test_period.py
index affe3b3854490..99255d819d28e 100644
--- a/pandas/tests/arrays/test_period.py
+++ b/pandas/tests/arrays/test_period.py
@@ -41,6 +41,22 @@ def test_period_array_ok(data, freq, expected):
     tm.assert_numpy_array_equal(result, expected)
 
 
+def test_period_array_readonly_object():
+    # https://github.com/pandas-dev/pandas/issues/25403
+    pa = period_array([pd.Period('2019-01-01')])
+    arr = np.asarray(pa, dtype='object')
+    arr.setflags(write=False)
+
+    result = period_array(arr)
+    tm.assert_period_array_equal(result, pa)
+
+    result = pd.Series(arr)
+    tm.assert_series_equal(result, pd.Series(pa))
+
+    result = pd.DataFrame({"A": arr})
+    tm.assert_frame_equal(result, pd.DataFrame({"A": pa}))
+
+
 def test_from_datetime64_freq_changes():
     # https://github.com/pandas-dev/pandas/issues/23438
     arr = pd.date_range("2017", periods=3, freq="D")