the daemon is vulnerable to malicious client, which is able to send
large elen, and corrupt the stack, etc.
* throw at seeing corrupted entity_addr_t where its elen exceeds
the length of sockaddr
* handle the exception thrown when decoding entity_addr_t in messenger
layer.
* if a malicious client manages to send a corrutped entity_addr_t to
daemon, daemon will crash because decode fails and the exception is
not handled. it's better than continuing working with the bogus
message.
Signed-off-by: Kefu Chai <kchai@redhat.com>
}
addr_bl.append(state_buffer+strlen(CEPH_BANNER), sizeof(ceph_entity_addr));
- {
+ try {
bufferlist::iterator ti = addr_bl.begin();
::decode(peer_addr, ti);
- }
+ } catch (const buffer::error& e) {
+ lderr(async_msgr->cct) << __func__ << " decode peer_addr failed " << dendl;
+ goto fail;
+ }
ldout(async_msgr->cct, 10) << __func__ << " accept peer addr is " << peer_addr << dendl;
if (peer_addr.is_blank_ip()) {
__u32 elen;
::decode(elen, bl);
if (elen) {
- bl.copy(elen, (char*)get_sockaddr());
+ if (elen < sizeof(u.sa.sa_family)) {
+ throw buffer::malformed_input("elen smaller than family len");
+ }
+ bl.copy(sizeof(u.sa.sa_family), (char*)&u.sa.sa_family);
+ if (elen > get_sockaddr_len()) {
+ throw buffer::malformed_input("elen exceeds sockaddr len");
+ }
+ elen -= sizeof(u.sa.sa_family);
+ bl.copy(elen, u.sa.sa_data);
}
DECODE_FINISH(bl);
}
ldout(msgr->cct,10) << "accept couldn't read peer_addr" << dendl;
goto fail_unlocked;
}
- {
+ try {
bufferlist::iterator ti = addrbl.begin();
::decode(peer_addr, ti);
+ } catch (const buffer::error& e) {
+ ldout(msgr->cct,2) << __func__ << " decode peer_addr failed: " << e.what()
+ << dendl;
+ goto fail_unlocked;
}
ldout(msgr->cct,10) << "accept peer addr is " << peer_addr << dendl;