On 02.09.2022 18:36, Daniel Gustafsson wrote:
This had bitrotted a fair bit, attached is a rebase along with (mostly)
documentation fixes.  0001 adds a generic GUC for ignoring event triggers and
0002 adds the login event with event trigger support, and hooks it up to the
GUC such that broken triggers wont require single-user mode.  Moving the CF
entry back to Needs Review.


Hello!

There is a race around setting and clearing of dathasloginevt.

Steps to reproduce:

1. Create a trigger:

  CREATE FUNCTION on_login_proc() RETURNS event_trigger AS $$
  BEGIN
    RAISE NOTICE 'You are welcome!';
  END;
  $$ LANGUAGE plpgsql;

CREATE EVENT TRIGGER on_login_trigger ON login EXECUTE PROCEDURE on_login_proc();

2. Then drop it, but don't start new sessions:

  DROP EVENT TRIGGER on_login_trigger;

3. Create another trigger, but don't commit yet:

  BEGIN;
CREATE EVENT TRIGGER on_login_trigger ON login EXECUTE PROCEDURE on_login_proc();

4. Start a new session. This clears dathasloginevt.

5. Commit the transaction:

  COMMIT;

Now we have a trigger, but it doesn't fire, because dathasloginevt=false.


If two sessions create triggers concurrently, one of them will fail.

Steps:

1. In the first session, start a transaction and create a trigger:

  BEGIN;
CREATE EVENT TRIGGER on_login_trigger1 ON login EXECUTE PROCEDURE on_login_proc();

2. In the second session, create another trigger (this query blocks):

CREATE EVENT TRIGGER on_login_trigger2 ON login EXECUTE PROCEDURE on_login_proc();

3. Commit in the first session:

  COMMIT;

The second session fails:

postgres=# CREATE EVENT TRIGGER on_login_trigger2 ON login EXECUTE PROCEDURE on_login_proc();
  ERROR:  tuple concurrently updated



What else bothers me is that login triggers execute in an environment under user control and one has to be very careful. The example trigger from the documentation

+DECLARE

+  hour integer = EXTRACT('hour' FROM current_time);

+  rec boolean;

+BEGIN

+-- 1. Forbid logging in between 2AM and 4AM.

+IF hour BETWEEN 2 AND 4 THEN

+  RAISE EXCEPTION 'Login forbidden';

+END IF;


can be bypassed with PGOPTIONS='-c timezone=...'. Probably this is nothing new and concerns any SECURITY DEFINER function, but still...


Best regards,

--
Sergey Shinderuk                https://postgrespro.com/


Reply via email to