[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
(ITS#6215) liblber problems
Full_Name: Hallvard B Furuseth
Version:
OS:
URL:
Submission from: (NULL) (129.240.6.233)
Submitted by: hallvard
Given these declarations:
#include <lber.h>
#define LBER_EXBUFSIZ 4060 /* from liblber/io.c */
static char data[8000];
struct berval bv;
BerElement *ber;
Buffer overrun i ber_flatten(,,0):
ber = der_alloc();
ber_printf(ber, "o", data, LBER_EXBUFSIZ - 4);
ber_flatten2(ber, &bv, 0);
ber_flatten2(,,0) \0-terminates the Ber buffer, but does not grow it first
at need. Simplest fix is to allocate an extra byte in ber_realloc(), and
reduce LBER_EXBUFSIZ by 1 to compensate. I don't know how kosher it is to
write into the ber buffer in the first place though.
Coredump - write through NULL pointer:
ber_flatten2(der_alloc(), &bv, 0);
A fresh Ber has no buffers yet, the buffer pointers are NULL.
\0-terminating a NULL pointer doesn't work too well. Don't know if
it should be called a bug though, since ber_flatten2() doesn't work
right on an incomplete Ber element either (due to seqorset stuff).
The NULL pointers in a fresh ber also mean ber_write, ber_len()
& co do pointer arithmetic on NULL pointers, which is not valid.
Oh well, it seems to work on most machines.
Buffer overrun in ber_write():
ber = der_alloc();
ber_printf(ber, "{");
ber_write(ber, data, 6000, 0);
ber_write() needs buffer space and calls ber_realloc(ber, 6000).
However "{" has moved ber->ber_sos->sos_ptr (the write destination)
6 bytes beyond ber->ber_end, so 6006 bytes are actually needed.
ber_realloc() does not know that, and allocates 6000 bytes.
It cannot happen with ber_write() called from liblber: Next liblber
write after "{" will be just a few bytes with the next element's tag.
ber_realloc() always allocates 4060 bytes or more - moving sos_ptr
beyond ber_end again.
This can only happen if a caller outside liblber generates a complete
"tag, length, contents" element >= 4060 bytes and ber_write()s it in one
operation. There are ber_write()s in libldap and slapd/connection.c,
but haven't checked if any are at risk.
Don't know where to fix it:
- in ber_realloc(), most techinically correct.
- in ber_write() - simpler since it already knows about sos_ptr.
- in ber_start_seqorset() - always alloc a buffer, never point
beyond allocated data. Cleanest but most space-costly.