From 8deb6bc4addaf84a1fe2e66ec84fff3b88470507 Mon Sep 17 00:00:00 2001 From: jingtaoye35 <1255153887@qq.com> Date: Fri, 8 Sep 2023 13:16:21 +0800 Subject: [PATCH] add priv check for select for update --- src/share/schema/ob_schema_getter_guard.cpp | 39 +++++++++++++++++++ src/share/schema/ob_schema_getter_guard.h | 3 ++ src/share/schema/ob_schema_struct.cpp | 1 + src/share/schema/ob_schema_struct.h | 15 +++---- .../privilege_check/ob_privilege_check.cpp | 2 + .../resolver/ddl/ob_create_view_resolver.cpp | 1 + 6 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/share/schema/ob_schema_getter_guard.cpp b/src/share/schema/ob_schema_getter_guard.cpp index a80bd41264..4b26287b2f 100644 --- a/src/share/schema/ob_schema_getter_guard.cpp +++ b/src/share/schema/ob_schema_getter_guard.cpp @@ -3439,10 +3439,49 @@ int ObSchemaGetterGuard::check_single_table_priv(const ObSessionPrivInfo &sessio } } } + if (OB_SUCC(ret) && table_need_priv.is_for_update_) { + if (OB_FAIL(check_single_table_priv_for_update_(session_priv, table_need_priv, priv_mgr))) { + LOG_WARN("failed to check select table for update priv", K(ret)); + } + } } return ret; } +/* select ... from table for update, need select privilege and one of (delete, update lock tables). + * ob donesn't have lock tables yet, then it checks select first and one of (delete、update on table level). + */ +int ObSchemaGetterGuard::check_single_table_priv_for_update_(const ObSessionPrivInfo &session_priv, + const ObNeedPriv &table_need_priv, + const ObPrivMgr &priv_mgr) +{ + int ret = OB_SUCCESS; + const uint64_t tenant_id = session_priv.tenant_id_; + const uint64_t user_id = session_priv.user_id_; + bool pass = false; + const ObNeedPriv need_priv(table_need_priv.db_, table_need_priv.table_, table_need_priv.priv_level_, + OB_PRIV_UPDATE | OB_PRIV_DELETE, table_need_priv.is_sys_table_, + table_need_priv.is_for_update_); + if (OB_UNLIKELY(!table_need_priv.is_for_update_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("should not run this function without for update", K(ret), K(table_need_priv)); + } else if (OB_PRIV_HAS_ANY(session_priv.user_priv_set_, need_priv.priv_set_)) { + /* check ok */ + } else if (OB_FAIL(check_priv_db_or_(session_priv, need_priv, priv_mgr, tenant_id, user_id, pass))) { + LOG_WARN("failed to check priv db or", K(ret)); + } else if (!pass && OB_FAIL(check_priv_table_or_(need_priv, priv_mgr, tenant_id, user_id, pass))) { + LOG_WARN("fail to check priv table or", K(ret)); + } else if (!pass) { + ret = OB_ERR_NO_TABLE_PRIVILEGE; + const char *priv_name = "SELECT with locking clause"; + LOG_USER_ERROR(OB_ERR_NO_TABLE_PRIVILEGE, (int)strlen(priv_name), priv_name, + session_priv.user_name_.length(), session_priv.user_name_.ptr(), + session_priv.host_name_.length(), session_priv.host_name_.ptr(), + table_need_priv.table_.length(), table_need_priv.table_.ptr()); + } else { /* check ok */ } + return ret; +} + int ObSchemaGetterGuard::check_db_priv(const ObSessionPrivInfo &session_priv, const ObString &db, const ObPrivSet need_priv, diff --git a/src/share/schema/ob_schema_getter_guard.h b/src/share/schema/ob_schema_getter_guard.h index cb9fad185f..2b6936f326 100644 --- a/src/share/schema/ob_schema_getter_guard.h +++ b/src/share/schema/ob_schema_getter_guard.h @@ -1153,6 +1153,9 @@ private: int get_table_schemas_in_tenant_(const uint64_t tenant_id, const bool only_view_schema, common::ObIArray &table_schemas); + int check_single_table_priv_for_update_(const ObSessionPrivInfo &session_priv, + const ObNeedPriv &table_need_priv, + const ObPrivMgr &priv_mgr); private: common::ObArenaAllocator local_allocator_; ObMultiVersionSchemaService *schema_service_; diff --git a/src/share/schema/ob_schema_struct.cpp b/src/share/schema/ob_schema_struct.cpp index ca61313dc8..9d9a315d91 100644 --- a/src/share/schema/ob_schema_struct.cpp +++ b/src/share/schema/ob_schema_struct.cpp @@ -8962,6 +8962,7 @@ int ObNeedPriv::deep_copy(const ObNeedPriv &other, common::ObIAllocator &allocat priv_level_ = other.priv_level_; priv_set_ = other.priv_set_; is_sys_table_ = other.is_sys_table_; + is_for_update_ = other.is_for_update_; if (OB_FAIL(ob_write_string(allocator, other.db_, db_))) { LOG_WARN("Fail to deep copy db", K_(db), K(ret)); } else if (OB_FAIL(ob_write_string(allocator, other.table_, table_))) { diff --git a/src/share/schema/ob_schema_struct.h b/src/share/schema/ob_schema_struct.h index 59314d31d0..2bf0773527 100755 --- a/src/share/schema/ob_schema_struct.h +++ b/src/share/schema/ob_schema_struct.h @@ -4638,14 +4638,14 @@ struct ObNeedPriv const common::ObString &table, ObPrivLevel priv_level, ObPrivSet priv_set, - const bool is_sys_table) - : db_(db), table_(table), priv_level_(priv_level), - priv_set_(priv_set), is_sys_table_(is_sys_table) + const bool is_sys_table, + const bool is_for_update = false) + : db_(db), table_(table), priv_level_(priv_level), priv_set_(priv_set), + is_sys_table_(is_sys_table), is_for_update_(is_for_update) { } ObNeedPriv() - : db_(), table_(), - priv_level_(OB_PRIV_INVALID_LEVEL), - priv_set_(0), is_sys_table_(false) + : db_(), table_(), priv_level_(OB_PRIV_INVALID_LEVEL), priv_set_(0), is_sys_table_(false), + is_for_update_(false) { } int deep_copy(const ObNeedPriv &other, common::ObIAllocator &allocator); common::ObString db_; @@ -4653,7 +4653,8 @@ struct ObNeedPriv ObPrivLevel priv_level_; ObPrivSet priv_set_; bool is_sys_table_; // May be used to represent the table of schema metadata - TO_STRING_KV(K_(db), K_(table), K_(priv_set), K_(priv_level), K_(is_sys_table)); + bool is_for_update_; + TO_STRING_KV(K_(db), K_(table), K_(priv_set), K_(priv_level), K_(is_sys_table), K_(is_for_update)); }; struct ObStmtNeedPrivs diff --git a/src/sql/privilege_check/ob_privilege_check.cpp b/src/sql/privilege_check/ob_privilege_check.cpp index 0b32d5ff96..4bd9d737b2 100644 --- a/src/sql/privilege_check/ob_privilege_check.cpp +++ b/src/sql/privilege_check/ob_privilege_check.cpp @@ -924,6 +924,7 @@ int get_dml_stmt_need_privs( need_priv.table_ = table_item->table_name_; need_priv.priv_set_ = priv_set; need_priv.is_sys_table_ = table_item->is_system_table_; + need_priv.is_for_update_ = table_item->for_update_; need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL; //no check for information_schema select if (stmt::T_SELECT != dml_stmt->get_stmt_type()) { @@ -1901,6 +1902,7 @@ int get_load_data_stmt_need_privs( need_priv.table_ = load_data_stmt->get_load_arguments().table_name_; need_priv.priv_set_ = OB_PRIV_INSERT; need_priv.is_sys_table_ = false; + need_priv.is_for_update_ = false; need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL; ADD_NEED_PRIV(need_priv); } diff --git a/src/sql/resolver/ddl/ob_create_view_resolver.cpp b/src/sql/resolver/ddl/ob_create_view_resolver.cpp index 5bde72fc60..191e55f229 100644 --- a/src/sql/resolver/ddl/ob_create_view_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_view_resolver.cpp @@ -456,6 +456,7 @@ int ObCreateViewResolver::check_privilege_needed(ObCreateTableStmt &stmt, need_priv.table_ = table_name; need_priv.priv_set_ = OB_PRIV_SELECT; need_priv.is_sys_table_ = table_item->is_system_table_; + need_priv.is_for_update_ = table_item->for_update_; need_priv.priv_level_ = OB_PRIV_TABLE_LEVEL; if (OB_FAIL(stmt.add_view_need_priv(need_priv))) { LOG_WARN("Fail to add need_priv", K(ret), K(need_priv));