Thread: pgsql: Fix race condition in pg_ctl reading postmaster.pid.

pgsql: Fix race condition in pg_ctl reading postmaster.pid.

From
Heikki Linnakangas
Date:
Fix race condition in pg_ctl reading postmaster.pid.

If postmaster changed postmaster.pid while pg_ctl was reading it, pg_ctl
could overrun the buffer it allocated for the file. Fix by reading the
whole file to memory with one read() call.

initdb contains an identical copy of the readfile() function, but the files
that initdb reads are static, not modified concurrently. Nevertheless, add
a simple bounds-check there, if only to silence static analysis tools.

Per report from Dave Vitek. Backpatch to all supported branches.

Branch
------
master

Details
-------
http://git.postgresql.org/pg/commitdiff/5c89684e08cda82727bd8bdad155b9235fb7246e

Modified Files
--------------
src/bin/initdb/initdb.c |    9 +++--
src/bin/pg_ctl/pg_ctl.c |   88 +++++++++++++++++++++++++++++++----------------
2 files changed, 63 insertions(+), 34 deletions(-)


Re: pgsql: Fix race condition in pg_ctl reading postmaster.pid.

From
Tom Lane
Date:
Heikki Linnakangas <heikki.linnakangas@iki.fi> writes:
> Fix race condition in pg_ctl reading postmaster.pid.
> If postmaster changed postmaster.pid while pg_ctl was reading it, pg_ctl
> could overrun the buffer it allocated for the file. Fix by reading the
> whole file to memory with one read() call.

Maybe I'm just not awake enough, but that code doesn't look to me like
it does the right thing with a non-newline-terminated file.  Doesn't it
drop the last character of the last line?

Given the way that pg_ctl uses the file, I think that the old logic of
"pretend the file ends with a newline" is wrong anyway.  If we do manage
to see an intermediate state of the file, it would be better to not
return the last line at all than to return a truncated (a/k/a wrong)
value for that line.  So I'd vote to rejigger the logic to ignore any
data after the last newline.

            regards, tom lane


Re: pgsql: Fix race condition in pg_ctl reading postmaster.pid.

From
Heikki Linnakangas
Date:
On 15.10.2012 17:05, Tom Lane wrote:
> Heikki Linnakangas<heikki.linnakangas@iki.fi>  writes:
>> Fix race condition in pg_ctl reading postmaster.pid.
>> If postmaster changed postmaster.pid while pg_ctl was reading it, pg_ctl
>> could overrun the buffer it allocated for the file. Fix by reading the
>> whole file to memory with one read() call.
>
> Maybe I'm just not awake enough, but that code doesn't look to me like
> it does the right thing with a non-newline-terminated file.  Doesn't it
> drop the last character of the last line?

No. It loops until the next-to-last character when it searches for
newlines. When it hits that, it creates the final string to return,
which includes the final character, whether it's a newline or not.

BTW, an easy way to test this is to edit postmaster.opts on a running
server, and do "pg_ctl status". It prints out the contents of
postmaster.opts, as parsed by the function.

> Given the way that pg_ctl uses the file, I think that the old logic of
> "pretend the file ends with a newline" is wrong anyway.  If we do manage
> to see an intermediate state of the file, it would be better to not
> return the last line at all than to return a truncated (a/k/a wrong)
> value for that line.  So I'd vote to rejigger the logic to ignore any
> data after the last newline.

Good point. I'll rejigger..

- Heikki