From 33501d242661a545211df43bf645398b492398ae Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Sat, 27 Sep 2014 10:37:07 +0200 Subject: [PATCH] librados: cap the rados*{write,append} buffer length When the caller submits a payload that will end up being rejected with rados.Error: Ioctx.write(rbd): failed to write hw: errno EMSGSIZE it is stored in a bufferlist whose length is an unsigned int. If the value of the len parameter is greater than UINT_MAX/2, rados_write, rados_write_full and rados_append will fail with E2BIG. Multiple calls to rados_write or rados_append can fill objects larger than UINT_MAX/2. http://tracker.ceph.com/issues/9592 Fixes: #9592 Signed-off-by: Loic Dachary --- src/include/rados/librados.h | 9 ++++++--- src/librados/librados.cc | 6 ++++++ src/test/librados/io.cc | 9 +++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/include/rados/librados.h b/src/include/rados/librados.h index 3c90ca4a305d6..6ed12c2f9189f 100644 --- a/src/include/rados/librados.h +++ b/src/include/rados/librados.h @@ -1070,7 +1070,8 @@ int rados_ioctx_snap_get_stamp(rados_ioctx_t io, rados_snap_t id, time_t *t); uint64_t rados_get_last_version(rados_ioctx_t io); /** - * Write data to an object + * Write *len* bytes from *buf* into the *oid* object, starting at + * offset *off*. The value of *len* must be <= UINT_MAX/2. * * @note This will never return a positive value not equal to len. * @param io the io context in which the write will occur @@ -1083,7 +1084,8 @@ uint64_t rados_get_last_version(rados_ioctx_t io); int rados_write(rados_ioctx_t io, const char *oid, const char *buf, size_t len, uint64_t off); /** - * Write an entire object + * Write *len* bytes from *buf* into the *oid* object. The value of + * *len* must be <= UINT_MAX/2. * * The object is filled with the provided data. If the object exists, * it is atomically truncated and then written. @@ -1118,7 +1120,8 @@ int rados_clone_range(rados_ioctx_t io, const char *dst, uint64_t dst_off, const char *src, uint64_t src_off, size_t len); /** - * Append data to an object + * Append *len* bytes from *buf* into the *oid* object. The value of + * *len* must be <= UINT_MAX/2. * * @param io the context to operate in * @param oid the name of the object diff --git a/src/librados/librados.cc b/src/librados/librados.cc index 45bde1a0b69d0..835e7a137cc4d 100644 --- a/src/librados/librados.cc +++ b/src/librados/librados.cc @@ -2463,6 +2463,8 @@ extern "C" int rados_ioctx_selfmanaged_snap_set_write_ctx(rados_ioctx_t io, extern "C" int rados_write(rados_ioctx_t io, const char *o, const char *buf, size_t len, uint64_t off) { tracepoint(librados, rados_write_enter, io, o, buf, len, off); + if (len > UINT_MAX/2) + return -E2BIG; librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io; object_t oid(o); bufferlist bl; @@ -2475,6 +2477,8 @@ extern "C" int rados_write(rados_ioctx_t io, const char *o, const char *buf, siz extern "C" int rados_append(rados_ioctx_t io, const char *o, const char *buf, size_t len) { tracepoint(librados, rados_append_enter, io, o, buf, len); + if (len > UINT_MAX/2) + return -E2BIG; librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io; object_t oid(o); bufferlist bl; @@ -2487,6 +2491,8 @@ extern "C" int rados_append(rados_ioctx_t io, const char *o, const char *buf, si extern "C" int rados_write_full(rados_ioctx_t io, const char *o, const char *buf, size_t len) { tracepoint(librados, rados_write_full_enter, io, o, buf, len); + if (len > UINT_MAX/2) + return -E2BIG; librados::IoCtxImpl *ctx = (librados::IoCtxImpl *)io; object_t oid(o); bufferlist bl; diff --git a/src/test/librados/io.cc b/src/test/librados/io.cc index 0cfa91e4b8468..3005000b2f089 100644 --- a/src/test/librados/io.cc +++ b/src/test/librados/io.cc @@ -1,6 +1,8 @@ // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -* // vim: ts=8 sw=2 smarttab +#include + #include "include/rados/librados.h" #include "include/rados/librados.hpp" #include "test/librados/test.h" @@ -25,6 +27,13 @@ TEST_F(LibRadosIo, SimpleWrite) { ASSERT_EQ(0, rados_write(ioctx, "foo", buf, sizeof(buf), 0)); } +TEST_F(LibRadosIo, E2BIG) { + char buf[1]; + 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)); +} + TEST_F(LibRadosIo, ReadTimeout) { char buf[128]; memset(buf, 'a', sizeof(buf)); -- 2.39.5