Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid cache of field privileges in procedure request after their changes [CORE5108] #5392

Open
firebird-automations opened this issue Feb 9, 2016 · 3 comments

Comments

@firebird-automations
Copy link
Collaborator

Submitted by: @romansimakov

To reproduce it on SuperServer execute:
-------------------------------------------------------
roman:bin$ ./isql
Use CONNECT or CREATE DATABASE to specify a database
SQL> connect 'localhost:/tmp/429.fdb';
Database: 'localhost:/tmp/429.fdb'
SQL> create table t(i integer);
SQL> insert into t values (1);
SQL> commit;
SQL> ^Droman:bin$
roman:bin$ ./gsec
GSEC> add test -pw test
GSEC> roman:bin$
roman:bin$ ./isql -user test -password test
Use CONNECT or CREATE DATABASE to specify a database
SQL> connect 'localhost:/tmp/429.fdb';
Database: 'localhost:/tmp/429.fdb', User: test
SQL> set term ^;
SQL> edit^
SQL> set term ;^
SQL> commit;
SQL> show procedures;
Procedure Name Invalid Dependency, Type
================================= ======= =====================================
P T, Table
SQL> execute procedure p;
Statement failed, SQLSTATE = 28000
no permission for update/write access to TABLE T
SQL> ^Droman:bin$
roman:bin$ ./isql
Use CONNECT or CREATE DATABASE to specify a database
SQL> connect 'localhost:/tmp/429.fdb';
Database: 'localhost:/tmp/429.fdb'
SQL> grant update(i) on t to test;
SQL> commit;
SQL> ^Droman:bin$
roman:bin$ ./isql -user test -password test
Use CONNECT or CREATE DATABASE to specify a database
SQL> connect 'localhost:/tmp/429.fdb';
Database: 'localhost:/tmp/429.fdb', User: test
SQL> execute procedure p;
Statement failed, SQLSTATE = 28000
no permission for update/write access to COLUMN T.I
SQL> update t set i = 3;
SQL> ^Droman:bin$
roman:bin$ ./isql
Use CONNECT or CREATE DATABASE to specify a database
SQL> connect 'localhost:/tmp/429.fdb';
Database: 'localhost:/tmp/429.fdb'
SQL> select * from t;

       I

============
3
-------------------------------------------------------
Procedure which is used in test case declared as:
create procedure p
as
begin
update t set i = 2;
end

@firebird-automations
Copy link
Collaborator Author

Modified by: @romansimakov

assignee: Roman Simakov [ roman-simakov ]

@firebird-automations
Copy link
Collaborator Author

Commented by: @romansimakov

When procedure is compiled fields use default security class, but after granting field level privileges their security classes are changed which cause to check relation security class instead of field security class. I suggest to make field security class permanent and generate them when field is defining like in patch:

Author: Roman Simakov <mailto:roman.simakov@gmail.com>
Date: Fri Feb 5 16:43:56 2016 +0300

Fixed [CORE5108](https://github.com/FirebirdSQL/firebird/issues?q=CORE5108+in%3Atitle)\.

diff --git a/src/jrd/drq.h b/src/jrd/drq.h
index f034ee9..f067998 100644
--- a/src/jrd/drq.h
+++ b/src/jrd/drq.h
@@ -219,6 +219,7 @@ const int drq_l_xcp_name = 165; // lookup exception name
const int drq_l_gen_name = 166; // lookup generator name
const int drq_e_grant3 = 167; // revoke all on all
const int drq_s2_difference = 168; // Store backup difference file, DYN_mod's change_backup_mode
-const int drq_MAX = 169;
+const int drq_g_nxt_fsc_id = 169; // generate next field security class id
+const int drq_MAX = 170;

#⁠endif // JRD_DRQ_H
diff --git a/src/jrd/dyn_def.epp b/src/jrd/dyn_def.epp
index 39bfc12..3bbca45 100644
--- a/src/jrd/dyn_def.epp
+++ b/src/jrd/dyn_def.epp
@@ -2761,6 +2761,14 @@ void DYN_define_local_field(Global* gbl,
DYN_execute(gbl, ptr, relation_name, &tmp, NULL, NULL, NULL);
}

+ // If security class is not defined explicitly we generate it automatically
+ if (RFR.RDB$SECURITY_CLASS.NULL)
+ {
+ RFR.RDB$SECURITY_CLASS.NULL = FALSE;
+ sprintf(RFR.RDB$SECURITY_CLASS, "%s%" SQUADFORMAT, SQL_FLD_SECCLASS_PREFIX,
+ DYN_UTIL_gen_unique_id(tdbb, gbl, drq_g_nxt_fsc_id, "RDB$SECURITY_CLASS"));
+ }
+
if (has_default && DYN_UTIL_is_array(tdbb, gbl, RFR.RDB$FIELD_SOURCE))
{
DYN_error_punt(false, 226, RFR.RDB$FIELD_SOURCE);
@@ -4050,6 +4058,10 @@ void DYN_define_sql_field(Global* gbl,
RFR.RDB$DEFAULT_VALUE.NULL = TRUE;
RFR.RDB$COLLATION_ID.NULL = TRUE;

+ RFR.RDB$SECURITY_CLASS.NULL = FALSE;
+ sprintf(RFR.RDB$SECURITY_CLASS, "%s%" SQUADFORMAT, SQL_FLD_SECCLASS_PREFIX,
+ DYN_UTIL_gen_unique_id(tdbb, gbl, drq_g_nxt_fsc_id, "RDB$SECURITY_CLASS"));
+
old_request = request;
const SSHORT old_id = id;
request = CMP_find_request(tdbb, drq_s_sql_gfld, DYN_REQUESTS);

@firebird-automations
Copy link
Collaborator Author

Commented by: @romansimakov

#81

I implemented another way to fix. If field level permissions were changed we reset metadata cache. I did not implement selection of procedures to reset which depend on changed field since it overhead which may not be good and cost about the same as restore metadata cache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants