]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
MySQL sqlippool SP: Run as invoker, not definer; close transaction on error (#4171)
authorTerry Burton <tez@terryburton.co.uk>
Tue, 3 Aug 2021 21:16:46 +0000 (22:16 +0100)
committerGitHub <noreply@github.com>
Tue, 3 Aug 2021 21:16:46 +0000 (17:16 -0400)
In MariaDB/MySQL, stored procedures default to running in the context of
the definer rather than the invoker.

This is a problem in a streaming replication scenario since the definer
is often the root user who has the "super" power to write to a read-only
database (unless super-read-only is enabled, which is not available for
MariaDB), thus breaking the replication timeline.

Additionally, exiting an SP does not finalise any running transaction.
If an exception is raised within the SP (e.g. due to the database being
read-only) we must handle this and finalise the transaction, otherwise
subsequent calls to "SET TRANSACTION ISOLATION LEVEL READ COMMITTED"
will fail ad nauseam until the connection is finally closed.

raddb/mods-config/sql/ippool/mysql/procedure.sql

index 1db20854f243841e499e1e5e6a5fecb104bddd09..1a05bf99129a71a6600570a981050cfa62307ff4 100644 (file)
@@ -38,9 +38,16 @@ CREATE PROCEDURE fr_ippool_allocate_previous_or_new_address (
        IN v_lease_duration INT,
        IN v_requested_address VARCHAR(15)
 )
+SQL SECURITY INVOKER
 proc:BEGIN
        DECLARE r_address VARCHAR(15);
 
+       DECLARE EXIT HANDLER FOR SQLEXCEPTION
+       BEGIN
+               ROLLBACK;
+               RESIGNAL;
+       END;
+
        SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
 
        START TRANSACTION;