]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
librados: cap the rados*{write,append} buffer length 2584/head
authorLoic Dachary <loic-201408@dachary.org>
Sat, 27 Sep 2014 08:37:07 +0000 (10:37 +0200)
committerLoic Dachary <loic-201408@dachary.org>
Sat, 27 Sep 2014 08:48:01 +0000 (10:48 +0200)
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 <loic-201408@dachary.org>
src/include/rados/librados.h
src/librados/librados.cc
src/test/librados/io.cc

index 3c90ca4a305d637c241e413e7513ecf104e7951c..6ed12c2f9189f0e9d3c8933cee018d5a28adf98c 100644 (file)
@@ -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
index 45bde1a0b69d0c77a59ef6199f6f8f620073a83c..835e7a137cc4d21cec050b7e86d40cffcc24b752 100644 (file)
@@ -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;
index 0cfa91e4b8468fdef95c5b2bfe63f50a0b857dad..3005000b2f0895089ceca76885af3f3b314600c0 100644 (file)
@@ -1,6 +1,8 @@
 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*
 // vim: ts=8 sw=2 smarttab
 
+#include <climits>
+
 #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));