Safer auto-initdb for RPM init script

Started by Tom Laneover 19 years ago30 messageshackers
Jump to latest
#1Tom Lane
tgl@sss.pgh.pa.us

We've seen more than one report of corruption of PG databases that
seemed to be due to the willingness of the RPM init script to run
initdb if it thinks the data directory isn't there. This is pretty
darn risky on an NFS volume, for instance, which might be offline
at the instant the script looks. The failure case is

- script doesn't see data directory
- script runs initdb and starts postmaster
- offline volume comes online
- KABOOM

The initdb creates a "local" database that's physically on the root
volume underneath the mountpoint directory for the intended volume.
After the mountable volume comes online, these files are shadowed
by the original database files. The problem is that by this point the
postmaster has a copy of pg_control in memory from the freshly-initdb'd
database, and that pg_control has a WAL end address and XID counter far
less than is correct for the real database. Havoc ensues, very probably
resulting in a hopelessly corrupt database.

I don't really want to remove the auto-initdb feature from the script,
because it's important not to drive away newbies by making Postgres
hard to start for the first time. But I think we'd better think about
ways to make it more bulletproof.

The first thought that comes to mind is to have the RPM install create
the data directory if not present and create a flag file in it showing
that it's safe to initdb. Then the script is allowed to initdb only
if it finds the directory and the flag file but not PG_VERSION.
Something like (untested off-the-cuff coding)

%post server

if [ ! -d $PGDATA ]; then
mkdir $PGDATA
touch $PGDATA/NO_DATABASE_YET
fi

and in initscript

if [ -d $PGDATA -a -f $PGDATA/NO_DATABASE_YET -a ! -f $PGDATA/PG_VERSION ] ; then
rm -f $PGDATA/NO_DATABASE_YET && initdb ...
fi

If the data directory is not mounted then the -d test would fail,
unless the directory is itself the mount point, in which case it
would be there but not contain the NO_DATABASE_YET file.

I can still imagine ways for this to fail, eg if you run an RPM
install or upgrade while your mountable data directory is offline.
But it ought to be an order of magnitude safer than things are now.
(Hm, maybe the %post script should only run during an RPM install,
not an upgrade.)

Comments? Anyone see a better way?

regards, tom lane

#2Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#1)
Re: Safer auto-initdb for RPM init script

Am Freitag, 25. August 2006 15:19 schrieb Tom Lane:

I don't really want to remove the auto-initdb feature from the script,
because it's important not to drive away newbies by making Postgres
hard to start for the first time. But I think we'd better think about
ways to make it more bulletproof.

Why not run initdb in the %post and not in the init script at all? That
should be newbie-friendly as well.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#3Magnus Hagander
magnus@hagander.net
In reply to: Tom Lane (#1)
Re: Safer auto-initdb for RPM init script

I don't really want to remove the auto-initdb feature from the
script, because it's important not to drive away newbies by making
Postgres hard to start for the first time. But I think we'd better
think about ways to make it more bulletproof.

Why does initdb have to happen on startup? Wouldn't it be much more
logical to do it at install time? (like we do in the win32 installer,
for example, I'm sure there are other examples as well)

//Magnus

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Magnus Hagander (#3)
Re: Safer auto-initdb for RPM init script

"Magnus Hagander" <mha@sollentuna.net> writes:

I don't really want to remove the auto-initdb feature from the
script, because it's important not to drive away newbies by making
Postgres hard to start for the first time. But I think we'd better
think about ways to make it more bulletproof.

Why does initdb have to happen on startup? Wouldn't it be much more
logical to do it at install time?

It eats rather a lot of disk space for a package that might just be
getting loaded as part of a system install, with no likelihood of
actually being used. In CVS tip a just-initdb'd data directory seems
to be a shade under 30MB, which I guess isn't a huge amount these days
but it compares unfavorably with the installed footprint of the code
itself (postgresql-server RPM looks to be about 4MB).

If this were a bulletproof solution then I'd consider it anyway, but
AFAICS it's got the very same vulnerabilities as the flag-file method,
ie, if you RPM install or upgrade while your mountable data directory
is offline, you can still get screwed.

regards, tom lane

#5Joe Conway
mail@joeconway.com
In reply to: Tom Lane (#1)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init script

Tom Lane wrote:

We've seen more than one report of corruption of PG databases that
seemed to be due to the willingness of the RPM init script to run
initdb if it thinks the data directory isn't there. This is pretty
darn risky on an NFS volume, for instance, which might be offline
at the instant the script looks. The failure case is

- script doesn't see data directory
- script runs initdb and starts postmaster
- offline volume comes online
- KABOOM

Been there, done exactly that...

I can still imagine ways for this to fail, eg if you run an RPM
install or upgrade while your mountable data directory is offline.
But it ought to be an order of magnitude safer than things are now.
(Hm, maybe the %post script should only run during an RPM install,
not an upgrade.)

That's probably a good plan.

Comments? Anyone see a better way?

I can't think of any offhand that aren't too expensive. We ended up
putting a root-owned empty data directory beneath the mount point, but
that can't be automated.

We also decided to turn off the init script execution entirely. The DBAs
were more comfortable with a manual database startup for a production
machine anyway (this is the way they typically handle Oracle databases
also). They get paged if the server ever goes down unplanned, and in
that event they like to check things out before bringing the db back up.
For planned outages, database startup is simply part of the plan.

Joe

#6Sander Steffann
s.steffann@computel.nl
In reply to: Tom Lane (#4)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM initscript

Hi,

If this were a bulletproof solution then I'd consider it anyway, but
AFAICS it's got the very same vulnerabilities as the flag-file method,
ie, if you RPM install or upgrade while your mountable data directory
is offline, you can still get screwed.

Isn't the most bulletproof solution to make initdb more careful about
overwriting an existing data directory?

- Sander

#7Andrew Dunstan
andrew@dunslane.net
In reply to: Sander Steffann (#6)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM initscript

Sander Steffann wrote:

Hi,

If this were a bulletproof solution then I'd consider it anyway, but
AFAICS it's got the very same vulnerabilities as the flag-file method,
ie, if you RPM install or upgrade while your mountable data directory
is offline, you can still get screwed.

Isn't the most bulletproof solution to make initdb more careful about
overwriting an existing data directory?

It is extremely careful. The point is that the NFS mount will hide the
existing datadir from initdb.

cheers

andrew

#8Reinhard Max
max@suse.de
In reply to: Tom Lane (#4)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init

On Fri, 25 Aug 2006 at 10:20, Tom Lane wrote:

If this were a bulletproof solution then I'd consider it anyway, but
AFAICS it's got the very same vulnerabilities as the flag-file
method, ie, if you RPM install or upgrade while your mountable data
directory is offline, you can still get screwed.

Another flaw of the flag-file method is, that PGDATA might have been
changed by the sysadmin between installing the RPM and calling the
init script for the first time.

But shouldn't mountpoints always have 000 permissions to prevent
writing into the directory as long as nothing is mounted to it?

cu
Reinhard

#9Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#4)
Re: Safer auto-initdb for RPM init script

Am Freitag, 25. August 2006 16:20 schrieb Tom Lane:

It eats rather a lot of disk space for a package that might just be
getting loaded as part of a system install, with no likelihood of
actually being used.

Wouldn't the system install start the init script at the end of the
installation process anyway?

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#10Peter Eisentraut
peter_e@gmx.net
In reply to: Reinhard Max (#8)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init

Am Freitag, 25. August 2006 16:31 schrieb Reinhard Max:

But shouldn't mountpoints always have 000 permissions to prevent
writing into the directory as long as nothing is mounted to it?

That's an interesting point, but in practice nobody does that. And we're
trying to defend exactly against the case where someone has set up a mount
point manually.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#11Tom Lane
tgl@sss.pgh.pa.us
In reply to: Reinhard Max (#8)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init script

Reinhard Max <max@suse.de> writes:

Another flaw of the flag-file method is, that PGDATA might have been
changed by the sysadmin between installing the RPM and calling the
init script for the first time.

What problem do you see there? With either of these methods, a manual
change in PGDATA would require a manual initdb before the postmaster
would start. That seems like a good conservative thing to me.

(Actually, with the flag-file method you could get the initscript
to run initdb for you by hand-creating the flag file, but it seems
unlikely people would do that in practice.)

But shouldn't mountpoints always have 000 permissions to prevent
writing into the directory as long as nothing is mounted to it?

Not sure that that helps much given that the initscript runs as root.
And in any case the point here is to protect against human error,
not to assume that the installation is managed according to very
best practices.

regards, tom lane

#12Bruce Momjian
bruce@momjian.us
In reply to: Tom Lane (#1)
Re: Safer auto-initdb for RPM init script

Tom Lane <tgl@sss.pgh.pa.us> writes:

Comments? Anyone see a better way?

Well the truly bullet-proof mechanism would be to check every data file on
every open. You could have a header with some kind of unique tag generated at
initdb time and the backend could ensure it matches the same tag in the
control flag whenever you open a data file.

That might be too expensive though I don't see data files getting opened all
that frequently. You could do the same thing for free by putting the tag in
the file names though.

--
Gregory Stark
EnterpriseDB http://www.enterprisedb.com

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Peter Eisentraut (#9)
Re: Safer auto-initdb for RPM init script

Peter Eisentraut <peter_e@gmx.net> writes:

Am Freitag, 25. August 2006 16:20 schrieb Tom Lane:

It eats rather a lot of disk space for a package that might just be
getting loaded as part of a system install, with no likelihood of
actually being used.

Wouldn't the system install start the init script at the end of the
installation process anyway?

No, it doesn't. (The Red Hat RPMs in fact did that ... for about
a week ... until I was told in no uncertain terms that we don't
start unnecessary daemons by default.)

regards, tom lane

#14Peter Eisentraut
peter_e@gmx.net
In reply to: Sander Steffann (#6)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM initscript

Am Freitag, 25. August 2006 17:17 schrieb Enver ALTIN:

Am I the only one who believes that PostgreSQL project is not supposed
to fix (or include workarounds for) some other systems that actually
don't work very well?

Yes.

If NFS is causing trouble, let it be.

NFS is not the trouble.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#15Peter Eisentraut
peter_e@gmx.net
In reply to: Tom Lane (#13)
Re: Safer auto-initdb for RPM init script

Am Freitag, 25. August 2006 16:54 schrieb Tom Lane:

No, it doesn't. (The Red Hat RPMs in fact did that ... for about
a week ... until I was told in no uncertain terms that we don't
start unnecessary daemons by default.)

Well, there seem to be philosophical differences between the various operating
systems -- "We won't install unnecessary packages." vs. "We won't start
unnecessary daemons in unnecessarily installed packages." -- in which case
your solution doesn't sound all that bad.

--
Peter Eisentraut
http://developer.postgresql.org/~petere/

#16Enver ALTIN
ealtin@parkyeri.com
In reply to: Andrew Dunstan (#7)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM initscript

Merhaba,

On Fri, Aug 25, 2006 at 10:30:56AM -0400, Andrew Dunstan wrote:

It is extremely careful. The point is that the NFS mount will hide the
existing datadir from initdb.

Am I the only one who believes that PostgreSQL project is not supposed
to fix (or include workarounds for) some other systems that actually
don't work very well?

If NFS is causing trouble, let it be.

Thanks,
--
Enver

#17Bort, Paul
pbort@tmwsystems.com
In reply to: Peter Eisentraut (#10)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init

Am Freitag, 25. August 2006 16:31 schrieb Reinhard Max:

But shouldn't mountpoints always have 000 permissions to prevent
writing into the directory as long as nothing is mounted to it?

That's an interesting point, but in practice nobody does
that. And we're
trying to defend exactly against the case where someone has
set up a mount
point manually.

It had never occurred to me, but I'm definitely going to start doing it
now. So it will be in practice, at least around here.

Regards,
Paul Bort

#18Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Joe Conway (#5)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init script

On Fri, Aug 25, 2006 at 07:21:50AM -0700, Joe Conway wrote:

We also decided to turn off the init script execution entirely. The DBAs
were more comfortable with a manual database startup for a production
machine anyway (this is the way they typically handle Oracle databases
also). They get paged if the server ever goes down unplanned, and in
that event they like to check things out before bringing the db back up.
For planned outages, database startup is simply part of the plan.

I'd *really* like to have an official way to just disable the initdb
code entirely.
--
Jim C. Nasby, Sr. Engineering Consultant jnasby@pervasive.com
Pervasive Software http://pervasive.com work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf cell: 512-569-9461

#19Joshua D. Drake
jd@commandprompt.com
In reply to: Jim Nasby (#18)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init

Jim C. Nasby wrote:

On Fri, Aug 25, 2006 at 07:21:50AM -0700, Joe Conway wrote:

We also decided to turn off the init script execution entirely. The DBAs
were more comfortable with a manual database startup for a production
machine anyway (this is the way they typically handle Oracle databases
also). They get paged if the server ever goes down unplanned, and in
that event they like to check things out before bringing the db back up.
For planned outages, database startup is simply part of the plan.

I'd *really* like to have an official way to just disable the initdb
code entirely.

I am not exactly sure why we initdb at all. IMHO it would be better if
the start script just checked if there was a cluster. If not, it
wouldn't start, it would error with: You do not have a cluster, please
read man page on initdb.

Joshua D. Drake

--

=== The PostgreSQL Company: Command Prompt, Inc. ===
Sales/Support: +1.503.667.4564 || 24x7/Emergency: +1.800.492.2240
Providing the most comprehensive PostgreSQL solutions since 1997
http://www.commandprompt.com/

#20Jim Nasby
Jim.Nasby@BlueTreble.com
In reply to: Joshua D. Drake (#19)
Re: [Pgsqlrpms-hackers] Safer auto-initdb for RPM init

On Sat, Aug 26, 2006 at 01:32:17PM -0700, Joshua D. Drake wrote:

Jim C. Nasby wrote:

On Fri, Aug 25, 2006 at 07:21:50AM -0700, Joe Conway wrote:

We also decided to turn off the init script execution entirely. The DBAs
were more comfortable with a manual database startup for a production
machine anyway (this is the way they typically handle Oracle databases
also). They get paged if the server ever goes down unplanned, and in
that event they like to check things out before bringing the db back up.
For planned outages, database startup is simply part of the plan.

I'd *really* like to have an official way to just disable the initdb
code entirely.

I am not exactly sure why we initdb at all. IMHO it would be better if
the start script just checked if there was a cluster. If not, it
wouldn't start, it would error with: You do not have a cluster, please
read man page on initdb.

As Tom mentioned, it's for newbie-friendliness. While I can understand
that, I think it needs to be easy to shut that off.
--
Jim C. Nasby, Sr. Engineering Consultant jnasby@pervasive.com
Pervasive Software http://pervasive.com work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf cell: 512-569-9461

#21Andrew Dunstan
andrew@dunslane.net
In reply to: Jim Nasby (#18)
#22Matthew T. O'Connor
matthew@zeut.net
In reply to: Jim Nasby (#20)
#23Joshua D. Drake
jd@commandprompt.com
In reply to: Matthew T. O'Connor (#22)
#24Matthew T. O'Connor
matthew@zeut.net
In reply to: Joshua D. Drake (#23)
#25Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Jim Nasby (#18)
#26Andrew Dunstan
andrew@dunslane.net
In reply to: Alvaro Herrera (#25)
#27Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Andrew Dunstan (#26)
#28Devrim GÜNDÜZ
devrim@gunduz.org
In reply to: Andrew Dunstan (#21)
#29Lamar Owen
lamar.owen@wgcr.org
In reply to: Matthew T. O'Connor (#24)
#30Reinhard Max
max@suse.de
In reply to: Lamar Owen (#29)