Skip to content

Commit 4f66c93

Browse files
committed
Update sepgsql to add mandatory access control for TRUNCATE
Use SELinux "db_table: { truncate }" to check if permission is granted to TRUNCATE. Update example SELinux policy to grant needed permission for TRUNCATE. Add new regression test to demonstrate a positive and negative cases. Test will only be run if the loaded SELinux policy has the "db_table: { truncate }" permission. Makes use of recent commit which added object TRUNCATE hook. Patch by Yuli Khodorkovskiy with minor editorialization by me. Not back-patched because the object TRUNCATE hook was not. Author: Yuli Khodorkovskiy Reviewed-by: Joe Conway Discussion: https://postgr.es/m/CAFL5wJcomybj1Xdw7qWmPJRpGuFukKgNrDb6uVBaCMgYS9dkaA%40mail.gmail.com
1 parent f7a2002 commit 4f66c93

File tree

8 files changed

+152
-1
lines changed

8 files changed

+152
-1
lines changed

contrib/sepgsql/expected/truncate.out

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
--
2+
-- Regression Test for TRUNCATE
3+
--
4+
--
5+
-- Setup
6+
--
7+
CREATE TABLE julio_claudians (name text, birth_date date);
8+
SECURITY LABEL ON TABLE julio_claudians IS 'system_u:object_r:sepgsql_regtest_foo_table_t:s0';
9+
INSERT INTO julio_claudians VALUES ('Augustus', 'September 23, 63 BC'), ('Tiberius', 'November 16, 42 BC'), ('Caligula', 'August 31, 0012'), ('Claudius', 'August 1, 0010'), ('Nero', 'December 15, 0037');
10+
CREATE TABLE flavians (name text, birth_date date);
11+
SECURITY LABEL ON TABLE flavians IS 'system_u:object_r:sepgsql_table_t:s0';
12+
INSERT INTO flavians VALUES ('Vespasian', 'November 17, 0009'), ('Titus', 'December 30, 0039'), ('Domitian', 'October 24, 0051');
13+
SELECT * from julio_claudians;
14+
name | birth_date
15+
----------+---------------
16+
Augustus | 09-23-0063 BC
17+
Tiberius | 11-16-0042 BC
18+
Caligula | 08-31-0012
19+
Claudius | 08-01-0010
20+
Nero | 12-15-0037
21+
(5 rows)
22+
23+
SELECT * from flavians;
24+
name | birth_date
25+
-----------+------------
26+
Vespasian | 11-17-0009
27+
Titus | 12-30-0039
28+
Domitian | 10-24-0051
29+
(3 rows)
30+
31+
TRUNCATE TABLE julio_claudians; -- ok
32+
TRUNCATE TABLE flavians; -- failed
33+
ERROR: SELinux: security policy violation
34+
SELECT * from julio_claudians;
35+
name | birth_date
36+
------+------------
37+
(0 rows)
38+
39+
SELECT * from flavians;
40+
name | birth_date
41+
-----------+------------
42+
Vespasian | 11-17-0009
43+
Titus | 12-30-0039
44+
Domitian | 10-24-0051
45+
(3 rows)
46+

contrib/sepgsql/hooks.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,20 @@ sepgsql_object_access(ObjectAccessType access,
188188
}
189189
break;
190190

191+
case OAT_TRUNCATE:
192+
{
193+
switch (classId)
194+
{
195+
case RelationRelationId:
196+
sepgsql_relation_truncate(objectId);
197+
break;
198+
default:
199+
/* Ignore unsupported object classes */
200+
break;
201+
}
202+
}
203+
break;
204+
191205
case OAT_POST_ALTER:
192206
{
193207
ObjectAccessPostAlter *pa_arg = arg;

contrib/sepgsql/relation.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,46 @@ sepgsql_relation_drop(Oid relOid)
516516
}
517517
}
518518

