Skip to content

[DISCARDED PXC-5291 will have fix](8.4)PXC-5292: CREATE TRIGGER with nonexistent DEFINER by SET_ANY_DEFINER … - #2325

Open
jaideepkarande wants to merge 1 commit into
percona:8.4from
jaideepkarande:PXC-5292-8.4
Open

[DISCARDED PXC-5291 will have fix](8.4)PXC-5292: CREATE TRIGGER with nonexistent DEFINER by SET_ANY_DEFINER …#2325
jaideepkarande wants to merge 1 commit into
percona:8.4from
jaideepkarande:PXC-5292-8.4

Conversation

@jaideepkarande

Copy link
Copy Markdown
Contributor

…user can cause node inconsistency/eviction

https://perconadev.atlassian.net/browse/PXC-5292

The early privilege gate added by PXC-4765 in Sql_cmd_create_trigger::execute() runs before wsrep_to_isolation_begin() so the origin rejects an invalid DEFINER before replicating it. That gate mirrored only the definer-mismatch stage of check_valid_definer() (WL#15874), not the orphan-definer stage. As a result a user with SET_ANY_DEFINER but without SUPER or ALLOW_NONEXISTENT_DEFINER could create a trigger with a non-existent DEFINER: the early gate passed, the statement replicated, then the origin rejected it during creation (after TOI) while the appliers created it successfully -- leaving the origin inconsistent and evicting it from the cluster.

Add the orphan-definer check (require SUPER or ALLOW_NONEXISTENT_DEFINER when the DEFINER is not an existing ACL user) to the early pre-TOI gate, mirroring stage 2 of check_valid_definer(). The informational ER_NO_SUCH_USER note is left to the authoritative post-TOI check_valid_definer() call to avoid a duplicate warning.

…user can cause node inconsistency/eviction

https://perconadev.atlassian.net/browse/PXC-5292

The early privilege gate added by PXC-4765 in Sql_cmd_create_trigger::execute()
runs before wsrep_to_isolation_begin() so the origin rejects an invalid DEFINER
before replicating it. That gate mirrored only the definer-mismatch stage of
check_valid_definer() (WL#15874), not the orphan-definer stage. As a result a
user with SET_ANY_DEFINER but without SUPER or ALLOW_NONEXISTENT_DEFINER could
create a trigger with a non-existent DEFINER: the early gate passed, the
statement replicated, then the origin rejected it during creation (after TOI)
while the appliers created it successfully -- leaving the origin inconsistent
and evicting it from the cluster.

Add the orphan-definer check (require SUPER or ALLOW_NONEXISTENT_DEFINER when
the DEFINER is not an existing ACL user) to the early pre-TOI gate, mirroring
stage 2 of check_valid_definer(). The informational ER_NO_SUCH_USER note is
left to the authoritative post-TOI check_valid_definer() call to avoid a
duplicate warning.
@jaideepkarande

Copy link
Copy Markdown
Contributor Author

@jaideepkarande
jaideepkarande marked this pull request as ready for review July 16, 2026 06:18
Comment thread sql/sql_trigger.cc
true /* report_error */))
return true;

/*

@kamil-holubicki kamil-holubicki Aug 28, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think both prechecks (This one and the one introduced in PXC-4765) can be collapsed into a single call to check_valid_definer() + binlog specific checks, like

Security_context *sctx = thd->security_context();
LEX *lex = thd->lex;

const bool definer_is_current_user =
    !lex->definer ||
    (strcmp(lex->definer->user.str, sctx->priv_user().str) == 0 &&
     my_strcasecmp(system_charset_info,
                   lex->definer->host.str, sctx->priv_host().str) == 0);

// WSREP-specific binlog gate: creating a trigger under your OWN name still
// requires SUPER/SET_ANY_DEFINER when trust_function_creators is off and
// binlog is on. check_valid_definer() does not cover this (its stage 1 is
// skipped when definer == current user).
if (definer_is_current_user &&
    !trust_function_creators &&
    (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
    !(sctx->check_access(SUPER_ACL) ||
      sctx->has_global_grant(STRING_WITH_LEN("SET_ANY_DEFINER")).first)) {
  my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER,
             "You do not have the SUPER privilege (you *might* want to use "
             "the less safe log_bin_trust_function_creators variable)",
             MYF(0));
  return true;
}

// Everything else: differing-definer privilege, system_user protection,
// orphan-definer privilege - delegate to the authoritative check.
if (lex->definer && check_valid_definer(thd, lex->definer)) return true;

NOTE:

The wrinkle: ER_NO_SUCH_USER warning duplication on the origin.

If a caller with ALLOW_NONEXISTENT_DEFINER creates a trigger with an orphan definer:

  • Pre-TOI check_valid_definer passes stage 2 and pushes ER_NO_SUCH_USER (sql_authorization.cc:7832-7834).
  • Post-TOI check_valid_definer at table_trigger_dispatcher.cc:207 runs again on the origin during actual creation and pushes it again.

Client sees the note twice.

To fix that:
Add a bool quiet (or bool report_no_such_user_warning) param to check_valid_definer(). Minimal, does the job; touches sql/auth/sql_authorization.cc

@jaideepkarande jaideepkarande changed the title (8.4)PXC-5292: CREATE TRIGGER with nonexistent DEFINER by SET_ANY_DEFINER … [DISCARDED PXC-5291 will have fix](8.4)PXC-5292: CREATE TRIGGER with nonexistent DEFINER by SET_ANY_DEFINER … Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants