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

Started by Heikki Linnakangasalmost 14 years ago3 messagescomitters
Jump to latest
#1Heikki Linnakangas
heikki.linnakangas@enterprisedb.com

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(-)

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Heikki Linnakangas (#1)
Re: pgsql: Fix race condition in pg_ctl reading postmaster.pid.

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

#3Heikki Linnakangas
heikki.linnakangas@enterprisedb.com
In reply to: Tom Lane (#2)
Re: pgsql: Fix race condition in pg_ctl reading postmaster.pid.

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