Обсуждение: Out-of-bounds write and incorrect detection of trigger file in pg_standby
Hi all,
In pg_standby.c, we use a 32-byte buffer in CheckForExternalTrigger to
which is read the content of the trigger file defined by -f:
CheckForExternalTrigger(void)
{
char buf[32];
[...]
if ((len = read(fd, buf, sizeof(buf))) < 0)
{
stuff();
}
if (len < sizeof(buf))
buf[len] = '\0';
However it happens that if the file read contains 32 bytes or more, we
enforce \0 in a position out of bounds. While looking at that, I also
noticed that pg_standby can trigger a failover as long as the
beginning of buf matches either "smart" or "fast", but I think we
should check for a perfect match instead of a comparison of the first
bytes, no?
Attached is a patch to fix the out-of-bound issue as well as
improvements for the detection of the trigger file content. I think
that the out-of-bound fix should be backpatched, while the
improvements for the trigger file are master-only. Coverity has
pointed out the out-of-bound issue.
Regards,
--
Michael
Вложения
On Wed, Jan 14, 2015 at 8:24 AM, Michael Paquier
<michael.paquier@gmail.com> wrote:
> In pg_standby.c, we use a 32-byte buffer in CheckForExternalTrigger to
> which is read the content of the trigger file defined by -f:
> CheckForExternalTrigger(void)
> {
> char buf[32];
> [...]
> if ((len = read(fd, buf, sizeof(buf))) < 0)
> {
> stuff();
> }
>
> if (len < sizeof(buf))
> buf[len] = '\0';
> However it happens that if the file read contains 32 bytes or more, we
> enforce \0 in a position out of bounds. While looking at that, I also
> noticed that pg_standby can trigger a failover as long as the
> beginning of buf matches either "smart" or "fast", but I think we
> should check for a perfect match instead of a comparison of the first
> bytes, no?
>
> Attached is a patch to fix the out-of-bound issue as well as
> improvements for the detection of the trigger file content. I think
> that the out-of-bound fix should be backpatched, while the
> improvements for the trigger file are master-only. Coverity has
> pointed out the out-of-bound issue.
I would imagine that the goal might have been to accept not only smart
but also smart\r and smart\n and smart\r\n. It's a little weird that
we also accept smartypants, though.
Instead of doing this:
if (len < sizeof(buf)) buf[len] = '\0';
...I would suggest making the size of the buffer one greater than the
size of the read(), and then always nul-terminating the buffer. It
seems to me that would make the code easier to reason about.
--
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
Re: Out-of-bounds write and incorrect detection of trigger file in pg_standby
От
Michael Paquier
Дата:
On Thu, Jan 15, 2015 at 7:13 AM, Robert Haas <robertmhaas@gmail.com> wrote: > Instead of doing this: > > if (len < sizeof(buf)) > buf[len] = '\0'; > > ...I would suggest making the size of the buffer one greater than the > size of the read(), and then always nul-terminating the buffer. It > seems to me that would make the code easier to reason about. How about the attached then? This way we still detect the same way any invalid values: - if ((len = read(fd, buf, sizeof(buf))) < 0) + if ((len = read(fd, buf, sizeof(buf) - 1)) < 0) Regards, -- Michael
Вложения
On Wed, Jan 14, 2015 at 9:27 PM, Michael Paquier <michael.paquier@gmail.com> wrote: > On Thu, Jan 15, 2015 at 7:13 AM, Robert Haas <robertmhaas@gmail.com> wrote: >> Instead of doing this: >> >> if (len < sizeof(buf)) >> buf[len] = '\0'; >> >> ...I would suggest making the size of the buffer one greater than the >> size of the read(), and then always nul-terminating the buffer. It >> seems to me that would make the code easier to reason about. > How about the attached then? This way we still detect the same way any > invalid values: > - if ((len = read(fd, buf, sizeof(buf))) < 0) > + if ((len = read(fd, buf, sizeof(buf) - 1)) < 0) Committed and back-patched all the way. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company