Bug #20240
closedlibradosstriper processes arbitrary printf placeholders in user input
0%
Description
I've discovered an issue with libradosstriper. It seems it's
processing the printf formatting placeholders in the objects name (soid),
which can lead to broken striped objects.
For example:
test ~# echo 123 > test # Capturing striper segment suffix prematurely: test ~# rados -p sata --striper put "testme%016llx_TEST" test # Now pool contains an object with a valid striped segment name, # and some garbage object test ~# rados -p sata ls testme%016llx_TEST.0000000000000000 testme0000000000000000_TEST.3030656d74736574 # All data is in the garbage object, but xattrs on valid one test ~# rados -p sata stat testme%016llx_TEST.0000000000000000 sata/testme%016llx_TEST.0000000000000000 mtime 2017-06-06 02:56:06.000000, size 0 test ~# rados -p sata stat testme0000000000000000_TEST.3030656d74736574 sata/testme0000000000000000_TEST.3030656d74736574 mtime 2017-06-06 02:56:06.000000, size 4 test ~# rados -p sata listxattr testme0000000000000000_TEST.3030656d74736574 (empty output) test ~# rados -p sata listxattr testme%016llx_TEST.0000000000000000 lock.striper.lock striper.layout.object_size striper.layout.stripe_count striper.layout.stripe_unit striper.size
Also it can crash the whole program which is linked to libradosstriper by using '%n' in the soid:
test ~# rados -p sata --striper put "testme%n" test *** %n in writable segment detected *** *** Caught signal (Aborted) ** in thread 7f8a59d40a40 thread_name:rados ceph version 10.2.5 (c461ee19ecbc0c5c330aca20f7392c9a00730367) 1: (()+0x47a72) [0x7f8a59b49a72] 2: (()+0x10330) [0x7f8a466bd330] 3: (gsignal()+0x37) [0x7f8a458fac37] 4: (abort()+0x148) [0x7f8a458fe028] 5: (()+0x732a4) [0x7f8a459372a4] 6: (__libc_fatal()+0x1e) [0x7f8a459372ce] 7: (_IO_vfprintf()+0x1e00) [0x7f8a4590fa40] 8: (__vsnprintf_chk()+0x95) [0x7f8a459cd165] 9: (__snprintf_chk()+0x78) [0x7f8a459cd0c8] 10: (Striper::file_to_extents(CephContext*, char const*, file_layout_t const*, unsigned long, unsigned long, unsigned long, std::map<object_t, std::vector<ObjectExtent, std::allocator<ObjectExtent> >, std::less<object_t>, std::allocator<std::pair<object_t const, std::vector<ObjectExtent, std::allocator<ObjectExtent> > > > >&, unsigned long)+0x341) [0x7f8a46b427d1] 11: (Striper::file_to_extents(CephContext*, char const*, file_layout_t const*, unsigned long, unsigned long, unsigned long, std::vector<ObjectExtent, std::allocator<ObjectExtent> >&, unsigned long)+0x46) [0x7f8a46b450d6] 12: (libradosstriper::RadosStriperImpl::internal_aio_write(std::string const&, libradosstriper::MultiAioCompletionImpl*, ceph::buffer::list const&, unsigned long, unsigned long, ceph_file_layout const&)+0x117) [0x7f8a46ab1687] 13: (libradosstriper::RadosStriperImpl::write_in_open_object(std::string const&, ceph_file_layout const&, std::string const&, ceph::buffer::list const&, unsigned long, unsigned long)+0xac) [0x7f8a46ab1a8c] 14: (libradosstriper::RadosStriperImpl::write(std::string const&, ceph::buffer::list const&, unsigned long, unsigned long)+0x6f) [0x7f8a46ab64af] 15: (main()+0x6911) [0x7f8a59b1adc1] 16: (__libc_start_main()+0xf5) [0x7f8a458e5f45] 17: (()+0x23597) [0x7f8a59b25597] 2017-06-06 03:10:36.766597 7f8a59d40a40 -1 *** Caught signal (Aborted) ** in thread 7f8a59d40a40 thread_name:rados ceph version 10.2.5 (c461ee19ecbc0c5c330aca20f7392c9a00730367) 1: (()+0x47a72) [0x7f8a59b49a72] 2: (()+0x10330) [0x7f8a466bd330] 3: (gsignal()+0x37) [0x7f8a458fac37] 4: (abort()+0x148) [0x7f8a458fe028] 5: (()+0x732a4) [0x7f8a459372a4] 6: (__libc_fatal()+0x1e) [0x7f8a459372ce] 7: (_IO_vfprintf()+0x1e00) [0x7f8a4590fa40] 8: (__vsnprintf_chk()+0x95) [0x7f8a459cd165] 9: (__snprintf_chk()+0x78) [0x7f8a459cd0c8] 10: (Striper::file_to_extents(CephContext*, char const*, file_layout_t const*, unsigned long, unsigned long, unsigned long, std::map<object_t, std::vector<ObjectExtent, std::allocator<ObjectExtent> >, std::less<object_t>, std::allocator<std::pair<object_t const, std::vector<ObjectExtent, std::allocator<ObjectExtent> > > > >&, unsigned long)+0x341) [0x7f8a46b427d1] 11: (Striper::file_to_extents(CephContext*, char const*, file_layout_t const*, unsigned long, unsigned long, unsigned long, std::vector<ObjectExtent, std::allocator<ObjectExtent> >&, unsigned long)+0x46) [0x7f8a46b450d6] 12: (libradosstriper::RadosStriperImpl::internal_aio_write(std::string const&, libradosstriper::MultiAioCompletionImpl*, ceph::buffer::list const&, unsigned long, unsigned long, ceph_file_layout const&)+0x117) [0x7f8a46ab1687] 13: (libradosstriper::RadosStriperImpl::write_in_open_object(std::string const&, ceph_file_layout const&, std::string const&, ceph::buffer::list const&, unsigned long, unsigned long)+0xac) [0x7f8a46ab1a8c] 14: (libradosstriper::RadosStriperImpl::write(std::string const&, ceph::buffer::list const&, unsigned long, unsigned long)+0x6f) [0x7f8a46ab64af] 15: (main()+0x6911) [0x7f8a59b1adc1] 16: (__libc_start_main()+0xf5) [0x7f8a458e5f45] 17: (()+0x23597) [0x7f8a59b25597] NOTE: a copy of the executable, or `objdump -rdS <executable>` is needed to interpret this. --- begin dump of recent events --- -14> 2017-06-06 03:10:36.707505 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command perfcounters_dump hook 0x7f8a59f1a2a0 -13> 2017-06-06 03:10:36.707542 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command 1 hook 0x7f8a59f1a2a0 -12> 2017-06-06 03:10:36.707554 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command perf dump hook 0x7f8a59f1a2a0 -11> 2017-06-06 03:10:36.707558 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command perfcounters_schema hook 0x7f8a59f1a2a0 -10> 2017-06-06 03:10:36.707563 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command 2 hook 0x7f8a59f1a2a0 -9> 2017-06-06 03:10:36.707566 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command perf schema hook 0x7f8a59f1a2a0 -8> 2017-06-06 03:10:36.707570 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command perf reset hook 0x7f8a59f1a2a0 -7> 2017-06-06 03:10:36.707592 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command config show hook 0x7f8a59f1a2a0 -6> 2017-06-06 03:10:36.707599 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command config set hook 0x7f8a59f1a2a0 -5> 2017-06-06 03:10:36.707610 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command config get hook 0x7f8a59f1a2a0 -4> 2017-06-06 03:10:36.707613 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command config diff hook 0x7f8a59f1a2a0 -3> 2017-06-06 03:10:36.707616 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command log flush hook 0x7f8a59f1a2a0 -2> 2017-06-06 03:10:36.707619 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command log dump hook 0x7f8a59f1a2a0 -1> 2017-06-06 03:10:36.707623 7f8a59d40a40 5 asok(0x7f8a59f16f90) register_command log reopen hook 0x7f8a59f1a2a0 0> 2017-06-06 03:10:36.766597 7f8a59d40a40 -1 *** Caught signal (Aborted) ** in thread 7f8a59d40a40 thread_name:rados ceph version 10.2.5 (c461ee19ecbc0c5c330aca20f7392c9a00730367) 1: (()+0x47a72) [0x7f8a59b49a72] 2: (()+0x10330) [0x7f8a466bd330] 3: (gsignal()+0x37) [0x7f8a458fac37] 4: (abort()+0x148) [0x7f8a458fe028] 5: (()+0x732a4) [0x7f8a459372a4] 6: (__libc_fatal()+0x1e) [0x7f8a459372ce] 7: (_IO_vfprintf()+0x1e00) [0x7f8a4590fa40] 8: (__vsnprintf_chk()+0x95) [0x7f8a459cd165] 9: (__snprintf_chk()+0x78) [0x7f8a459cd0c8] 10: (Striper::file_to_extents(CephContext*, char const*, file_layout_t const*, unsigned long, unsigned long, unsigned long, std::map<object_t, std::vector<ObjectExtent, std::allocator<ObjectExtent> >, std::less<object_t>, std::allocator<std::pair<object_t const, std::vector<ObjectExtent, std::allocator<ObjectExtent> > > > >&, unsigned long)+0x341) [0x7f8a46b427d1] 11: (Striper::file_to_extents(CephContext*, char const*, file_layout_t const*, unsigned long, unsigned long, unsigned long, std::vector<ObjectExtent, std::allocator<ObjectExtent> >&, unsigned long)+0x46) [0x7f8a46b450d6] 12: (libradosstriper::RadosStriperImpl::internal_aio_write(std::string const&, libradosstriper::MultiAioCompletionImpl*, ceph::buffer::list const&, unsigned long, unsigned long, ceph_file_layout const&)+0x117) [0x7f8a46ab1687] 13: (libradosstriper::RadosStriperImpl::write_in_open_object(std::string const&, ceph_file_layout const&, std::string const&, ceph::buffer::list const&, unsigned long, unsigned long)+0xac) [0x7f8a46ab1a8c] 14: (libradosstriper::RadosStriperImpl::write(std::string const&, ceph::buffer::list const&, unsigned long, unsigned long)+0x6f) [0x7f8a46ab64af] 15: (main()+0x6911) [0x7f8a59b1adc1] 16: (__libc_start_main()+0xf5) [0x7f8a458e5f45] 17: (()+0x23597) [0x7f8a59b25597] NOTE: a copy of the executable, or `objdump -rdS <executable>` is needed to interpret this. --- logging levels --- 0/ 0 none 0/ 0 lockdep 0/ 0 context 0/ 0 crush 0/ 0 mds 0/ 0 mds_balancer 0/ 0 mds_locker 0/ 0 mds_log 0/ 0 mds_log_expire 0/ 0 mds_migrator 0/ 0 buffer 0/ 0 timer 0/ 0 filer 0/ 0 striper 0/ 0 objecter 0/ 0 rados 0/ 0 rbd 0/ 5 rbd_mirror 0/ 0 rbd_replay 0/ 0 journaler 0/ 0 objectcacher 0/ 0 client 0/ 0 osd 0/ 0 optracker 0/ 0 objclass 0/ 0 filestore 0/ 0 journal 0/ 0 ms 0/ 0 mon 0/ 0 monc 0/ 0 paxos 0/ 0 tp 0/ 0 auth 0/ 0 crypto 0/ 0 finisher 0/ 0 heartbeatmap 0/ 0 perfcounter 0/ 0 rgw 1/10 civetweb 1/ 5 javaclient 0/ 0 asok 0/ 0 throttle 0/ 0 refs 1/ 5 xio 1/ 5 compressor 1/ 5 newstore 1/ 5 bluestore 1/ 5 bluefs 1/ 3 bdev 1/ 5 kstore 4/ 5 rocksdb 4/ 5 leveldb 1/ 5 kinetic 1/ 5 fuse -2/-2 (syslog threshold) 99/99 (stderr threshold) max_recent 500 max_new 1000 log_file --- end dump of recent events --- Aborted
As far as I discovered "rados_striper_write()" and "rados_striper_read()"
functions are affected, "rados_striper_trunc()" and "rados_striper_remove()"
are not.
It seems that format processing happens in snprintf() in the
"Striper::file_to_extents()", which creates a stripe name. This function
is used in client interfaces, including librbd and libradosstriper.
libradosstriper needs to escape formatable sequences in user input
before calling "file_to_extents()". This change has been introduced in the
attached patch.
Additional review of the the code which uses "Striper::file_to_extents()" would be appropriate.
Files