From 5d1d9dba60bf9752e9de6351b8d92c32abbc14c9 Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Mon, 29 Sep 2014 00:39:50 +0200 Subject: [PATCH] librados: cap the IoCtxImpl::{aio_}*{write,append} buffer length If the value of the len parameter is greater than UINT_MAX/2, IoCtxImpl::aio_write, IoCtxImpl::aio_write_full, IoCtxImpl::aio_append, IoCtxImpl::write, IoCtxImpl::append will fail with E2BIG. IoCtxImpl::write_full is the exception because it does not have a length argument to check. For more information see 33501d242661a545211df43bf645398b492398ae http://tracker.ceph.com/issues/9592 Fixes: #9592 Signed-off-by: Loic Dachary --- src/librados/IoCtxImpl.cc | 10 ++++++++++ src/test/librados/aio.cc | 12 ++++++++++++ src/test/librados/io.cc | 5 +++++ 3 files changed, 27 insertions(+) diff --git a/src/librados/IoCtxImpl.cc b/src/librados/IoCtxImpl.cc index aadd04fe6fd..47835b77731 100644 --- a/src/librados/IoCtxImpl.cc +++ b/src/librados/IoCtxImpl.cc @@ -408,6 +408,8 @@ int librados::IoCtxImpl::create(const object_t& oid, bool exclusive, int librados::IoCtxImpl::write(const object_t& oid, bufferlist& bl, size_t len, uint64_t off) { + if (len > UINT_MAX/2) + return -E2BIG; ::ObjectOperation op; prepare_assert_ops(&op); bufferlist mybl; @@ -418,6 +420,8 @@ int librados::IoCtxImpl::write(const object_t& oid, bufferlist& bl, int librados::IoCtxImpl::append(const object_t& oid, bufferlist& bl, size_t len) { + if (len > UINT_MAX/2) + return -E2BIG; ::ObjectOperation op; prepare_assert_ops(&op); bufferlist mybl; @@ -646,6 +650,8 @@ int librados::IoCtxImpl::aio_write(const object_t &oid, AioCompletionImpl *c, utime_t ut = ceph_clock_now(client->cct); ldout(client->cct, 20) << "aio_write " << oid << " " << off << "~" << len << " snapc=" << snapc << " snap_seq=" << snap_seq << dendl; + if (len > UINT_MAX/2) + return -E2BIG; /* can't write to a snapshot */ if (snap_seq != CEPH_NOSNAP) return -EROFS; @@ -668,6 +674,8 @@ int librados::IoCtxImpl::aio_append(const object_t &oid, AioCompletionImpl *c, { utime_t ut = ceph_clock_now(client->cct); + if (len > UINT_MAX/2) + return -E2BIG; /* can't write to a snapshot */ if (snap_seq != CEPH_NOSNAP) return -EROFS; @@ -691,6 +699,8 @@ int librados::IoCtxImpl::aio_write_full(const object_t &oid, { utime_t ut = ceph_clock_now(client->cct); + if (bl.length() > UINT_MAX/2) + return -E2BIG; /* can't write to a snapshot */ if (snap_seq != CEPH_NOSNAP) return -EROFS; diff --git a/src/test/librados/aio.cc b/src/test/librados/aio.cc index 92ffa11e6af..79987299f99 100644 --- a/src/test/librados/aio.cc +++ b/src/test/librados/aio.cc @@ -177,6 +177,18 @@ TEST(LibRadosAio, TooBig) { my_completion, buf, UINT_MAX)); } +TEST(LibRadosAio, TooBigPP) { + AioTestDataPP test_data; + ASSERT_EQ("", test_data.init()); + + bufferlist bl; + AioCompletion *aio_completion = test_data.m_cluster.aio_create_completion( + (void*)&test_data, NULL, NULL); + ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_write("foo", aio_completion, bl, UINT_MAX, 0)); + ASSERT_EQ(-E2BIG, test_data.m_ioctx.aio_append("foo", aio_completion, bl, UINT_MAX)); + // ioctx.aio_write_full no way to overflow bl.length() +} + TEST(LibRadosAio, SimpleWrite) { AioTestData test_data; rados_completion_t my_completion; diff --git a/src/test/librados/io.cc b/src/test/librados/io.cc index df6e418c518..8bada67c52d 100644 --- a/src/test/librados/io.cc +++ b/src/test/librados/io.cc @@ -32,6 +32,11 @@ TEST_F(LibRadosIo, TooBig) { ASSERT_EQ(-E2BIG, rados_write(ioctx, "A", buf, UINT_MAX, 0)); ASSERT_EQ(-E2BIG, rados_append(ioctx, "A", buf, UINT_MAX)); ASSERT_EQ(-E2BIG, rados_write_full(ioctx, "A", buf, UINT_MAX)); + IoCtx ioctx; + bufferlist bl; + ASSERT_EQ(-E2BIG, ioctx.write("foo", bl, UINT_MAX, 0)); + ASSERT_EQ(-E2BIG, ioctx.append("foo", bl, UINT_MAX)); + // ioctx.write_full no way to overflow bl.length() } TEST_F(LibRadosIo, ReadTimeout) {