Project

General

Profile

Bug #20240

libradosstriper processes arbitrary printf placeholders in user input

Added by Stan K 4 months ago. Updated about 1 month ago.

Status:
Resolved
Priority:
Normal
Category:
libradosstriper
Target version:
-
Start date:
06/09/2017
Due date:
% Done:

0%

Source:
Tags:
Backport:
jewel
Regression:
No
Severity:
3 - minor
Reviewed:
Affected Versions:
ceph-qa-suite:
Release:
Needs Doc:
No

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.

libradosstriper_format.patch View (1.34 KB) Stan K, 06/09/2017 04:20 PM


Related issues

Copied to Ceph - Backport #21297: jewel: libradosstriper processes arbitrary printf placeholders in user input Resolved

History

#1 Updated by Stan K 4 months ago

Red Hat has assigned CVE ID CVE-2017-7519 to this issue.

#2 Updated by Greg Farnum 4 months ago

  • Category set to libradosstriper
  • Status changed from New to Need Review

#3 Updated by Jesse Williamson 4 months ago

  • Assignee set to Jesse Williamson

Stan, your patch is applied here:
https://github.com/ceph/ceph/pull/15674

...I'm looking for other places this might occur.

Thank you!

#4 Updated by Jesse Williamson 4 months ago

@Stan K, I'll need to your email address to sign you off as the author of the patch, assuming that you've given me permission to use that code.

#5 Updated by Stan K 4 months ago

@Jesse Williamson, yes, of course you have my permission to use this code.
My email is .

#6 Updated by Kefu Chai 3 months ago

  • Status changed from Need Review to Resolved

#7 Updated by Nathan Cutler 2 months ago

  • Status changed from Resolved to Pending Upstream
  • Backport set to jewel

#8 Updated by Nathan Cutler about 1 month ago

  • Status changed from Pending Upstream to Pending Backport

#9 Updated by Nathan Cutler about 1 month ago

  • Copied to Backport #21297: jewel: libradosstriper processes arbitrary printf placeholders in user input added

#10 Updated by Nathan Cutler about 1 month ago

  • Status changed from Pending Backport to Resolved

Also available in: Atom PDF