A fix to prevent a potential buffer overrun in the messenger, marked

for stable.
 -----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCAAxFiEEydHwtzie9C7TfviiSn/eOAIR84sFAmSxZc4THGlkcnlvbW92
 QGdtYWlsLmNvbQAKCRBKf944AhHzi2bBB/9y4X7jwmrdPLritmVIZR/m2C3AKRk6
 w4EI5w3zcwisdYhb8DDS5iufLI+M0d7ztVKU7GQMzfgX6Up59DSD+2r4BrDzZWCK
 Y6bggpHNHQ+ALxrpvieBXU/D8FtGGL0M1+uuU84Qkd3sWMFbG8BM5kKhrPHG2thE
 G4OZrubAL9fDBjrsoQI+9w5wZT75OUAh51hoz3HCCJA5KP+tTTekMADL4Hh90Nuj
 rfy8a+97FLayPBnNxNzsu/BKCFflGX5c6cI47PIl96HOXu9QCFoQh6dp/s5FHiYw
 alosIoU4VubUJDIRK6kovUurdaytha7Sj/EyF/epiRmH2DUWr4eU3ULM
 =f7z1
 -----END PGP SIGNATURE-----

Merge tag 'ceph-for-6.5-rc2' of https://github.com/ceph/ceph-client

Pull ceph fix from Ilya Dryomov:
 "A fix to prevent a potential buffer overrun in the messenger, marked
  for stable"

* tag 'ceph-for-6.5-rc2' of https://github.com/ceph/ceph-client:
  libceph: harden msgr2.1 frame segment length checks
This commit is contained in:
Linus Torvalds 2023-07-14 09:05:15 -07:00
commit ddbd91617f

View File

@ -390,6 +390,8 @@ static int head_onwire_len(int ctrl_len, bool secure)
int head_len; int head_len;
int rem_len; int rem_len;
BUG_ON(ctrl_len < 0 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN);
if (secure) { if (secure) {
head_len = CEPH_PREAMBLE_SECURE_LEN; head_len = CEPH_PREAMBLE_SECURE_LEN;
if (ctrl_len > CEPH_PREAMBLE_INLINE_LEN) { if (ctrl_len > CEPH_PREAMBLE_INLINE_LEN) {
@ -408,6 +410,10 @@ static int head_onwire_len(int ctrl_len, bool secure)
static int __tail_onwire_len(int front_len, int middle_len, int data_len, static int __tail_onwire_len(int front_len, int middle_len, int data_len,
bool secure) bool secure)
{ {
BUG_ON(front_len < 0 || front_len > CEPH_MSG_MAX_FRONT_LEN ||
middle_len < 0 || middle_len > CEPH_MSG_MAX_MIDDLE_LEN ||
data_len < 0 || data_len > CEPH_MSG_MAX_DATA_LEN);
if (!front_len && !middle_len && !data_len) if (!front_len && !middle_len && !data_len)
return 0; return 0;
@ -520,29 +526,34 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc)
desc->fd_aligns[i] = ceph_decode_16(&p); desc->fd_aligns[i] = ceph_decode_16(&p);
} }
if (desc->fd_lens[0] < 0 ||
desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) {
pr_err("bad control segment length %d\n", desc->fd_lens[0]);
return -EINVAL;
}
if (desc->fd_lens[1] < 0 ||
desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) {
pr_err("bad front segment length %d\n", desc->fd_lens[1]);
return -EINVAL;
}
if (desc->fd_lens[2] < 0 ||
desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) {
pr_err("bad middle segment length %d\n", desc->fd_lens[2]);
return -EINVAL;
}
if (desc->fd_lens[3] < 0 ||
desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) {
pr_err("bad data segment length %d\n", desc->fd_lens[3]);
return -EINVAL;
}
/* /*
* This would fire for FRAME_TAG_WAIT (it has one empty * This would fire for FRAME_TAG_WAIT (it has one empty
* segment), but we should never get it as client. * segment), but we should never get it as client.
*/ */
if (!desc->fd_lens[desc->fd_seg_cnt - 1]) { if (!desc->fd_lens[desc->fd_seg_cnt - 1]) {
pr_err("last segment empty\n"); pr_err("last segment empty, segment count %d\n",
return -EINVAL; desc->fd_seg_cnt);
}
if (desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) {
pr_err("control segment too big %d\n", desc->fd_lens[0]);
return -EINVAL;
}
if (desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) {
pr_err("front segment too big %d\n", desc->fd_lens[1]);
return -EINVAL;
}
if (desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) {
pr_err("middle segment too big %d\n", desc->fd_lens[2]);
return -EINVAL;
}
if (desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) {
pr_err("data segment too big %d\n", desc->fd_lens[3]);
return -EINVAL; return -EINVAL;
} }