mirror of
https://github.com/MariaDB/server.git
synced 2026-05-17 12:27:33 +02:00
MDEV-35384 Table performance_schema.session_status and other two tables are not shown in information_schema.tables for normal users
get_all_tables() skipped tables if the user has no privileges on the schema itself and no granted privilege on any tables in the schema. that is, it was skipping performance_schema tables (privileges on them aren't explicitly granted, but internally hard-coded) To fix: * extend ACL_internal_table_access::check() method with `bool any_combination_will_do` * fix all perfschema privilege checks to take it into account. * don't reuse table_acl_check object for all tables, initialize it for every table otherwise GRANT_INTERNAL_INFO will leak * remove incorrect privilege check from get_all_tables()
This commit is contained in:
parent
0706c01b88
commit
b79723ffe3
7 changed files with 105 additions and 52 deletions
|
|
@ -760,28 +760,34 @@ static bool allow_drop_table_privilege() {
|
|||
PFS_readonly_acl pfs_readonly_acl;
|
||||
|
||||
ACL_internal_access_result
|
||||
PFS_readonly_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
||||
PFS_readonly_acl::check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
const privilege_t always_forbidden= INSERT_ACL | UPDATE_ACL | DELETE_ACL
|
||||
| /* CREATE_ACL | */ REFERENCES_ACL | INDEX_ACL | ALTER_ACL
|
||||
| CREATE_VIEW_ACL | SHOW_VIEW_ACL | TRIGGER_ACL | LOCK_TABLES_ACL;
|
||||
|
||||
if (unlikely((want_access & always_forbidden) != NO_ACL))
|
||||
return ACL_INTERNAL_ACCESS_DENIED;
|
||||
|
||||
return ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
if (any_combination_will_do)
|
||||
return want_access & ~always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_CHECK_GRANT: ACL_INTERNAL_ACCESS_DENIED;
|
||||
else
|
||||
return want_access & always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_DENIED : ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
}
|
||||
|
||||
|
||||
PFS_readonly_world_acl pfs_readonly_world_acl;
|
||||
|
||||
ACL_internal_access_result
|
||||
PFS_readonly_world_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
||||
PFS_readonly_world_acl::check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
ACL_internal_access_result res= PFS_readonly_acl::check(want_access, save_priv);
|
||||
ACL_internal_access_result res=
|
||||
PFS_readonly_acl::check(want_access, save_priv, any_combination_will_do);
|
||||
if (res == ACL_INTERNAL_ACCESS_CHECK_GRANT)
|
||||
{
|
||||
if (want_access == SELECT_ACL)
|
||||
if (any_combination_will_do ?
|
||||
((want_access & SELECT_ACL) != NO_ACL) : (want_access == SELECT_ACL))
|
||||
res= ACL_INTERNAL_ACCESS_GRANTED;
|
||||
}
|
||||
return res;
|
||||
|
|
@ -790,9 +796,11 @@ PFS_readonly_world_acl::check(privilege_t want_access, privilege_t *save_priv) c
|
|||
PFS_readonly_processlist_acl pfs_readonly_processlist_acl;
|
||||
|
||||
ACL_internal_access_result PFS_readonly_processlist_acl::check(
|
||||
privilege_t want_access, privilege_t *save_priv) const {
|
||||
privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
ACL_internal_access_result res =
|
||||
PFS_readonly_acl::check(want_access, save_priv);
|
||||
PFS_readonly_acl::check(want_access, save_priv, any_combination_will_do);
|
||||
|
||||
if ((res == ACL_INTERNAL_ACCESS_CHECK_GRANT) && (want_access == SELECT_ACL)) {
|
||||
THD *thd = current_thd;
|
||||
|
|
@ -818,34 +826,41 @@ ACL_internal_access_result PFS_readonly_processlist_acl::check(
|
|||
PFS_truncatable_acl pfs_truncatable_acl;
|
||||
|
||||
ACL_internal_access_result
|
||||
PFS_truncatable_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
||||
PFS_truncatable_acl::check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
const privilege_t always_forbidden= INSERT_ACL | UPDATE_ACL | DELETE_ACL
|
||||
| /* CREATE_ACL | */ REFERENCES_ACL | INDEX_ACL | ALTER_ACL
|
||||
| CREATE_VIEW_ACL | SHOW_VIEW_ACL | TRIGGER_ACL | LOCK_TABLES_ACL;
|
||||
|
||||
if (unlikely((want_access & always_forbidden) != NO_ACL))
|
||||
return ACL_INTERNAL_ACCESS_DENIED;
|
||||
|
||||
return ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
if (any_combination_will_do)
|
||||
return want_access & ~always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_CHECK_GRANT: ACL_INTERNAL_ACCESS_DENIED;
|
||||
else
|
||||
return want_access & always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_DENIED : ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
}
|
||||
|
||||
|
||||
PFS_truncatable_world_acl pfs_truncatable_world_acl;
|
||||
|
||||
ACL_internal_access_result
|
||||
PFS_truncatable_world_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
||||
PFS_truncatable_world_acl::check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
ACL_internal_access_result res= PFS_truncatable_acl::check(want_access, save_priv);
|
||||
ACL_internal_access_result res=
|
||||
PFS_truncatable_acl::check(want_access, save_priv, any_combination_will_do);
|
||||
if (res == ACL_INTERNAL_ACCESS_CHECK_GRANT)
|
||||
{
|
||||
if (want_access == DROP_ACL)
|
||||
if (any_combination_will_do ?
|
||||
((want_access & SELECT_ACL) != NO_ACL) : (want_access == SELECT_ACL))
|
||||
res= ACL_INTERNAL_ACCESS_GRANTED;
|
||||
else if (any_combination_will_do ?
|
||||
((want_access & DROP_ACL) != NO_ACL) : (want_access == DROP_ACL))
|
||||
{
|
||||
if (allow_drop_table_privilege())
|
||||
res= ACL_INTERNAL_ACCESS_GRANTED;
|
||||
}
|
||||
else if (want_access == SELECT_ACL)
|
||||
res= ACL_INTERNAL_ACCESS_GRANTED;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -854,44 +869,48 @@ PFS_truncatable_world_acl::check(privilege_t want_access, privilege_t *save_priv
|
|||
PFS_updatable_acl pfs_updatable_acl;
|
||||
|
||||
ACL_internal_access_result
|
||||
PFS_updatable_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
||||
PFS_updatable_acl::check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
const privilege_t always_forbidden= INSERT_ACL | DELETE_ACL
|
||||
| /* CREATE_ACL | */ REFERENCES_ACL | INDEX_ACL | ALTER_ACL
|
||||
| CREATE_VIEW_ACL | SHOW_VIEW_ACL | TRIGGER_ACL;
|
||||
|
||||
if (unlikely((want_access & always_forbidden) != NO_ACL))
|
||||
return ACL_INTERNAL_ACCESS_DENIED;
|
||||
|
||||
return ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
if (any_combination_will_do)
|
||||
return want_access & ~always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_CHECK_GRANT: ACL_INTERNAL_ACCESS_DENIED;
|
||||
else
|
||||
return want_access & always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_DENIED : ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
}
|
||||
|
||||
PFS_editable_acl pfs_editable_acl;
|
||||
|
||||
ACL_internal_access_result
|
||||
PFS_editable_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
||||
PFS_editable_acl::check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
const privilege_t always_forbidden= /* CREATE_ACL | */ REFERENCES_ACL
|
||||
| INDEX_ACL | ALTER_ACL | CREATE_VIEW_ACL | SHOW_VIEW_ACL | TRIGGER_ACL;
|
||||
|
||||
if (unlikely((want_access & always_forbidden) != NO_ACL))
|
||||
return ACL_INTERNAL_ACCESS_DENIED;
|
||||
|
||||
return ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
if (any_combination_will_do)
|
||||
return want_access & ~always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_CHECK_GRANT: ACL_INTERNAL_ACCESS_DENIED;
|
||||
else
|
||||
return want_access & always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_DENIED : ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
}
|
||||
|
||||
PFS_unknown_acl pfs_unknown_acl;
|
||||
|
||||
ACL_internal_access_result
|
||||
PFS_unknown_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
||||
PFS_unknown_acl::check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const
|
||||
{
|
||||
const privilege_t always_forbidden= CREATE_ACL
|
||||
| REFERENCES_ACL | INDEX_ACL | ALTER_ACL
|
||||
| CREATE_VIEW_ACL | TRIGGER_ACL;
|
||||
|
||||
if (unlikely((want_access & always_forbidden) != NO_ACL))
|
||||
return ACL_INTERNAL_ACCESS_DENIED;
|
||||
|
||||
/*
|
||||
There is no point in hiding (by enforcing ACCESS_DENIED for SELECT_ACL
|
||||
on performance_schema.*) tables that do not exist anyway.
|
||||
|
|
@ -902,7 +921,12 @@ PFS_unknown_acl::check(privilege_t want_access, privilege_t *save_priv) const
|
|||
The same goes for other DML (INSERT_ACL | UPDATE_ACL | DELETE_ACL),
|
||||
for ease of use: error messages will be less surprising.
|
||||
*/
|
||||
return ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
if (any_combination_will_do)
|
||||
return want_access & ~always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_CHECK_GRANT: ACL_INTERNAL_ACCESS_DENIED;
|
||||
else
|
||||
return want_access & always_forbidden
|
||||
? ACL_INTERNAL_ACCESS_DENIED : ACL_INTERNAL_ACCESS_CHECK_GRANT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -340,8 +340,8 @@ public:
|
|||
|
||||
~PFS_readonly_acl() = default;
|
||||
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv) const override;
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
/** Singleton instance of PFS_readonly_acl. */
|
||||
|
|
@ -359,7 +359,7 @@ public:
|
|||
~PFS_truncatable_acl() = default;
|
||||
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv) const override;
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
/** Singleton instance of PFS_truncatable_acl. */
|
||||
|
|
@ -377,7 +377,7 @@ public:
|
|||
~PFS_updatable_acl() = default;
|
||||
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv) const override;
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
/** Singleton instance of PFS_updatable_acl. */
|
||||
|
|
@ -395,7 +395,7 @@ public:
|
|||
~PFS_editable_acl() = default;
|
||||
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv) const override;
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
/** Singleton instance of PFS_editable_acl. */
|
||||
|
|
@ -412,7 +412,7 @@ public:
|
|||
~PFS_unknown_acl() = default;
|
||||
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv) const override;
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
/** Singleton instance of PFS_unknown_acl. */
|
||||
|
|
@ -430,7 +430,8 @@ public:
|
|||
|
||||
~PFS_readonly_world_acl()
|
||||
{}
|
||||
ACL_internal_access_result check(privilege_t want_access, privilege_t *save_priv) const override;
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -449,7 +450,8 @@ public:
|
|||
|
||||
~PFS_truncatable_world_acl()
|
||||
{}
|
||||
ACL_internal_access_result check(privilege_t want_access, privilege_t *save_priv) const override;
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -469,7 +471,7 @@ class PFS_readonly_processlist_acl : public PFS_readonly_acl {
|
|||
{}
|
||||
|
||||
ACL_internal_access_result check(privilege_t want_access,
|
||||
privilege_t *save_priv) const override;
|
||||
privilege_t *save_priv, bool any_combination_will_do) const override;
|
||||
};
|
||||
|
||||
/** Singleton instance of PFS_readonly_processlist_acl */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue