VACUUM as a denial-of-service attack - Mailing list pgsql-hackers

From Tom Lane
Subject VACUUM as a denial-of-service attack
Date
Msg-id 5124.943341039@sss.pgh.pa.us
Whole thread Raw
Responses Re: [HACKERS] VACUUM as a denial-of-service attack  (The Hermit Hacker <scrappy@hub.org>)
List pgsql-hackers
Whilst playing around with concurrent VACUUMs (see previous message),
I looked at some other issues that were on my TODO list.  I think
these deserve a separate thread:

1. VACUUM does internal start/commit-transaction calls around the
processing of each table it handles.  That's good, because it ensures
that the results of vacuuming each table are committed down to disk
before we move on to vacuuming the next one (and take the ever-present
chance of failure).  But if VACUUM is invoked inside a BEGIN/END
transaction block, those start/commit-transaction calls don't actually
commit anything; they reduce to plain statement boundaries within
the transaction.  This is Bad, Very Bad, on two grounds: (a) abort while vacuuming a later table imperils the results
forall     prior tables, since they won't get committed; (b) by the time we approach the end of vacuuming a whole
database,    we will hold exclusive locks on just about everything, which will     not be good for the progress of any
actualwork being done by     other backends.  Not to mention the very strong possibility of     hitting a deadlock
againstlocks held by other backends.
 

I had previously suggested banning VACUUM inside a transaction block
to forestall these problems.  I now see that the problems really only
apply to the case of VACUUMing a whole database --- the variant of
VACUUM that processes only a single table could be allowed inside
a BEGIN/END block, and it wouldn't create any problems worse than
any other command that grabs exclusive access on a table.  (OK,
you could BEGIN and then VACUUM a lot of tables one by one, but
then you deserve any problems you get...)

So: should VACUUM refuse to run inside BEGIN at all, or should it
refuse only the whole-database variant?  The former would be more
consistent and easier to explain, but the latter might be more useful.

2. It is a serious security breach that any random user can VACUUM
any table.  Particularly in the current code, where VACUUM can be
done inside a transaction, because that means the user can sit on
the locks acquired by VACUUM.  I can't do "lock table pg_shadow"
as an unprivileged user --- but I can do "begin; vacuum pg_shadow;
<twiddle thumbs>".  Guess what happens when subsequent users try
to connect.

Even if we disallow all forms of VACUUM inside transactions, one
could still mount a moderately effective denial-of-service attack
by issuing a continuous stream of "vacuum pg_shadow" commands,
or perhaps repeated vacuums of some large-and-mission-critical
user table.

I think a reasonable answer to this is to restrict VACUUM on any
table to be allowed only to the table owner and Postgres superuser.
Does anyone have an objection or better idea?
        regards, tom lane


pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Concurrent VACUUM: first results
Next
From: Michael Meskes
Date:
Subject: Float/Numeric?