Skip to content
/ server Public

Commit ca63e2c

Browse files
MDEV-37950: INSERT ... RETURNING exposes columns for which the user lacks
SELECT privilege Analysis: When setup_fields() is called, the want_privilege is set to NO_ACL, so correct priveleges are not checked. Fix: Since RETURNING requires SELECT_ACL privelige, when we are setting up the returning fields for the given query, set want_privilege to SELECT_ACL. Reset to original value of want_privilege once done.
1 parent 6892722 commit ca63e2c

File tree

3 files changed

+115
-4
lines changed

3 files changed

+115
-4
lines changed

mysql-test/main/insert_notembedded.result

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,3 +121,46 @@ connection default;
121121
DROP DATABASE meow;
122122
set local sql_mode=default;
123123
set global sql_mode=default;
124+
#
125+
# MDEV-37950: INSERT ... RETURNING exposes columns for which
126+
# the user lacks SELECT privilege
127+
#
128+
CREATE USER regular;
129+
GRANT INSERT ON *.* TO regular;
130+
GRANT DELETE ON *.* TO regular;
131+
CREATE DATABASE test1;
132+
DROP TABLE IF EXISTS test1.t_trigger_test1;
133+
Warnings:
134+
Note 1051 Unknown table 'test1.t_trigger_test1'
135+
CREATE TABLE test1.t_trigger_test1 (
136+
id INT AUTO_INCREMENT PRIMARY KEY,
137+
name VARCHAR(50),
138+
note VARCHAR(100)
139+
);
140+
CREATE TRIGGER test1.trg_before_insert
141+
BEFORE INSERT ON test1.t_trigger_test1
142+
FOR EACH ROW
143+
BEGIN
144+
SET NEW.name = CONCAT('BEFORE_', NEW.name);
145+
END |
146+
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING *;
147+
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
148+
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING id, name, note;
149+
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
150+
# same for DELETE because delete with "WHERE" still requires to
151+
# read from the table, which basically means having select privileges
152+
DELETE FROM test1.t_trigger_test1 WHERE id=1;
153+
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
154+
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING id;
155+
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
156+
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING *;
157+
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
158+
DELETE FROM test1.t_trigger_test1 RETURNING *;
159+
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
160+
DELETE FROM test1.t_trigger_test1 RETURNING id;
161+
ERROR 42000: SELECT command denied to user 'regular'@'localhost' for column 'id' in table 't_trigger_test1'
162+
DELETE FROM test1.t_trigger_test1;
163+
DROP TRIGGER test1.trg_before_insert;
164+
DROP TABLE test1.t_trigger_test1;
165+
DROP USER regular;
166+
DROP DATABASE test1;

mysql-test/main/insert_notembedded.test

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,60 @@ DROP DATABASE meow;
158158

159159
set local sql_mode=default;
160160
set global sql_mode=default;
161+
162+
--echo #
163+
--echo # MDEV-37950: INSERT ... RETURNING exposes columns for which
164+
--echo # the user lacks SELECT privilege
165+
--echo #
166+
CREATE USER regular;
167+
GRANT INSERT ON *.* TO regular;
168+
GRANT DELETE ON *.* TO regular;
169+
170+
CREATE DATABASE test1;
171+
DROP TABLE IF EXISTS test1.t_trigger_test1;
172+
CREATE TABLE test1.t_trigger_test1 (
173+
id INT AUTO_INCREMENT PRIMARY KEY,
174+
name VARCHAR(50),
175+
note VARCHAR(100)
176+
);
177+
DELIMITER |;
178+
CREATE TRIGGER test1.trg_before_insert
179+
BEFORE INSERT ON test1.t_trigger_test1
180+
FOR EACH ROW
181+
BEGIN
182+
SET NEW.name = CONCAT('BEFORE_', NEW.name);
183+
END |
184+
DELIMITER ;|
185+
186+
change_user regular;
187+
188+
--error ER_COLUMNACCESS_DENIED_ERROR
189+
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING *;
190+
--error ER_COLUMNACCESS_DENIED_ERROR
191+
INSERT INTO test1.t_trigger_test1 (name) VALUES ('Alice') RETURNING id, name, note;
192+
193+
--echo # same for DELETE because delete with "WHERE" still requires to
194+
--echo # read from the table, which basically means having select privileges
195+
196+
--error ER_COLUMNACCESS_DENIED_ERROR
197+
DELETE FROM test1.t_trigger_test1 WHERE id=1;
198+
199+
--error ER_COLUMNACCESS_DENIED_ERROR
200+
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING id;
201+
202+
--error ER_COLUMNACCESS_DENIED_ERROR
203+
DELETE FROM test1.t_trigger_test1 WHERE id=1 RETURNING *;
204+
205+
--error ER_COLUMNACCESS_DENIED_ERROR
206+
DELETE FROM test1.t_trigger_test1 RETURNING *;
207+
208+
--error ER_COLUMNACCESS_DENIED_ERROR
209+
DELETE FROM test1.t_trigger_test1 RETURNING id;
210+
211+
DELETE FROM test1.t_trigger_test1;
212+
213+
change_user root;
214+
DROP TRIGGER test1.trg_before_insert;
215+
DROP TABLE test1.t_trigger_test1;
216+
DROP USER regular;
217+
DROP DATABASE test1;

sql/sql_base.cc

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7909,12 +7909,23 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
79097909

79107910
int setup_returning_fields(THD* thd, TABLE_LIST* table_list)
79117911
{
7912+
GRANT_INFO *saved_grant;
7913+
int res= 0;
7914+
79127915
if (!thd->lex->has_returning())
79137916
return 0;
7914-
return setup_wild(thd, table_list, thd->lex->returning()->item_list, NULL,
7915-
thd->lex->returning(), true)
7916-
|| setup_fields(thd, Ref_ptr_array(), thd->lex->returning()->item_list,
7917-
MARK_COLUMNS_READ, NULL, NULL, 0, THD_WHERE::RETURNING);
7917+
7918+
saved_grant= &table_list->table->grant;
7919+
table_list->table->grant.want_privilege|= SELECT_ACL;
7920+
7921+
res= setup_wild(thd, table_list, thd->lex->returning()->item_list, NULL,
7922+
thd->lex->returning(), true)
7923+
|| setup_fields(thd, Ref_ptr_array(), thd->lex->returning()->item_list,
7924+
MARK_COLUMNS_READ, NULL, NULL, 0, THD_WHERE::RETURNING);
7925+
7926+
table_list->table->grant= *saved_grant;
7927+
7928+
return res;
79187929
}
79197930

79207931

0 commit comments

Comments
 (0)