519+
/*
520+
* sepgsql_relation_truncate
521+
*
522+
* Check privileges to TRUNCATE the supplied relation.
523+
*/
524+
void
525+
sepgsql_relation_truncate(Oid relOid)
526+
{
527+
ObjectAddress object;
528+
char *audit_name;
529+
uint16_t tclass = 0;
530+
char relkind = get_rel_relkind(relOid);
531+
532+
switch (relkind)
533+
{
534+
case RELKIND_RELATION:
535+
case RELKIND_PARTITIONED_TABLE:
536+
tclass = SEPG_CLASS_DB_TABLE;
537+
break;
538+
default:
539+
/* ignore other relkinds */
540+
return;
541+
}
542+
543+
/*
544+
* check db_table:{truncate} permission
545+
*/
546+
object.classId = RelationRelationId;
547+
object.objectId = relOid;
548+
object.objectSubId = 0;
549+
audit_name = getObjectIdentity(&object);
550+
551+
sepgsql_avc_check_perms(&object,
552+
tclass,
553+
SEPG_DB_TABLE__TRUNCATE,
554+
audit_name,
555+
true);
556+
pfree(audit_name);
557+
}
558+
519559
/*
520560
* sepgsql_relation_relabel
521561
*

contrib/sepgsql/selinux.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,9 @@ static struct
359359
{
360360
"lock", SEPG_DB_TABLE__LOCK
361361
},
362+
{
363+
"truncate", SEPG_DB_TABLE__TRUNCATE
364+
},
362365
{
363366
NULL, 0UL
364367
},

contrib/sepgsql/sepgsql-regtest.te

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,14 @@ allow sepgsql_regtest_var_t sepgsql_regtest_var_table_t:db_table { getattr selec
150150
allow sepgsql_regtest_var_t sepgsql_regtest_var_table_t:db_column { getattr select update insert };
151151
allow sepgsql_regtest_var_t sepgsql_regtest_var_table_t:db_tuple { select update insert delete };
152152

153+
optional_policy(`
154+
gen_require(`
155+
class db_table { truncate };
156+
')
157+
158+
allow sepgsql_regtest_superuser_t sepgsql_regtest_foo_table_t:db_table { truncate };
159+
')
160+
153161
optional_policy(`
154162
gen_require(`
155163
role unconfined_r;

contrib/sepgsql/sepgsql.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@
145145
#define SEPG_DB_TABLE__INSERT (1<<8)
146146
#define SEPG_DB_TABLE__DELETE (1<<9)
147147
#define SEPG_DB_TABLE__LOCK (1<<10)
148+
#define SEPG_DB_TABLE__TRUNCATE (1<<11)
148149

149150
#define SEPG_DB_SEQUENCE__CREATE (SEPG_DB_DATABASE__CREATE)
150151
#define SEPG_DB_SEQUENCE__DROP (SEPG_DB_DATABASE__DROP)
@@ -312,6 +313,7 @@ extern void sepgsql_attribute_relabel(Oid relOid, AttrNumber attnum,
312313
extern void sepgsql_attribute_setattr(Oid relOid, AttrNumber attnum);
313314
extern void sepgsql_relation_post_create(Oid relOid);
314315
extern void sepgsql_relation_drop(Oid relOid);
316+
extern void sepgsql_relation_truncate(Oid relOid);
315317
extern void sepgsql_relation_relabel(Oid relOid, const char *seclabel);
316318
extern void sepgsql_relation_setattr(Oid relOid);
317319

contrib/sepgsql/sql/truncate.sql

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--
2+
-- Regression Test for TRUNCATE
3+
--
4+
5+
--
6+
-- Setup
7+
--
8+
CREATE TABLE julio_claudians (name text, birth_date date);
9+
SECURITY LABEL ON TABLE julio_claudians IS 'system_u:object_r:sepgsql_regtest_foo_table_t:s0';
10+
INSERT INTO julio_claudians VALUES ('Augustus', 'September 23, 63 BC'), ('Tiberius', 'November 16, 42 BC'), ('Caligula', 'August 31, 0012'), ('Claudius', 'August 1, 0010'), ('Nero', 'December 15, 0037');
11+
12+
CREATE TABLE flavians (name text, birth_date date);
13+
SECURITY LABEL ON TABLE flavians IS 'system_u:object_r:sepgsql_table_t:s0';
14+
15+
INSERT INTO flavians VALUES ('Vespasian', 'November 17, 0009'), ('Titus', 'December 30, 0039'), ('Domitian', 'October 24, 0051');
16+
17+
SELECT * from julio_claudians;
18+
SELECT * from flavians;
19+
20+
TRUNCATE TABLE julio_claudians; -- ok
21+
TRUNCATE TABLE flavians; -- failed
22+
23+
SELECT * from julio_claudians;
24+
SELECT * from flavians;

contrib/sepgsql/test_sepgsql

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,20 @@ echo "found ${NUM}"
287287
echo
288288
echo "============== running sepgsql regression tests =============="
289289

290-
make REGRESS="label dml ddl alter misc" REGRESS_OPTS="--launcher ./launcher" installcheck
290+
tests="label dml ddl alter misc"
291291

292+
# Check if the truncate permission exists in the loaded policy, and if so,
293+
# run the truncate test
294+
#
295+
# Testing the TRUNCATE regression test can be done by manually adding
296+
# the permission with CIL if necessary:
297+
# sudo semodule -cE base
298+
# sudo sed -i -E 's/(class db_table.*?) \)/\1 truncate\)/' base.cil
299+
# sudo semodule -i base.cil
300+
301+
if [ -f /sys/fs/selinux/class/db_table/perms/truncate ]; then
302+
tests+=" truncate"
303+
fi
304+
305+
make REGRESS="$tests" REGRESS_OPTS="--launcher ./launcher" installcheck
292306
# exit with the exit code provided by "make"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy