diff --git a/.cvsignore b/.cvsignore deleted file mode 100644 index 19279bd..0000000 --- a/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -postgresql-8.4.1.tar.bz2 diff --git a/Makefile b/Makefile deleted file mode 100644 index dad7c56..0000000 --- a/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# Makefile for source rpm: sepostgresql -# $Id$ -NAME := sepostgresql -SPECFILE = $(firstword $(wildcard *.spec)) - -define find-makefile-common -for d in common ../common ../../common ; do if [ -f $$d/Makefile.common ] ; then if [ -f $$d/CVS/Root -a -w $$/Makefile.common ] ; then cd $$d ; cvs -Q update ; fi ; echo "$$d/Makefile.common" ; break ; fi ; done -endef - -MAKEFILE_COMMON := $(shell $(find-makefile-common)) - -ifeq ($(MAKEFILE_COMMON),) -# attept a checkout -define checkout-makefile-common -test -f CVS/Root && { cvs -Q -d $$(cat CVS/Root) checkout common && echo "common/Makefile.common" ; } || { echo "ERROR: I can't figure out how to checkout the 'common' module." ; exit -1 ; } >&2 -endef - -MAKEFILE_COMMON := $(shell $(checkout-makefile-common)) -endif - -include $(MAKEFILE_COMMON) diff --git a/dead.package b/dead.package new file mode 100644 index 0000000..e1c0fac --- /dev/null +++ b/dead.package @@ -0,0 +1 @@ +SE-PostgreSQL was merged into mainstream as contrib/sepgsql extension diff --git a/sepostgresql-8.4.patch b/sepostgresql-8.4.patch deleted file mode 100644 index 4e35401..0000000 --- a/sepostgresql-8.4.patch +++ /dev/null @@ -1,15483 +0,0 @@ -diff -Nrpc base/configure sepgsql/configure -*** base/configure Sun Sep 6 19:40:49 2009 ---- sepgsql/configure Sun Sep 6 19:53:10 2009 -*************** with_libxml -*** 710,715 **** ---- 710,716 ---- - with_libxslt - with_system_tzdata - with_zlib -+ enable_selinux - GREP - EGREP - ELF_SYS -*************** Optional Features: -*** 1378,1383 **** ---- 1379,1385 ---- - --enable-thread-safety make client libraries thread-safe - --enable-thread-safety-force - force thread-safety despite thread test failure -+ --enable-selinux enable to build with SELinux support - --disable-float4-byval disable float4 passed by value - --disable-float8-byval disable float8 passed by value - --disable-largefile omit support for large files -*************** fi -*** 5532,5537 **** ---- 5534,5645 ---- - - - # -+ # SELinux support -+ # -+ -+ pgac_args="$pgac_args enable_selinux" -+ -+ # Check whether --enable-selinux was given. -+ if test "${enable_selinux+set}" = set; then -+ enableval=$enable_selinux; -+ case $enableval in -+ yes) -+ : -+ ;; -+ no) -+ : -+ ;; -+ *) -+ { { echo "$as_me:$LINENO: error: no argument expected for --enable-selinux option" >&5 -+ echo "$as_me: error: no argument expected for --enable-selinux option" >&2;} -+ { (exit 1); exit 1; }; } -+ ;; -+ esac -+ -+ else -+ enable_selinux=no -+ -+ fi -+ -+ -+ if test "$enable_selinux" = yes; then -+ { echo "$as_me:$LINENO: checking for avc_netlink_loop in -lselinux" >&5 -+ echo $ECHO_N "checking for avc_netlink_loop in -lselinux... $ECHO_C" >&6; } -+ if test "${ac_cv_lib_selinux_avc_netlink_loop+set}" = set; then -+ echo $ECHO_N "(cached) $ECHO_C" >&6 -+ else -+ ac_check_lib_save_LIBS=$LIBS -+ LIBS="-lselinux $LIBS" -+ cat >conftest.$ac_ext <<_ACEOF -+ /* confdefs.h. */ -+ _ACEOF -+ cat confdefs.h >>conftest.$ac_ext -+ cat >>conftest.$ac_ext <<_ACEOF -+ /* end confdefs.h. */ -+ -+ /* Override any GCC internal prototype to avoid an error. -+ Use char because int might match the return type of a GCC -+ builtin and then its argument prototype would still apply. */ -+ #ifdef __cplusplus -+ extern "C" -+ #endif -+ char avc_netlink_loop (); -+ int -+ main () -+ { -+ return avc_netlink_loop (); -+ ; -+ return 0; -+ } -+ _ACEOF -+ rm -f conftest.$ac_objext conftest$ac_exeext -+ if { (ac_try="$ac_link" -+ case "(($ac_try" in -+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; -+ *) ac_try_echo=$ac_try;; -+ esac -+ eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 -+ (eval "$ac_link") 2>conftest.er1 -+ ac_status=$? -+ grep -v '^ *+' conftest.er1 >conftest.err -+ rm -f conftest.er1 -+ cat conftest.err >&5 -+ echo "$as_me:$LINENO: \$? = $ac_status" >&5 -+ (exit $ac_status); } && { -+ test -z "$ac_c_werror_flag" || -+ test ! -s conftest.err -+ } && test -s conftest$ac_exeext && -+ $as_test_x conftest$ac_exeext; then -+ ac_cv_lib_selinux_avc_netlink_loop=yes -+ else -+ echo "$as_me: failed program was:" >&5 -+ sed 's/^/| /' conftest.$ac_ext >&5 -+ -+ ac_cv_lib_selinux_avc_netlink_loop=no -+ fi -+ -+ rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ -+ conftest$ac_exeext conftest.$ac_ext -+ LIBS=$ac_check_lib_save_LIBS -+ fi -+ { echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_avc_netlink_loop" >&5 -+ echo "${ECHO_T}$ac_cv_lib_selinux_avc_netlink_loop" >&6; } -+ if test $ac_cv_lib_selinux_avc_netlink_loop = yes; then -+ -+ cat >>confdefs.h <<_ACEOF -+ #define HAVE_SELINUX 1 -+ _ACEOF -+ -+ -+ else -+ { { echo "$as_me:$LINENO: error: \"--enable-selinux requires libselinux.\"" >&5 -+ echo "$as_me: error: \"--enable-selinux requires libselinux.\"" >&2;} -+ { (exit 1); exit 1; }; } -+ fi -+ -+ fi -+ -+ # - # Elf - # - -*************** with_libxml!$with_libxml$ac_delim -*** 28137,28147 **** - with_libxslt!$with_libxslt$ac_delim - with_system_tzdata!$with_system_tzdata$ac_delim - with_zlib!$with_zlib$ac_delim - GREP!$GREP$ac_delim - EGREP!$EGREP$ac_delim - ELF_SYS!$ELF_SYS$ac_delim - LDFLAGS_SL!$LDFLAGS_SL$ac_delim -- LD!$LD$ac_delim - _ACEOF - - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then ---- 28245,28255 ---- - with_libxslt!$with_libxslt$ac_delim - with_system_tzdata!$with_system_tzdata$ac_delim - with_zlib!$with_zlib$ac_delim -+ enable_selinux!$enable_selinux$ac_delim - GREP!$GREP$ac_delim - EGREP!$EGREP$ac_delim - ELF_SYS!$ELF_SYS$ac_delim - LDFLAGS_SL!$LDFLAGS_SL$ac_delim - _ACEOF - - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then -*************** _ACEOF -*** 28183,28188 **** ---- 28291,28297 ---- - ac_delim='%!_!# ' - for ac_last_try in false false false false false :; do - cat >conf$$subs.sed <<_ACEOF -+ LD!$LD$ac_delim - with_gnu_ld!$with_gnu_ld$ac_delim - ld_R_works!$ld_R_works$ac_delim - RANLIB!$RANLIB$ac_delim -*************** vpath_build!$vpath_build$ac_delim -*** 28245,28251 **** - LTLIBOBJS!$LTLIBOBJS$ac_delim - _ACEOF - -! if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 60; then - break - elif $ac_last_try; then - { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 ---- 28354,28360 ---- - LTLIBOBJS!$LTLIBOBJS$ac_delim - _ACEOF - -! if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 61; then - break - elif $ac_last_try; then - { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 -diff -Nrpc base/configure.in sepgsql/configure.in -*** base/configure.in Sun Sep 6 19:40:49 2009 ---- sepgsql/configure.in Sun Sep 6 19:53:10 2009 -*************** PGAC_ARG_BOOL(with, zlib, yes, -*** 764,769 **** ---- 764,782 ---- - AC_SUBST(with_zlib) - - # -+ # SELinux support -+ # -+ PGAC_ARG_BOOL(enable, selinux, no, -+ [enable to build with SELinux support]) -+ if test "$enable_selinux" = yes; then -+ AC_CHECK_LIB(selinux, avc_netlink_loop, -+ AC_DEFINE_UNQUOTED(HAVE_SELINUX, 1, -+ [SE-PostgreSQL feature is enabled]) -+ AC_SUBST(enable_selinux), -+ AC_MSG_ERROR("--enable-selinux requires libselinux.")) -+ fi -+ -+ # - # Elf - # - -diff -Nrpc base/src/Makefile.global.in sepgsql/src/Makefile.global.in -*** base/src/Makefile.global.in Tue Jun 30 01:26:47 2009 ---- sepgsql/src/Makefile.global.in Wed Jul 15 19:35:52 2009 -*************** enable_rpath = @enable_rpath@ -*** 164,169 **** ---- 164,170 ---- - enable_nls = @enable_nls@ - enable_debug = @enable_debug@ - enable_dtrace = @enable_dtrace@ -+ enable_selinux = @enable_selinux@ - enable_coverage = @enable_coverage@ - enable_thread_safety = @enable_thread_safety@ - -diff -Nrpc base/src/backend/Makefile sepgsql/src/backend/Makefile -*** base/src/backend/Makefile Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/Makefile Wed Jul 15 19:35:52 2009 -*************** include $(top_builddir)/src/Makefile.glo -*** 16,22 **** - - SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \ - main nodes optimizer port postmaster regex rewrite \ -! storage tcop tsearch utils $(top_builddir)/src/timezone - - include $(srcdir)/common.mk - ---- 16,22 ---- - - SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \ - main nodes optimizer port postmaster regex rewrite \ -! security storage tcop tsearch utils $(top_builddir)/src/timezone - - include $(srcdir)/common.mk - -*************** LIBS := $(filter-out -lpgport, $(LIBS)) -*** 34,39 **** ---- 34,44 ---- - # The backend doesn't need everything that's in LIBS, however - LIBS := $(filter-out -lz -lreadline -ledit -ltermcap -lncurses -lcurses, $(LIBS)) - -+ # SELinux needs libselinux -+ ifeq ($(enable_selinux), yes) -+ LIBS += -lselinux -+ endif -+ - ########################################################################## - - all: submake-libpgport postgres $(POSTGRES_IMP) -diff -Nrpc base/src/backend/access/common/heaptuple.c sepgsql/src/backend/access/common/heaptuple.c -*** base/src/backend/access/common/heaptuple.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/access/common/heaptuple.c Thu Sep 10 15:18:03 2009 -*************** -*** 60,65 **** ---- 60,66 ---- - #include "access/heapam.h" - #include "access/sysattr.h" - #include "access/tuptoaster.h" -+ #include "catalog/pg_security.h" - #include "executor/tuptable.h" - - -*************** heap_attisnull(HeapTuple tup, int attnum -*** 287,292 **** ---- 288,294 ---- - case MinCommandIdAttributeNumber: - case MaxTransactionIdAttributeNumber: - case MaxCommandIdAttributeNumber: -+ case SecurityAttributeNumber: - /* these are never null */ - break; - -*************** heap_getsysattr(HeapTuple tup, int attnu -*** 599,604 **** ---- 601,609 ---- - case TableOidAttributeNumber: - result = ObjectIdGetDatum(tup->t_tableOid); - break; -+ case SecurityAttributeNumber: -+ result = securitySysattSecLabelOut(tup->t_tableOid, tup); -+ break; - default: - elog(ERROR, "invalid attnum: %d", attnum); - result = 0; /* keep compiler quiet */ -*************** heap_form_tuple(TupleDesc tupleDescripto -*** 722,727 **** ---- 727,734 ---- - - if (tupleDescriptor->tdhasoid) - len += sizeof(Oid); -+ if (tupleDescriptor->tdhassecid) -+ len += sizeof(Oid); - - hoff = len = MAXALIGN(len); /* align user data safely */ - -*************** heap_form_tuple(TupleDesc tupleDescripto -*** 753,758 **** ---- 760,767 ---- - - if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */ - td->t_infomask = HEAP_HASOID; -+ if (tupleDescriptor->tdhassecid) -+ td->t_infomask |= HEAP_HASSECID; - - heap_fill_tuple(tupleDescriptor, - values, -*************** heap_modify_tuple(HeapTuple tuple, -*** 864,869 **** ---- 873,880 ---- - newTuple->t_tableOid = tuple->t_tableOid; - if (tupleDesc->tdhasoid) - HeapTupleSetOid(newTuple, HeapTupleGetOid(tuple)); -+ if (HeapTupleHasSecid(newTuple)) -+ HeapTupleSetSecid(newTuple, HeapTupleGetSecid(tuple)); - - return newTuple; - } -*************** heap_form_minimal_tuple(TupleDesc tupleD -*** 1474,1479 **** ---- 1485,1492 ---- - - if (tupleDescriptor->tdhasoid) - len += sizeof(Oid); -+ if (tupleDescriptor->tdhassecid) -+ len += sizeof(Oid); - - hoff = len = MAXALIGN(len); /* align user data safely */ - -*************** heap_form_minimal_tuple(TupleDesc tupleD -*** 1495,1500 **** ---- 1508,1515 ---- - - if (tupleDescriptor->tdhasoid) /* else leave infomask = 0 */ - tuple->t_infomask = HEAP_HASOID; -+ if (tupleDescriptor->tdhassecid) -+ tuple->t_infomask |= HEAP_HASSECID; - - heap_fill_tuple(tupleDescriptor, - values, -diff -Nrpc base/src/backend/access/common/tupdesc.c sepgsql/src/backend/access/common/tupdesc.c -*** base/src/backend/access/common/tupdesc.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/access/common/tupdesc.c Wed Sep 9 13:14:37 2009 -*************** CreateTemplateTupleDesc(int natts, bool -*** 88,93 **** ---- 88,94 ---- - desc->tdtypeid = RECORDOID; - desc->tdtypmod = -1; - desc->tdhasoid = hasoid; -+ desc->tdhassecid = false; - desc->tdrefcount = -1; /* assume not reference-counted */ - - return desc; -*************** CreateTupleDesc(int natts, bool hasoid, -*** 121,126 **** ---- 122,128 ---- - desc->tdtypeid = RECORDOID; - desc->tdtypmod = -1; - desc->tdhasoid = hasoid; -+ desc->tdhassecid = false; - desc->tdrefcount = -1; /* assume not reference-counted */ - - return desc; -*************** CreateTupleDescCopy(TupleDesc tupdesc) -*** 150,155 **** ---- 152,158 ---- - - desc->tdtypeid = tupdesc->tdtypeid; - desc->tdtypmod = tupdesc->tdtypmod; -+ desc->tdhassecid = tupdesc->tdhassecid; - - return desc; - } -*************** CreateTupleDescCopyConstr(TupleDesc tupd -*** 208,213 **** ---- 211,217 ---- - - desc->tdtypeid = tupdesc->tdtypeid; - desc->tdtypmod = tupdesc->tdtypmod; -+ desc->tdhassecid = tupdesc->tdhassecid; - - return desc; - } -*************** equalTupleDescs(TupleDesc tupdesc1, Tupl -*** 314,319 **** ---- 318,325 ---- - return false; - if (tupdesc1->tdhasoid != tupdesc2->tdhasoid) - return false; -+ if (tupdesc1->tdhassecid != tupdesc2->tdhassecid) -+ return false; - - for (i = 0; i < tupdesc1->natts; i++) - { -diff -Nrpc base/src/backend/access/heap/heapam.c sepgsql/src/backend/access/heap/heapam.c -*** base/src/backend/access/heap/heapam.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/access/heap/heapam.c Tue Sep 8 23:55:48 2009 -*************** -*** 54,59 **** ---- 54,60 ---- - #include "catalog/namespace.h" - #include "miscadmin.h" - #include "pgstat.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/freespace.h" - #include "storage/lmgr.h" -*************** heap_insert(Relation relation, HeapTuple -*** 2016,2021 **** ---- 2017,2028 ---- - Oid - simple_heap_insert(Relation relation, HeapTuple tup) - { -+ /* -+ * SELinux assigns default security label for the tuple, -+ * but does not check permissions to the internal operations. -+ */ -+ sepgsqlHeapTupleInsert(relation, tup, true); -+ - return heap_insert(relation, tup, GetCurrentCommandId(true), 0, NULL); - } - -*************** l2: -*** 2558,2563 **** ---- 2565,2575 ---- - Assert(!(newtup->t_data->t_infomask & HEAP_HASOID)); - } - -+ /* Preserve SecurityId, if not changed */ -+ if (HeapTupleHasSecid(newtup) && -+ !OidIsValid(HeapTupleGetSecid(newtup))) -+ HeapTupleSetSecid(newtup, HeapTupleGetSecid(&oldtup)); -+ - newtup->t_data->t_infomask &= ~(HEAP_XACT_MASK); - newtup->t_data->t_infomask2 &= ~(HEAP2_XACT_MASK); - newtup->t_data->t_infomask |= (HEAP_XMAX_INVALID | HEAP_UPDATED); -diff -Nrpc base/src/backend/access/heap/tuptoaster.c sepgsql/src/backend/access/heap/tuptoaster.c -*** base/src/backend/access/heap/tuptoaster.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/access/heap/tuptoaster.c Tue Sep 8 23:55:48 2009 -*************** toast_insert_or_update(Relation rel, Hea -*** 591,596 **** ---- 591,598 ---- - hoff += BITMAPLEN(numAttrs); - if (newtup->t_data->t_infomask & HEAP_HASOID) - hoff += sizeof(Oid); -+ if (HeapTupleHasSecid(newtup)) -+ hoff += sizeof(Oid); - hoff = MAXALIGN(hoff); - Assert(hoff == newtup->t_data->t_hoff); - /* now convert to a limit on the tuple data size */ -*************** toast_insert_or_update(Relation rel, Hea -*** 864,869 **** ---- 866,873 ---- - new_len += BITMAPLEN(numAttrs); - if (olddata->t_infomask & HEAP_HASOID) - new_len += sizeof(Oid); -+ if (HeapTupleHeaderHasSecid(olddata)) -+ new_len += sizeof(Oid); - new_len = MAXALIGN(new_len); - Assert(new_len == olddata->t_hoff); - new_data_len = heap_compute_data_size(tupleDesc, -*************** toast_flatten_tuple_attribute(Datum valu -*** 1015,1020 **** ---- 1019,1026 ---- - new_len += BITMAPLEN(numAttrs); - if (olddata->t_infomask & HEAP_HASOID) - new_len += sizeof(Oid); -+ if (HeapTupleHeaderHasSecid(olddata)) -+ new_len += sizeof(Oid); - new_len = MAXALIGN(new_len); - Assert(new_len == olddata->t_hoff); - new_data_len = heap_compute_data_size(tupleDesc, -*************** toast_save_datum(Relation rel, Datum val -*** 1213,1218 **** ---- 1219,1230 ---- - memcpy(VARDATA(&chunk_data), data_p, chunk_size); - toasttup = heap_form_tuple(toasttupDesc, t_values, t_isnull); - -+ /* -+ * NOTE: SE-PostgreSQL does not assign any security label -+ * for tuples within the TOASTVALUE relation, so we omit -+ * to put sepgsqlHeapTupleInsert() hook here. -+ */ -+ - heap_insert(toastrel, toasttup, mycid, options, NULL); - - /* -diff -Nrpc base/src/backend/access/transam/xact.c sepgsql/src/backend/access/transam/xact.c -*** base/src/backend/access/transam/xact.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/access/transam/xact.c Sun Sep 6 19:31:39 2009 -*************** -*** 36,41 **** ---- 36,43 ---- - #include "libpq/be-fsstubs.h" - #include "miscadmin.h" - #include "pgstat.h" -+ #include "security/rowlevel.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/fd.h" - #include "storage/lmgr.h" -*************** typedef struct TransactionStateData -*** 140,145 **** ---- 142,148 ---- - Oid prevUser; /* previous CurrentUserId setting */ - bool prevSecDefCxt; /* previous SecurityDefinerContext setting */ - bool prevXactReadOnly; /* entry-time xact r/o state */ -+ int prevRowlv; /* previous Row-level control behavior */ - struct TransactionStateData *parent; /* back link to parent */ - } TransactionStateData; - -*************** static TransactionStateData TopTransacti -*** 168,173 **** ---- 171,177 ---- - InvalidOid, /* previous CurrentUserId setting */ - false, /* previous SecurityDefinerContext setting */ - false, /* entry-time xact r/o state */ -+ ROWLV_FILTER_MODE, /* previous Row-level control behavior */ - NULL /* link to parent state block */ - }; - -*************** StartTransaction(void) -*** 1524,1529 **** ---- 1528,1534 ---- - s->nChildXids = 0; - s->maxChildXids = 0; - GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt); -+ s->prevRowlv = rowlvGetPerformingMode(); - /* SecurityDefinerContext should never be set outside a transaction */ - Assert(!s->prevSecDefCxt); - -*************** AbortTransaction(void) -*** 2030,2035 **** ---- 2035,2050 ---- - SetUserIdAndContext(s->prevUser, s->prevSecDefCxt); - - /* -+ * Reset behavior of row-level access controls -+ */ -+ rowlvSetPerformingMode(s->prevRowlv); -+ -+ /* -+ * Reset access vector cache on error -+ */ -+ sepgsqlAvcReset(); -+ -+ /* - * do abort processing - */ - AfterTriggerEndXact(false); -*************** AbortSubTransaction(void) -*** 3873,3878 **** ---- 3888,3903 ---- - SetUserIdAndContext(s->prevUser, s->prevSecDefCxt); - - /* -+ * Reset behavior of row-level access controls -+ */ -+ rowlvSetPerformingMode(s->prevRowlv); -+ -+ /* -+ * Reset access vector cache on error -+ */ -+ sepgsqlAvcReset(); -+ -+ /* - * We can skip all this stuff if the subxact failed before creating a - * ResourceOwner... - */ -*************** PushTransaction(void) -*** 4014,4019 **** ---- 4039,4045 ---- - s->blockState = TBLOCK_SUBBEGIN; - GetUserIdAndContext(&s->prevUser, &s->prevSecDefCxt); - s->prevXactReadOnly = XactReadOnly; -+ s->prevRowlv = rowlvGetPerformingMode(); - - CurrentTransactionState = s; - -diff -Nrpc base/src/backend/bootstrap/bootparse.y sepgsql/src/backend/bootstrap/bootparse.y -*** base/src/backend/bootstrap/bootparse.y Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/bootstrap/bootparse.y Wed Jul 15 19:35:52 2009 -*************** -*** 42,47 **** ---- 42,48 ---- - #include "nodes/pg_list.h" - #include "nodes/primnodes.h" - #include "rewrite/prs2lock.h" -+ #include "security/sepgsql.h" - #include "storage/block.h" - #include "storage/fd.h" - #include "storage/ipc.h" -*************** Boot_CreateStmt: -*** 211,216 **** ---- 212,222 ---- - else - { - Oid id; -+ Oid *secLabels = -+ sepgsqlCreateTableColumns(NULL, -+ LexIDStr($5), -+ PG_CATALOG_NAMESPACE, -+ tupdesc, RELKIND_RELATION); - - id = heap_create_with_catalog(LexIDStr($5), - PG_CATALOG_NAMESPACE, -*************** Boot_CreateStmt: -*** 225,231 **** - 0, - ONCOMMIT_NOOP, - (Datum) 0, -! true); - elog(DEBUG4, "relation created with oid %u", id); - } - do_end(); ---- 231,238 ---- - 0, - ONCOMMIT_NOOP, - (Datum) 0, -! true, -! secLabels); - elog(DEBUG4, "relation created with oid %u", id); - } - do_end(); -diff -Nrpc base/src/backend/bootstrap/bootstrap.c sepgsql/src/backend/bootstrap/bootstrap.c -*** base/src/backend/bootstrap/bootstrap.c Fri Feb 20 22:15:36 2009 ---- sepgsql/src/backend/bootstrap/bootstrap.c Wed Sep 9 13:14:37 2009 -*************** -*** 26,31 **** ---- 26,32 ---- - #include "access/xact.h" - #include "bootstrap/bootstrap.h" - #include "catalog/index.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_type.h" - #include "libpq/pqsignal.h" - #include "miscadmin.h" -*************** BootstrapModeMain(void) -*** 497,502 **** ---- 498,508 ---- - */ - boot_yyparse(); - -+ /* -+ * Flush all the cached security label -+ */ -+ securityPostBootstrapingMode(); -+ - /* Perform a checkpoint to ensure everything's down to disk */ - SetProcessingMode(NormalProcessing); - CreateCheckPoint(CHECKPOINT_IS_SHUTDOWN | CHECKPOINT_IMMEDIATE); -*************** InsertOneTuple(Oid objectid) -*** 794,799 **** ---- 800,807 ---- - tupDesc = CreateTupleDesc(numattr, - RelationGetForm(boot_reldesc)->relhasoids, - attrtypes); -+ tupDesc->tdhassecid = RelationGetDescr(boot_reldesc)->tdhassecid; -+ - tuple = heap_form_tuple(tupDesc, values, Nulls); - if (objectid != (Oid) 0) - HeapTupleSetOid(tuple, objectid); -diff -Nrpc base/src/backend/catalog/Makefile sepgsql/src/backend/catalog/Makefile -*** base/src/backend/catalog/Makefile Wed May 13 11:30:07 2009 ---- sepgsql/src/backend/catalog/Makefile Wed Jul 15 19:30:50 2009 -*************** include $(top_builddir)/src/Makefile.glo -*** 13,19 **** - OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \ - pg_aggregate.o pg_constraint.o pg_conversion.o pg_depend.o pg_enum.o \ - pg_inherits.o pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o \ -! pg_shdepend.o pg_type.o storage.o toasting.o - - BKIFILES = postgres.bki postgres.description postgres.shdescription - ---- 13,19 ---- - OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \ - pg_aggregate.o pg_constraint.o pg_conversion.o pg_depend.o pg_enum.o \ - pg_inherits.o pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o \ -! pg_security.o pg_shdepend.o pg_type.o storage.o toasting.o - - BKIFILES = postgres.bki postgres.description postgres.shdescription - -*************** POSTGRES_BKI_SRCS = $(addprefix $(top_sr -*** 34,40 **** - pg_enum.h pg_namespace.h pg_conversion.h pg_depend.h \ - pg_database.h pg_tablespace.h pg_pltemplate.h \ - pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \ -! pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \ - pg_ts_parser.h pg_ts_template.h \ - pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \ - toasting.h indexing.h \ ---- 34,40 ---- - pg_enum.h pg_namespace.h pg_conversion.h pg_depend.h \ - pg_database.h pg_tablespace.h pg_pltemplate.h \ - pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \ -! pg_security.h pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \ - pg_ts_parser.h pg_ts_template.h \ - pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \ - toasting.h indexing.h \ -diff -Nrpc base/src/backend/catalog/aclchk.c sepgsql/src/backend/catalog/aclchk.c -*** base/src/backend/catalog/aclchk.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/aclchk.c Wed Sep 9 21:29:33 2009 -*************** -*** 35,40 **** ---- 35,41 ---- - #include "catalog/pg_operator.h" - #include "catalog/pg_opfamily.h" - #include "catalog/pg_proc.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_tablespace.h" - #include "catalog/pg_type.h" - #include "catalog/pg_ts_config.h" -*************** -*** 43,48 **** ---- 44,50 ---- - #include "foreign/foreign.h" - #include "miscadmin.h" - #include "parser/parse_func.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/fmgroids.h" - #include "utils/lsyscache.h" -*************** expand_all_col_privileges(Oid table_oid, -*** 672,677 **** ---- 674,685 ---- - if (curr_att == ObjectIdAttributeNumber && !classForm->relhasoids) - continue; - -+ /* Skip OID column, if it doesn't exist */ -+ if (curr_att == SecurityAttributeNumber && -+ (classForm->relkind != RELKIND_RELATION || -+ table_oid == SecurityRelationId)) -+ continue; -+ - /* Views don't have any system columns at all */ - if (classForm->relkind == RELKIND_VIEW && curr_att < 0) - continue; -*************** ExecGrant_Function(InternalGrant *istmt) -*** 1572,1577 **** ---- 1580,1587 ---- - funcId, grantorId, ACL_KIND_PROC, - NameStr(pg_proc_tuple->proname), - 0, NULL); -+ /* SELinux: db_procedure:{setattr} */ -+ sepgsqlCheckProcedureSetattr(funcId); - - /* - * Generate new ACL. -*************** ExecGrant_Namespace(InternalGrant *istmt -*** 1815,1820 **** ---- 1825,1833 ---- - NameStr(pg_namespace_tuple->nspname), - 0, NULL); - -+ /* SELinux: db_schema:{setattr} */ -+ sepgsqlCheckSchemaSetattr(nspid); -+ - /* - * Generate new ACL. - * -diff -Nrpc base/src/backend/catalog/catalog.c sepgsql/src/backend/catalog/catalog.c -*** base/src/backend/catalog/catalog.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/catalog.c Wed Jul 15 19:30:50 2009 -*************** -*** 31,36 **** ---- 31,37 ---- - #include "catalog/pg_database.h" - #include "catalog/pg_namespace.h" - #include "catalog/pg_pltemplate.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_shdepend.h" - #include "catalog/pg_shdescription.h" - #include "catalog/pg_tablespace.h" -*************** IsSharedRelation(Oid relationId) -*** 304,309 **** ---- 305,311 ---- - relationId == AuthMemRelationId || - relationId == DatabaseRelationId || - relationId == PLTemplateRelationId || -+ relationId == SecurityRelationId || - relationId == SharedDescriptionRelationId || - relationId == SharedDependRelationId || - relationId == TableSpaceRelationId) -*************** IsSharedRelation(Oid relationId) -*** 316,321 **** ---- 318,325 ---- - relationId == DatabaseNameIndexId || - relationId == DatabaseOidIndexId || - relationId == PLTemplateNameIndexId || -+ relationId == SecuritySecidIndexId || -+ relationId == SecuritySecattrIndexId || - relationId == SharedDescriptionObjIndexId || - relationId == SharedDependDependerIndexId || - relationId == SharedDependReferenceIndexId || -*************** IsSharedRelation(Oid relationId) -*** 327,332 **** ---- 331,338 ---- - relationId == PgAuthidToastIndex || - relationId == PgDatabaseToastTable || - relationId == PgDatabaseToastIndex || -+ relationId == PgSecurityToastTable || -+ relationId == PgSecurityToastIndex || - relationId == PgShdescriptionToastTable || - relationId == PgShdescriptionToastIndex) - return true; -diff -Nrpc base/src/backend/catalog/dependency.c sepgsql/src/backend/catalog/dependency.c -*** base/src/backend/catalog/dependency.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/catalog/dependency.c Mon Sep 7 00:55:45 2009 -*************** -*** 63,68 **** ---- 63,69 ---- - #include "nodes/nodeFuncs.h" - #include "parser/parsetree.h" - #include "rewrite/rewriteRemove.h" -+ #include "security/sepgsql.h" - #include "storage/lmgr.h" - #include "utils/builtins.h" - #include "utils/fmgroids.h" -*************** static void reportDependentObjects(const -*** 160,166 **** - DropBehavior behavior, - int msglevel, - const ObjectAddress *origObject); -! static void deleteOneObject(const ObjectAddress *object, Relation depRel); - static void doDeletion(const ObjectAddress *object); - static void AcquireDeletionLock(const ObjectAddress *object); - static void ReleaseDeletionLock(const ObjectAddress *object); ---- 161,168 ---- - DropBehavior behavior, - int msglevel, - const ObjectAddress *origObject); -! static void deleteOneObject(const ObjectAddress *object, -! Relation depRel, bool permission); - static void doDeletion(const ObjectAddress *object); - static void AcquireDeletionLock(const ObjectAddress *object); - static void ReleaseDeletionLock(const ObjectAddress *object); -*************** static void getOpFamilyDescription(Strin -*** 192,200 **** - * are variants on the same theme; if you change anything here you'll likely - * need to fix them too. - */ -! void -! performDeletion(const ObjectAddress *object, -! DropBehavior behavior) - { - Relation depRel; - ObjectAddresses *targetObjects; ---- 194,202 ---- - * are variants on the same theme; if you change anything here you'll likely - * need to fix them too. - */ -! static void -! performDeletionInternal(const ObjectAddress *object, -! DropBehavior behavior, bool permission) - { - Relation depRel; - ObjectAddresses *targetObjects; -*************** performDeletion(const ObjectAddress *obj -*** 240,246 **** - { - ObjectAddress *thisobj = targetObjects->refs + i; - -! deleteOneObject(thisobj, depRel); - } - - /* And clean up */ ---- 242,248 ---- - { - ObjectAddress *thisobj = targetObjects->refs + i; - -! deleteOneObject(thisobj, depRel, permission); - } - - /* And clean up */ -*************** performDeletion(const ObjectAddress *obj -*** 249,254 **** ---- 251,268 ---- - heap_close(depRel, RowExclusiveLock); - } - -+ void -+ performDeletion(const ObjectAddress *object, DropBehavior behavior) -+ { -+ performDeletionInternal(object, behavior, true); -+ } -+ -+ void -+ performDeletionNoPerms(const ObjectAddress *object, DropBehavior behavior) -+ { -+ performDeletionInternal(object, behavior, false); -+ } -+ - /* - * performMultipleDeletions: Similar to performDeletion, but act on multiple - * objects at once. -*************** performMultipleDeletions(const ObjectAdd -*** 322,328 **** - { - ObjectAddress *thisobj = targetObjects->refs + i; - -! deleteOneObject(thisobj, depRel); - } - - /* And clean up */ ---- 336,343 ---- - { - ObjectAddress *thisobj = targetObjects->refs + i; - -! /* currently, all the caller path need permission checks */ -! deleteOneObject(thisobj, depRel, true); - } - - /* And clean up */ -*************** deleteWhatDependsOn(const ObjectAddress -*** 393,399 **** - if (thisextra->flags & DEPFLAG_ORIGINAL) - continue; - -! deleteOneObject(thisobj, depRel); - } - - /* And clean up */ ---- 408,414 ---- - if (thisextra->flags & DEPFLAG_ORIGINAL) - continue; - -! deleteOneObject(thisobj, depRel, false); - } - - /* And clean up */ -*************** reportDependentObjects(const ObjectAddre -*** 942,954 **** - * depRel is the already-open pg_depend relation. - */ - static void -! deleteOneObject(const ObjectAddress *object, Relation depRel) - { - ScanKeyData key[3]; - int nkeys; - SysScanDesc scan; - HeapTuple tup; - - /* - * First remove any pg_depend records that link from this object to - * others. (Any records linking to this object should be gone already.) ---- 957,973 ---- - * depRel is the already-open pg_depend relation. - */ - static void -! deleteOneObject(const ObjectAddress *object, Relation depRel, bool permission) - { - ScanKeyData key[3]; - int nkeys; - SysScanDesc scan; - HeapTuple tup; - -+ /* SELinux checks db_xxx:{drop}, if necessary */ -+ if (permission) -+ sepgsqlCheckSysobjDrop(object); -+ - /* - * First remove any pg_depend records that link from this object to - * others. (Any records linking to this object should be gone already.) -diff -Nrpc base/src/backend/catalog/heap.c sepgsql/src/backend/catalog/heap.c -*** base/src/backend/catalog/heap.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/heap.c Wed Sep 9 16:47:01 2009 -*************** -*** 43,48 **** ---- 43,49 ---- - #include "catalog/pg_constraint.h" - #include "catalog/pg_inherits.h" - #include "catalog/pg_namespace.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_statistic.h" - #include "catalog/pg_tablespace.h" - #include "catalog/pg_type.h" -*************** -*** 56,61 **** ---- 57,63 ---- - #include "parser/parse_coerce.h" - #include "parser/parse_expr.h" - #include "parser/parse_relation.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/freespace.h" - #include "storage/smgr.h" -*************** static void AddNewRelationTuple(Relation -*** 74,80 **** - Oid new_rel_oid, Oid new_type_oid, - Oid relowner, - char relkind, -! Datum reloptions); - static Oid AddNewRelationType(const char *typeName, - Oid typeNamespace, - Oid new_rel_oid, ---- 76,83 ---- - Oid new_rel_oid, Oid new_type_oid, - Oid relowner, - char relkind, -! Datum reloptions, -! Oid *secLabels); - static Oid AddNewRelationType(const char *typeName, - Oid typeNamespace, - Oid new_rel_oid, -*************** static FormData_pg_attribute a7 = { -*** 158,164 **** - true, 'p', 'i', true, false, false, true, 0, {0} - }; - -! static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7}; - - /* - * This function returns a Form_pg_attribute pointer for a system attribute. ---- 161,176 ---- - true, 'p', 'i', true, false, false, true, 0, {0} - }; - -! /* -! * System columns for enhanced security features -! */ -! static FormData_pg_attribute a8 = { -! 0, {SecurityAttributeName}, TEXTOID, 0, -1, -! SecurityAttributeNumber, 0, -1, -1, -! false, 'x', 'i', true, false, false, true, 0, {0} -! }; -! -! static const Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7, &a8}; - - /* - * This function returns a Form_pg_attribute pointer for a system attribute. -*************** SystemAttributeByName(const char *attnam -*** 198,203 **** ---- 210,226 ---- - return NULL; - } - -+ /* -+ * If the given attribute number is writable, returns true. -+ */ -+ bool -+ SystemAttributeIsWritable(AttrNumber attnum) -+ { -+ if (attnum == SecurityAttributeNumber) -+ return true; -+ -+ return false; -+ } - - /* ---------------------------------------------------------------- - * XXX END OF UGLY HARD CODED BADNESS XXX -*************** heap_create(const char *relname, -*** 293,298 **** ---- 316,326 ---- - relid, - reltablespace, - shared_relation); -+ /* -+ * Does the relation have security attribute? -+ */ -+ RelationGetDescr(rel)->tdhassecid -+ = securityTupleDescHasSecid(relid, relkind); - - /* - * Have the storage manager create the relation's disk file, if needed. -*************** CheckAttributeType(const char *attname, -*** 487,493 **** - void - InsertPgAttributeTuple(Relation pg_attribute_rel, - Form_pg_attribute new_attribute, -! CatalogIndexState indstate) - { - Datum values[Natts_pg_attribute]; - bool nulls[Natts_pg_attribute]; ---- 515,522 ---- - void - InsertPgAttributeTuple(Relation pg_attribute_rel, - Form_pg_attribute new_attribute, -! CatalogIndexState indstate, -! Oid new_att_secid) - { - Datum values[Natts_pg_attribute]; - bool nulls[Natts_pg_attribute]; -*************** InsertPgAttributeTuple(Relation pg_attri -*** 520,525 **** ---- 549,557 ---- - - tup = heap_form_tuple(RelationGetDescr(pg_attribute_rel), values, nulls); - -+ if (HeapTupleHasSecid(tup)) -+ HeapTupleSetSecid(tup, new_att_secid); -+ - /* finally insert the new tuple, update the indexes, and clean up */ - simple_heap_insert(pg_attribute_rel, tup); - -*************** AddNewAttributeTuples(Oid new_rel_oid, -*** 543,555 **** - TupleDesc tupdesc, - char relkind, - bool oidislocal, -! int oidinhcount) - { - Form_pg_attribute attr; - int i; - Relation rel; - CatalogIndexState indstate; - int natts = tupdesc->natts; - ObjectAddress myself, - referenced; - ---- 575,589 ---- - TupleDesc tupdesc, - char relkind, - bool oidislocal, -! int oidinhcount, -! Oid *secLabels) - { - Form_pg_attribute attr; - int i; - Relation rel; - CatalogIndexState indstate; - int natts = tupdesc->natts; -+ Oid new_att_secid; - ObjectAddress myself, - referenced; - -*************** AddNewAttributeTuples(Oid new_rel_oid, -*** 573,579 **** - attr->attstattarget = -1; - attr->attcacheoff = -1; - -! InsertPgAttributeTuple(rel, attr, indstate); - - /* Add dependency info */ - myself.classId = RelationRelationId; ---- 607,617 ---- - attr->attstattarget = -1; - attr->attcacheoff = -1; - -! /* Security label of the column */ -! new_att_secid = (!secLabels ? InvalidOid -! : secLabels[i - FirstLowInvalidHeapAttributeNumber]); -! -! InsertPgAttributeTuple(rel, attr, indstate, new_att_secid); - - /* Add dependency info */ - myself.classId = RelationRelationId; -*************** AddNewAttributeTuples(Oid new_rel_oid, -*** 601,606 **** ---- 639,650 ---- - SysAtt[i]->attnum == ObjectIdAttributeNumber) - continue; - -+ /* skip Secid where appropriate */ -+ if (SysAtt[i]->attnum == SecurityAttributeNumber && -+ (relkind != RELKIND_RELATION || -+ new_rel_oid == SecurityRelationId)) -+ continue; -+ - memcpy(&attStruct, (char *) SysAtt[i], sizeof(FormData_pg_attribute)); - - /* Fill in the correct relation OID in the copied tuple */ -*************** AddNewAttributeTuples(Oid new_rel_oid, -*** 613,619 **** - attStruct.attinhcount = oidinhcount; - } - -! InsertPgAttributeTuple(rel, &attStruct, indstate); - } - } - ---- 657,667 ---- - attStruct.attinhcount = oidinhcount; - } - -! /* Security label of the system column */ -! new_att_secid = (!secLabels ? InvalidOid -! : secLabels[SysAtt[i]->attnum - FirstLowInvalidHeapAttributeNumber]); -! -! InsertPgAttributeTuple(rel, &attStruct, indstate, new_att_secid); - } - } - -*************** void -*** 641,647 **** - InsertPgClassTuple(Relation pg_class_desc, - Relation new_rel_desc, - Oid new_rel_oid, -! Datum reloptions) - { - Form_pg_class rd_rel = new_rel_desc->rd_rel; - Datum values[Natts_pg_class]; ---- 689,696 ---- - InsertPgClassTuple(Relation pg_class_desc, - Relation new_rel_desc, - Oid new_rel_oid, -! Datum reloptions, -! Oid new_rel_secid) - { - Form_pg_class rd_rel = new_rel_desc->rd_rel; - Datum values[Natts_pg_class]; -*************** InsertPgClassTuple(Relation pg_class_des -*** 690,695 **** ---- 739,747 ---- - */ - HeapTupleSetOid(tup, new_rel_oid); - -+ if (HeapTupleHasSecid(tup)) -+ HeapTupleSetSecid(tup, new_rel_secid); -+ - /* finally insert the new tuple, update the indexes, and clean up */ - simple_heap_insert(pg_class_desc, tup); - -*************** AddNewRelationTuple(Relation pg_class_de -*** 712,720 **** - Oid new_type_oid, - Oid relowner, - char relkind, -! Datum reloptions) - { - Form_pg_class new_rel_reltup; - - /* - * first we update some of the information in our uncataloged relation's ---- 764,774 ---- - Oid new_type_oid, - Oid relowner, - char relkind, -! Datum reloptions, -! Oid *secLabels) - { - Form_pg_class new_rel_reltup; -+ Oid new_rel_secid = InvalidOid; - - /* - * first we update some of the information in our uncataloged relation's -*************** AddNewRelationTuple(Relation pg_class_de -*** 771,778 **** - - new_rel_desc->rd_att->tdtypeid = new_type_oid; - - /* Now build and insert the tuple */ -! InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid, reloptions); - } - - ---- 825,836 ---- - - new_rel_desc->rd_att->tdtypeid = new_type_oid; - -+ if (secLabels) -+ new_rel_secid = secLabels[0]; -+ - /* Now build and insert the tuple */ -! InsertPgClassTuple(pg_class_desc, new_rel_desc, new_rel_oid, -! reloptions, new_rel_secid); - } - - -*************** heap_create_with_catalog(const char *rel -*** 843,849 **** - int oidinhcount, - OnCommitAction oncommit, - Datum reloptions, -! bool allow_system_table_mods) - { - Relation pg_class_desc; - Relation new_rel_desc; ---- 901,908 ---- - int oidinhcount, - OnCommitAction oncommit, - Datum reloptions, -! bool allow_system_table_mods, -! Oid *secLabels) - { - Relation pg_class_desc; - Relation new_rel_desc; -*************** heap_create_with_catalog(const char *rel -*** 1019,1031 **** - new_type_oid, - ownerid, - relkind, -! reloptions); - - /* - * now add tuples to pg_attribute for the attributes in our new relation. - */ - AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind, -! oidislocal, oidinhcount); - - /* - * Make a dependency link to force the relation to be deleted if its ---- 1078,1091 ---- - new_type_oid, - ownerid, - relkind, -! reloptions, -! secLabels); - - /* - * now add tuples to pg_attribute for the attributes in our new relation. - */ - AddNewAttributeTuples(relid, new_rel_desc->rd_att, relkind, -! oidislocal, oidinhcount, secLabels); - - /* - * Make a dependency link to force the relation to be deleted if its -*************** heap_drop_with_catalog(Oid relid) -*** 1484,1489 **** ---- 1544,1554 ---- - * delete relation tuple - */ - DeleteRelationTuple(relid); -+ -+ /* -+ * delete orphan pg_security entries -+ */ -+ securityReclaimOnDropTable(relid); - } - - -diff -Nrpc base/src/backend/catalog/index.c sepgsql/src/backend/catalog/index.c -*** base/src/backend/catalog/index.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/index.c Wed Jul 15 19:39:56 2009 -*************** -*** 48,53 **** ---- 48,54 ---- - #include "nodes/nodeFuncs.h" - #include "optimizer/clauses.h" - #include "optimizer/var.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/lmgr.h" - #include "storage/procarray.h" -*************** static TupleDesc ConstructTupleDescripto -*** 81,87 **** - Oid *classObjectId); - static void InitializeAttributeOids(Relation indexRelation, - int numatts, Oid indexoid); -! static void AppendAttributeTuples(Relation indexRelation, int numatts); - static void UpdateIndexRelation(Oid indexoid, Oid heapoid, - IndexInfo *indexInfo, - Oid *classOids, ---- 82,88 ---- - Oid *classObjectId); - static void InitializeAttributeOids(Relation indexRelation, - int numatts, Oid indexoid); -! static void AppendAttributeTuples(Relation indexRelation, int numatts, Oid *secLabels); - static void UpdateIndexRelation(Oid indexoid, Oid heapoid, - IndexInfo *indexInfo, - Oid *classOids, -*************** InitializeAttributeOids(Relation indexRe -*** 323,333 **** - * ---------------------------------------------------------------- - */ - static void -! AppendAttributeTuples(Relation indexRelation, int numatts) - { - Relation pg_attribute; - CatalogIndexState indstate; - TupleDesc indexTupDesc; - int i; - - /* ---- 324,335 ---- - * ---------------------------------------------------------------- - */ - static void -! AppendAttributeTuples(Relation indexRelation, int numatts, Oid *secLabels) - { - Relation pg_attribute; - CatalogIndexState indstate; - TupleDesc indexTupDesc; -+ Oid attsid = InvalidOid; - int i; - - /* -*************** AppendAttributeTuples(Relation indexRela -*** 351,357 **** - Assert(indexTupDesc->attrs[i]->attnum == i + 1); - Assert(indexTupDesc->attrs[i]->attcacheoff == -1); - -! InsertPgAttributeTuple(pg_attribute, indexTupDesc->attrs[i], indstate); - } - - CatalogCloseIndexes(indstate); ---- 353,363 ---- - Assert(indexTupDesc->attrs[i]->attnum == i + 1); - Assert(indexTupDesc->attrs[i]->attcacheoff == -1); - -! if (secLabels) -! attsid = secLabels[i - FirstLowInvalidHeapAttributeNumber]; -! -! InsertPgAttributeTuple(pg_attribute, indexTupDesc->attrs[i], -! indstate, attsid); - } - - CatalogCloseIndexes(indstate); -*************** index_create(Oid heapRelationId, -*** 519,524 **** ---- 525,532 ---- - TupleDesc indexTupDesc; - bool shared_relation; - Oid namespaceId; -+ Oid *secLabels; -+ Oid relsid = InvalidOid; - int i; - - pg_class = heap_open(RelationRelationId, RowExclusiveLock); -*************** index_create(Oid heapRelationId, -*** 604,609 **** ---- 612,625 ---- - classObjectId); - - /* -+ * compute security labels to be assigned on index relation -+ */ -+ secLabels = sepgsqlCreateTableColumns(NULL, indexRelationName, namespaceId, -+ indexTupDesc, RELKIND_INDEX); -+ if (secLabels) -+ relsid = secLabels[0]; -+ -+ /* - * Allocate an OID for the index, unless we were told what to use. - * - * The OID will be the relfilenode as well, so make sure it doesn't -*************** index_create(Oid heapRelationId, -*** 652,658 **** - */ - InsertPgClassTuple(pg_class, indexRelation, - RelationGetRelid(indexRelation), -! reloptions); - - /* done with pg_class */ - heap_close(pg_class, RowExclusiveLock); ---- 668,674 ---- - */ - InsertPgClassTuple(pg_class, indexRelation, - RelationGetRelid(indexRelation), -! reloptions, relsid); - - /* done with pg_class */ - heap_close(pg_class, RowExclusiveLock); -*************** index_create(Oid heapRelationId, -*** 668,674 **** - /* - * append ATTRIBUTE tuples for the index - */ -! AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs); - - /* ---------------- - * update pg_index ---- 684,690 ---- - /* - * append ATTRIBUTE tuples for the index - */ -! AppendAttributeTuples(indexRelation, indexInfo->ii_NumIndexAttrs, secLabels); - - /* ---------------- - * update pg_index -diff -Nrpc base/src/backend/catalog/namespace.c sepgsql/src/backend/catalog/namespace.c -*** base/src/backend/catalog/namespace.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/namespace.c Mon Sep 7 00:55:45 2009 -*************** -*** 39,44 **** ---- 39,45 ---- - #include "miscadmin.h" - #include "nodes/makefuncs.h" - #include "parser/parse_func.h" -+ #include "security/sepgsql.h" - #include "storage/backendid.h" - #include "storage/ipc.h" - #include "utils/acl.h" -*************** LookupExplicitNamespace(const char *nspn -*** 2105,2111 **** ---- 2106,2115 ---- - if (strcmp(nspname, "pg_temp") == 0) - { - if (OidIsValid(myTempNamespace)) -+ { -+ sepgsqlCheckSchemaSearch(myTempNamespace, true); - return myTempNamespace; -+ } - - /* - * Since this is used only for looking up existing objects, there is -*************** LookupExplicitNamespace(const char *nspn -*** 2127,2132 **** ---- 2131,2137 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - nspname); -+ sepgsqlCheckSchemaSearch(namespaceId, true); - - return namespaceId; - } -*************** recomputeNamespacePath(void) -*** 2722,2728 **** - if (OidIsValid(namespaceId) && - !list_member_oid(oidlist, namespaceId) && - pg_namespace_aclcheck(namespaceId, roleid, -! ACL_USAGE) == ACLCHECK_OK) - oidlist = lappend_oid(oidlist, namespaceId); - } - } ---- 2727,2734 ---- - if (OidIsValid(namespaceId) && - !list_member_oid(oidlist, namespaceId) && - pg_namespace_aclcheck(namespaceId, roleid, -! ACL_USAGE) == ACLCHECK_OK && -! sepgsqlCheckSchemaSearch(namespaceId, false)) - oidlist = lappend_oid(oidlist, namespaceId); - } - } -*************** recomputeNamespacePath(void) -*** 2731,2737 **** - /* pg_temp --- substitute temp namespace, if any */ - if (OidIsValid(myTempNamespace)) - { -! if (!list_member_oid(oidlist, myTempNamespace)) - oidlist = lappend_oid(oidlist, myTempNamespace); - } - else ---- 2737,2744 ---- - /* pg_temp --- substitute temp namespace, if any */ - if (OidIsValid(myTempNamespace)) - { -! if (!list_member_oid(oidlist, myTempNamespace) && -! sepgsqlCheckSchemaSearch(myTempNamespace, false)) - oidlist = lappend_oid(oidlist, myTempNamespace); - } - else -*************** recomputeNamespacePath(void) -*** 2750,2756 **** - if (OidIsValid(namespaceId) && - !list_member_oid(oidlist, namespaceId) && - pg_namespace_aclcheck(namespaceId, roleid, -! ACL_USAGE) == ACLCHECK_OK) - oidlist = lappend_oid(oidlist, namespaceId); - } - } ---- 2757,2764 ---- - if (OidIsValid(namespaceId) && - !list_member_oid(oidlist, namespaceId) && - pg_namespace_aclcheck(namespaceId, roleid, -! ACL_USAGE) == ACLCHECK_OK && -! sepgsqlCheckSchemaSearch(namespaceId, false)) - oidlist = lappend_oid(oidlist, namespaceId); - } - } -*************** InitTempTableNamespace(void) -*** 2816,2821 **** ---- 2824,2830 ---- - char namespaceName[NAMEDATALEN]; - Oid namespaceId; - Oid toastspaceId; -+ Oid nspsecid; - - Assert(!OidIsValid(myTempNamespace)); - -*************** InitTempTableNamespace(void) -*** 2836,2841 **** ---- 2845,2853 ---- - errmsg("permission denied to create temporary tables in database \"%s\"", - get_database_name(MyDatabaseId)))); - -+ /* SELinux checks permission to create temp schema */ -+ nspsecid = sepgsqlCheckSchemaCreate(namespaceName, NULL, true); -+ - snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d", MyBackendId); - - namespaceId = GetSysCacheOid(NAMESPACENAME, -*************** InitTempTableNamespace(void) -*** 2851,2857 **** - * temp tables. This works because the places that access the temp - * namespace for my own backend skip permissions checks on it. - */ -! namespaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID); - /* Advance command counter to make namespace visible */ - CommandCounterIncrement(); - } ---- 2863,2871 ---- - * temp tables. This works because the places that access the temp - * namespace for my own backend skip permissions checks on it. - */ -! namespaceId = NamespaceCreate(namespaceName, -! BOOTSTRAP_SUPERUSERID, -! nspsecid); - /* Advance command counter to make namespace visible */ - CommandCounterIncrement(); - } -*************** InitTempTableNamespace(void) -*** 2877,2883 **** - 0, 0, 0); - if (!OidIsValid(toastspaceId)) - { -! toastspaceId = NamespaceCreate(namespaceName, BOOTSTRAP_SUPERUSERID); - /* Advance command counter to make namespace visible */ - CommandCounterIncrement(); - } ---- 2891,2899 ---- - 0, 0, 0); - if (!OidIsValid(toastspaceId)) - { -! toastspaceId = NamespaceCreate(namespaceName, -! BOOTSTRAP_SUPERUSERID, -! nspsecid); - /* Advance command counter to make namespace visible */ - CommandCounterIncrement(); - } -*************** RemoveTempRelations(Oid tempNamespaceId) -*** 3030,3035 **** ---- 3046,3058 ---- - object.objectId = tempNamespaceId; - object.objectSubId = 0; - -+ /* -+ * TODO: -+ * SELinux should not check db_xxx:{drop} permission during cleaning -+ * up all the temporary objects. It may be necessary a bool argument -+ * to control MAC permission check on deleteOneObject() called from -+ * deleteWhatDependsOn() and so on. -+ */ - deleteWhatDependsOn(&object, false); - } - -diff -Nrpc base/src/backend/catalog/pg_aggregate.c sepgsql/src/backend/catalog/pg_aggregate.c -*** base/src/backend/catalog/pg_aggregate.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/pg_aggregate.c Wed Jul 15 19:37:35 2009 -*************** AggregateCreate(const char *aggName, -*** 231,237 **** - NIL, /* parameterDefaults */ - PointerGetDatum(NULL), /* proconfig */ - 1, /* procost */ -! 0); /* prorows */ - - /* - * Okay to create the pg_aggregate entry. ---- 231,238 ---- - NIL, /* parameterDefaults */ - PointerGetDatum(NULL), /* proconfig */ - 1, /* procost */ -! 0, /* prorows */ -! NULL); /* proseclabel*/ - - /* - * Okay to create the pg_aggregate entry. -diff -Nrpc base/src/backend/catalog/pg_largeobject.c sepgsql/src/backend/catalog/pg_largeobject.c -*** base/src/backend/catalog/pg_largeobject.c Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/catalog/pg_largeobject.c Wed Jul 15 19:48:58 2009 -*************** -*** 18,23 **** ---- 18,24 ---- - #include "access/heapam.h" - #include "catalog/indexing.h" - #include "catalog/pg_largeobject.h" -+ #include "security/sepgsql.h" - #include "utils/builtins.h" - #include "utils/fmgroids.h" - #include "utils/rel.h" -*************** LargeObjectCreate(Oid loid) -*** 59,64 **** ---- 60,68 ---- - - ntup = heap_form_tuple(pg_largeobject->rd_att, values, nulls); - -+ /* SELinux checks db_blob:{create} */ -+ sepgsqlCheckBlobCreate(pg_largeobject, ntup); -+ - /* - * Insert it - */ -*************** LargeObjectDrop(Oid loid) -*** 93,98 **** ---- 97,105 ---- - - while ((tuple = systable_getnext(sd)) != NULL) - { -+ /* SELinux checks db_blob:{drop} */ -+ if (!found) -+ sepgsqlCheckBlobDrop(pg_largeobject, tuple); - simple_heap_delete(pg_largeobject, &tuple->t_self); - found = true; - } -diff -Nrpc base/src/backend/catalog/pg_namespace.c sepgsql/src/backend/catalog/pg_namespace.c -*** base/src/backend/catalog/pg_namespace.c Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/catalog/pg_namespace.c Tue Sep 8 23:55:48 2009 -*************** -*** 28,34 **** - * --------------- - */ - Oid -! NamespaceCreate(const char *nspName, Oid ownerId) - { - Relation nspdesc; - HeapTuple tup; ---- 28,34 ---- - * --------------- - */ - Oid -! NamespaceCreate(const char *nspName, Oid ownerId, Oid nspsecid) - { - Relation nspdesc; - HeapTuple tup; -*************** NamespaceCreate(const char *nspName, Oid -*** 66,71 **** ---- 66,73 ---- - tupDesc = nspdesc->rd_att; - - tup = heap_form_tuple(tupDesc, values, nulls); -+ if (HeapTupleHasSecid(tup)) -+ HeapTupleSetSecid(tup, nspsecid); - - nspoid = simple_heap_insert(nspdesc, tup); - Assert(OidIsValid(nspoid)); -diff -Nrpc base/src/backend/catalog/pg_proc.c sepgsql/src/backend/catalog/pg_proc.c -*** base/src/backend/catalog/pg_proc.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/pg_proc.c Tue Sep 8 23:55:48 2009 -*************** -*** 29,34 **** ---- 29,35 ---- - #include "miscadmin.h" - #include "nodes/nodeFuncs.h" - #include "parser/parse_type.h" -+ #include "security/sepgsql.h" - #include "tcop/pquery.h" - #include "tcop/tcopprot.h" - #include "utils/acl.h" -*************** ProcedureCreate(const char *procedureNam -*** 78,84 **** - List *parameterDefaults, - Datum proconfig, - float4 procost, -! float4 prorows) - { - Oid retval; - int parameterCount; ---- 79,86 ---- - List *parameterDefaults, - Datum proconfig, - float4 procost, -! float4 prorows, -! Node *proseclabel) - { - Oid retval; - int parameterCount; -*************** ProcedureCreate(const char *procedureNam -*** 96,101 **** ---- 98,104 ---- - Datum values[Natts_pg_proc]; - bool replaces[Natts_pg_proc]; - Oid relid; -+ Oid prosecid = InvalidOid; - NameData procname; - TupleDesc tupDesc; - bool is_update; -*************** ProcedureCreate(const char *procedureNam -*** 343,348 **** ---- 346,361 ---- - ObjectIdGetDatum(procNamespace), - 0); - -+ /* Check permission to create/replace a function */ -+ prosecid = sepgsqlCheckProcedureCreate(procedureName, -+ HeapTupleIsValid(oldtup) -+ ? HeapTupleGetOid(oldtup) -+ : InvalidOid, -+ procNamespace, -+ languageObjectId, -+ (DefElem *)proseclabel); -+ sepgsqlCheckSchemaAddName(procNamespace); -+ - if (HeapTupleIsValid(oldtup)) - { - /* There is one; okay to replace it? */ -*************** ProcedureCreate(const char *procedureNam -*** 477,482 **** ---- 490,497 ---- - - /* Okay, do it... */ - tup = heap_modify_tuple(oldtup, tupDesc, values, nulls, replaces); -+ if (HeapTupleHasSecid(tup) && OidIsValid(prosecid)) -+ HeapTupleSetSecid(tup, prosecid); - simple_heap_update(rel, &tup->t_self, tup); - - ReleaseSysCache(oldtup); -*************** ProcedureCreate(const char *procedureNam -*** 486,491 **** ---- 501,508 ---- - { - /* Creating a new procedure */ - tup = heap_form_tuple(tupDesc, values, nulls); -+ if (HeapTupleHasSecid(tup)) -+ HeapTupleSetSecid(tup, prosecid); - simple_heap_insert(rel, tup); - is_update = false; - } -diff -Nrpc base/src/backend/catalog/pg_security.c sepgsql/src/backend/catalog/pg_security.c -*** base/src/backend/catalog/pg_security.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/catalog/pg_security.c Thu Sep 10 15:18:03 2009 -*************** -*** 0 **** ---- 1,637 ---- -+ /* -+ * src/backend/catalog/pg_security.c -+ * routines to support security label management -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "access/genam.h" -+ #include "access/heapam.h" -+ #include "access/sysattr.h" -+ #include "access/xact.h" -+ #include "catalog/catalog.h" -+ #include "catalog/indexing.h" -+ #include "catalog/pg_proc.h" -+ #include "catalog/pg_security.h" -+ #include "catalog/pg_type.h" -+ #include "executor/spi.h" -+ #include "miscadmin.h" -+ #include "security/rowlevel.h" -+ #include "security/sepgsql.h" -+ #include "utils/builtins.h" -+ #include "utils/fmgroids.h" -+ #include "utils/memutils.h" -+ #include "utils/rel.h" -+ #include "utils/lsyscache.h" -+ #include "utils/syscache.h" -+ #include "utils/tqual.h" -+ -+ bool -+ securityTupleDescHasSecid(Oid relid, char relkind) -+ { -+ return sepgsqlTupleDescHasSecid(relid, relkind); -+ } -+ -+ /* -+ * security attribute management at the initdb phase. -+ */ -+ typedef struct earlySecAttr -+ { -+ struct earlySecAttr *next; -+ Oid secid; -+ Oid datid; -+ Oid relid; -+ char seckind; -+ char secattr[1]; -+ } earlySecAttr; -+ -+ static earlySecAttr *earlySecAttrList = NULL; -+ -+ static Oid -+ earlyInputSecurityAttr(Oid datid, Oid relid, char seckind, const char *secattr) -+ { -+ static Oid dummySecid = SecurityRelationId; -+ earlySecAttr *es; -+ -+ for (es = earlySecAttrList; es; es = es->next) -+ { -+ if (es->datid == datid && -+ es->relid == relid && -+ es->seckind == seckind && -+ strcmp(es->secattr, secattr) == 0) -+ return es->secid; -+ } -+ /* Not found */ -+ es = MemoryContextAlloc(TopMemoryContext, -+ sizeof(*es) + strlen(secattr)); -+ es->secid = --dummySecid; -+ es->datid = datid; -+ es->relid = relid; -+ es->seckind = seckind; -+ strcpy(es->secattr, secattr); -+ -+ es->next = earlySecAttrList; -+ earlySecAttrList = es; -+ -+ return es->secid; -+ } -+ -+ static char * -+ earlyOutputSecurityAttr(Oid datid, Oid relid, char seckind, Oid secid) -+ { -+ earlySecAttr *es; -+ -+ for (es = earlySecAttrList; es; es = es->next) -+ { -+ if (es->datid == datid && -+ es->relid == relid && -+ es->seckind == seckind && -+ es->secid == secid) -+ return pstrdup(es->secattr); -+ } -+ return NULL; /* Not found */ -+ } -+ -+ void -+ securityPostBootstrapingMode(void) -+ { -+ Relation rel; -+ HeapTuple tuple; -+ earlySecAttr *es; -+ Datum values[Natts_pg_security]; -+ bool nulls[Natts_pg_security]; -+ -+ if (!earlySecAttrList) -+ return; /* do nothing */ -+ -+ StartTransactionCommand(); -+ -+ /* flush all the cached entries */ -+ rel = heap_open(SecurityRelationId, RowExclusiveLock); -+ for (es = earlySecAttrList; es; es = es->next) -+ { -+ memset(nulls, false, sizeof(nulls)); -+ values[Anum_pg_security_secid - 1] = ObjectIdGetDatum(es->secid); -+ values[Anum_pg_security_datid - 1] = ObjectIdGetDatum(es->datid); -+ values[Anum_pg_security_relid - 1] = ObjectIdGetDatum(es->relid); -+ values[Anum_pg_security_seckind - 1] = CharGetDatum(es->seckind); -+ values[Anum_pg_security_secattr - 1] = CStringGetTextDatum(es->secattr); -+ -+ tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); -+ -+ simple_heap_insert(rel, tuple); -+ CatalogUpdateIndexes(rel, tuple); -+ heap_freetuple(tuple); -+ } -+ heap_close(rel, RowExclusiveLock); -+ -+ CommitTransactionCommand(); -+ } -+ -+ /* -+ * securityOnCreateDatabase -+ * copies all the entries refered by source database -+ */ -+ void -+ securityOnCreateDatabase(Oid src_datid, Oid dst_datid) -+ { -+ Relation rel; -+ ScanKeyData keys[1]; -+ SysScanDesc scan; -+ HeapTuple oldtup, newtup; -+ Datum values[Natts_pg_security]; -+ bool nulls[Natts_pg_security]; -+ bool replaces[Natts_pg_security]; -+ -+ /* Scan all entries with pg_security.datid = src_datid */ -+ ScanKeyInit(&keys[0], -+ Anum_pg_security_datid, -+ BTEqualStrategyNumber, F_OIDEQ, -+ ObjectIdGetDatum(src_datid)); -+ -+ rel = heap_open(SecurityRelationId, RowExclusiveLock); -+ -+ scan = systable_beginscan(rel, SecuritySecidIndexId, true, -+ SnapshotNow, 1, keys); -+ -+ /* pg_security.datid shall be replaced */ -+ memset(values, 0, sizeof(values)); -+ memset(nulls, false, sizeof(nulls)); -+ memset(replaces, false, sizeof(replaces)); -+ -+ values[Anum_pg_security_datid - 1] = ObjectIdGetDatum(dst_datid); -+ replaces[Anum_pg_security_datid - 1] = true; -+ -+ while (HeapTupleIsValid(oldtup = systable_getnext(scan))) -+ { -+ newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), -+ values, nulls, replaces); -+ simple_heap_insert(rel, newtup); -+ -+ CatalogUpdateIndexes(rel, newtup); -+ -+ heap_freetuple(newtup); -+ } -+ systable_endscan(scan); -+ -+ heap_close(rel, RowExclusiveLock); -+ } -+ -+ /* -+ * securityOnDropDatabase -+ * drops all the entries refered by dropped database -+ */ -+ void -+ securityOnDropDatabase(Oid datid) -+ { -+ Relation rel; -+ ScanKeyData keys[1]; -+ SysScanDesc scan; -+ HeapTuple tuple; -+ -+ /* Scan all entries with pg_security.datid = datid */ -+ ScanKeyInit(&keys[0], -+ Anum_pg_security_datid, -+ BTEqualStrategyNumber, F_OIDEQ, -+ ObjectIdGetDatum(datid)); -+ -+ rel = heap_open(SecurityRelationId, RowExclusiveLock); -+ -+ scan = systable_beginscan(rel, SecuritySecidIndexId, true, -+ SnapshotNow, 1, keys); -+ -+ while (HeapTupleIsValid(tuple = systable_getnext(scan))) -+ { -+ simple_heap_delete(rel, &tuple->t_self); -+ } -+ -+ systable_endscan(scan); -+ -+ heap_close(rel, RowExclusiveLock); -+ } -+ -+ /* -+ * InputSecurityAttr -+ */ -+ static Oid -+ InputSecurityAttr(Oid relid, char seckind, const char *secattr) -+ { -+ Relation rel; -+ HeapTuple tuple; -+ Oid datid; -+ Oid secid; -+ Datum values[Natts_pg_security]; -+ bool nulls[Natts_pg_security]; -+ -+ datid = (IsSharedRelation(relid) ? InvalidOid : MyDatabaseId); -+ -+ if (IsBootstrapProcessingMode()) -+ return earlyInputSecurityAttr(datid, relid, seckind, secattr); -+ -+ /* -+ * Lookup the syscache first -+ */ -+ tuple = SearchSysCache(SECURITYATTR, -+ ObjectIdGetDatum(datid), -+ ObjectIdGetDatum(relid), -+ CharGetDatum(seckind), -+ CStringGetTextDatum(secattr)); -+ if (HeapTupleIsValid(tuple)) -+ { -+ secid = ((Form_pg_security) GETSTRUCT(tuple))->secid; -+ -+ ReleaseSysCache(tuple); -+ -+ return secid; -+ } -+ -+ /* -+ * Insert a new tuple, if not exist -+ */ -+ rel = heap_open(SecurityRelationId, RowExclusiveLock); -+ -+ memset(nulls, false, sizeof(nulls)); -+ secid = GetNewOidWithIndex(rel, SecuritySecidIndexId, -+ Anum_pg_security_secid); -+ values[Anum_pg_security_secid - 1] = ObjectIdGetDatum(secid); -+ values[Anum_pg_security_datid - 1] = ObjectIdGetDatum(datid); -+ values[Anum_pg_security_relid - 1] = ObjectIdGetDatum(relid); -+ values[Anum_pg_security_seckind - 1] = CharGetDatum(seckind); -+ values[Anum_pg_security_secattr - 1] = CStringGetTextDatum(secattr); -+ -+ tuple = heap_form_tuple(RelationGetDescr(rel), values, nulls); -+ -+ simple_heap_insert(rel, tuple); -+ CatalogUpdateIndexes(rel, tuple); -+ -+ heap_close(rel, RowExclusiveLock); -+ -+ /* -+ * Newly inserted security label needs to be visible by -+ * later operations in this transaction. -+ */ -+ CommandCounterIncrement(); -+ -+ return secid; -+ } -+ -+ static char * -+ OutputSecurityAttr(Oid relid, char seckind, Oid secid) -+ { -+ Form_pg_security secForm; -+ Oid datid; -+ HeapTuple tuple; -+ Datum datum; -+ bool isnull; -+ char *result; -+ -+ datid = (IsSharedRelation(relid) ? InvalidOid : MyDatabaseId); -+ -+ if (IsBootstrapProcessingMode()) -+ return earlyOutputSecurityAttr(datid, relid, seckind, secid); -+ -+ tuple = SearchSysCache(SECURITYSECID, -+ ObjectIdGetDatum(secid), -+ ObjectIdGetDatum(datid), -+ 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ return NULL; -+ -+ /* -+ * Integrity checks -+ */ -+ secForm = (Form_pg_security) GETSTRUCT(tuple); -+ if (secForm->relid != relid) -+ goto error; -+ if (secForm->seckind != seckind) -+ goto error; -+ datum = SysCacheGetAttr(SECURITYSECID, tuple, -+ Anum_pg_security_secattr, -+ &isnull); -+ if (isnull) -+ goto error; -+ -+ result = TextDatumGetCString(datum); -+ -+ ReleaseSysCache(tuple); -+ -+ return result; -+ -+ error: -+ ReleaseSysCache(tuple); -+ -+ elog(NOTICE, -+ "invalid pg_security (secid=%u, datid=%u, relid=%u, seckind=%c)" -+ " for relid=%u, seckind=%c secid=%u", -+ secForm->secid, secForm->datid, secForm->relid, secForm->seckind, -+ relid, seckind, secid); -+ -+ return NULL; -+ } -+ -+ /* -+ * input/output handler -+ */ -+ Oid -+ securityRawSecLabelIn(Oid relid, char *seclabel) -+ { -+ seclabel = sepgsqlRawSecLabelIn(seclabel); -+ -+ return InputSecurityAttr(relid, SECKIND_SECURITY_LABEL, seclabel); -+ } -+ -+ char * -+ securityRawSecLabelOut(Oid relid, Oid secid) -+ { -+ char *seclabel = OutputSecurityAttr(relid, SECKIND_SECURITY_LABEL, secid); -+ -+ return sepgsqlRawSecLabelOut(seclabel); -+ } -+ -+ Oid -+ securityTransSecLabelIn(Oid relid, char *seclabel) -+ { -+ seclabel = sepgsqlTransSecLabelIn(seclabel); -+ -+ return securityRawSecLabelIn(relid, seclabel); -+ } -+ -+ char * -+ securityTransSecLabelOut(Oid relid, Oid secid) -+ { -+ char *seclabel = securityRawSecLabelOut(relid, secid); -+ -+ return sepgsqlTransSecLabelOut(seclabel); -+ } -+ -+ /* -+ * Output handler for system columns -+ */ -+ Datum -+ securitySysattSecLabelOut(Oid relid, HeapTuple tuple) -+ { -+ char *seclabel; -+ -+ seclabel = sepgsqlSysattSecLabelOut(relid, tuple); -+ if (!seclabel) -+ seclabel = "unlabled"; -+ -+ return CStringGetTextDatum(seclabel); -+ } -+ -+ /* -+ * securityReclaimOnDropTable -+ * drop orphan entries within pg_security on drop table -+ */ -+ void -+ securityReclaimOnDropTable(Oid relid) -+ { -+ Relation rel; -+ SysScanDesc scan; -+ ScanKeyData key[2]; -+ HeapTuple tuple; -+ Oid database_oid; -+ -+ database_oid = (IsSharedRelation(relid) ? InvalidOid : MyDatabaseId); -+ ScanKeyInit(&key[0], -+ Anum_pg_security_datid, -+ BTEqualStrategyNumber, F_OIDEQ, -+ ObjectIdGetDatum(database_oid)); -+ ScanKeyInit(&key[1], -+ Anum_pg_security_relid, -+ BTEqualStrategyNumber, F_OIDEQ, -+ ObjectIdGetDatum(relid)); -+ -+ rel = heap_open(SecurityRelationId, RowExclusiveLock); -+ scan = systable_beginscan(rel, SecuritySecattrIndexId, true, -+ SnapshotNow, 2, key); -+ while (HeapTupleIsValid(tuple = systable_getnext(scan))) -+ simple_heap_delete(rel, &tuple->t_self); -+ -+ systable_endscan(scan); -+ -+ heap_close(rel, RowExclusiveLock); -+ } -+ -+ /* -+ * security_quote_relation -+ * returns palloc'de identifier with explicit namespace -+ */ -+ static char * -+ security_quote_relation(Oid relid) -+ { -+ Oid nspoid = get_rel_namespace(relid); -+ char *nspname; -+ char *relname; -+ -+ nspname = get_namespace_name(nspoid); -+ relname = get_rel_name(relid); -+ -+ return quote_qualified_identifier(nspname, relname); -+ } -+ -+ /* -+ * security_reclaim_table -+ * reclaims orphan entries associated to a certain table -+ */ -+ static int -+ security_reclaim_table(Oid relid, char seckind) -+ { -+ StringInfoData query; -+ SPIPlanPtr plan; -+ Oid types[2]; -+ Datum values[2]; -+ Oid proc_oid; -+ Oid database_oid; -+ char *relname_full; -+ char *attname_datid; -+ char *attname_relid; -+ char *attname_secid; -+ char *attname_seckind; -+ char *attname_secattr; -+ char *sec_proname; -+ char *sec_nspname; -+ Form_pg_proc proForm; -+ HeapTuple protup; -+ -+ /* -+ * LOCK the target table -+ */ -+ initStringInfo(&query); -+ relname_full = security_quote_relation(relid); -+ appendStringInfo(&query, "LOCK %s IN SHARE MODE", relname_full); -+ if (SPI_execute(query.data, false, 0) != SPI_OK_UTILITY) -+ elog(ERROR, "SPI_execute failed on %s", query.data); -+ -+ /* -+ * DELETE orphan entries -+ */ -+ initStringInfo(&query); -+ attname_secid = get_attname(SecurityRelationId, Anum_pg_security_secid); -+ attname_datid = get_attname(SecurityRelationId, Anum_pg_security_datid); -+ attname_relid = get_attname(SecurityRelationId, Anum_pg_security_relid); -+ attname_seckind = get_attname(SecurityRelationId, Anum_pg_security_seckind); -+ attname_secattr = get_attname(SecurityRelationId, Anum_pg_security_secattr); -+ -+ appendStringInfo(&query, -+ "DELETE FROM %s " -+ "WHERE %s = $1 AND %s = $2 " -+ " AND %s = $3 AND %s NOT IN ", -+ security_quote_relation(SecurityRelationId), -+ quote_identifier(attname_datid), -+ quote_identifier(attname_relid), -+ quote_identifier(attname_seckind), -+ quote_identifier(attname_secid)); -+ switch (seckind) -+ { -+ case SECKIND_SECURITY_LABEL: -+ proc_oid = F_SECURITY_LABEL_TO_SECID; -+ break; -+ default: -+ elog(ERROR, "unexpected seckind: %c", seckind); -+ proc_oid = InvalidOid; /* to compiler silent */ -+ break; -+ } -+ -+ protup = SearchSysCache(PROCOID, -+ ObjectIdGetDatum(proc_oid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(protup)) -+ elog(ERROR, "cache lookup failed for procedure: %u", proc_oid); -+ proForm = (Form_pg_proc) GETSTRUCT(protup); -+ sec_proname = NameStr(proForm->proname); -+ sec_nspname = get_namespace_name(proForm->pronamespace); -+ -+ appendStringInfo(&query, -+ "(SELECT %s.%s(%s) FROM ONLY %s)", -+ quote_identifier(sec_nspname), -+ quote_identifier(sec_proname), -+ quote_identifier(get_rel_name(relid)), -+ relname_full); -+ ReleaseSysCache(protup); -+ -+ /* -+ * Setup and execute query -+ */ -+ types[0] = OIDOID; -+ types[1] = OIDOID; -+ types[2] = CHAROID; -+ plan = SPI_prepare(query.data, 3, types); -+ if (!plan) -+ elog(ERROR, "SPI_prepare failed on %s", query.data); -+ -+ database_oid = (IsSharedRelation(relid) ? InvalidOid : MyDatabaseId); -+ -+ values[0] = ObjectIdGetDatum(database_oid); -+ values[1] = ObjectIdGetDatum(relid); -+ values[2] = CharGetDatum(seckind); -+ if (SPI_execute_plan(plan, values, NULL, false, 0) != SPI_OK_DELETE) -+ elog(ERROR, "SPI_execute_plan failed on %s", query.data); -+ -+ SPI_freetuptable(SPI_tuptable); -+ -+ return SPI_processed; -+ } -+ -+ static int -+ security_reclaim_all_tables(char seckind) -+ { -+ StringInfoData query; -+ char *attname_datid; -+ char *attname_relid; -+ int index; -+ Datum datum; -+ bool isnull; -+ int count = 0; -+ List *relidList = NIL; -+ ListCell *l; -+ -+ initStringInfo(&query); -+ -+ attname_datid = get_attname(SecurityRelationId, Anum_pg_security_datid); -+ attname_relid = get_attname(SecurityRelationId, Anum_pg_security_relid); -+ appendStringInfo(&query, -+ "SELECT DISTINCT %s FROM %s WHERE %s IN (%u,%u)", -+ attname_relid, -+ security_quote_relation(SecurityRelationId), -+ attname_datid, InvalidOid, MyDatabaseId); -+ -+ if (SPI_execute(query.data, true, 0) != SPI_OK_SELECT) -+ elog(ERROR, "SPI_execute failed on %s", query.data); -+ -+ for (index = 0; index < SPI_processed; index++) -+ { -+ datum = SPI_getbinval(SPI_tuptable->vals[index], -+ SPI_tuptable->tupdesc, 1, &isnull); -+ if (isnull) -+ continue; -+ relidList = lappend_oid(relidList, DatumGetObjectId(datum)); -+ } -+ SPI_freetuptable(SPI_tuptable); -+ -+ foreach (l, relidList) -+ count += security_reclaim_table(lfirst_oid(l), seckind); -+ -+ return count; -+ } -+ -+ static int -+ security_reclaim(Oid relid, char seckind) -+ { -+ int saved_mode; -+ int count; -+ -+ if (!superuser()) -+ ereport(ERROR, -+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), -+ errmsg("must be superuser to reclaim security attributes"))); -+ /* -+ * Disables SE-PostgreSQL temporary -+ */ -+ saved_mode = sepgsqlSetEnforce(0); -+ -+ PG_TRY(); -+ { -+ if (SPI_connect() != SPI_OK_CONNECT) -+ elog(ERROR, "SPI_connect failed"); -+ -+ if (OidIsValid(relid)) -+ count = security_reclaim_table(relid, seckind); -+ else -+ count = security_reclaim_all_tables(seckind); -+ -+ if (SPI_finish() != SPI_OK_FINISH) -+ elog(ERROR, "SPI_finish failed"); -+ } -+ PG_CATCH(); -+ { -+ sepgsqlSetEnforce(saved_mode); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ sepgsqlSetEnforce(saved_mode); -+ -+ return count; -+ } -+ -+ Datum -+ security_reclaim_label(PG_FUNCTION_ARGS) -+ { -+ PG_RETURN_INT32(security_reclaim(InvalidOid, SECKIND_SECURITY_LABEL)); -+ } -+ -+ Datum -+ security_reclaim_table_label(PG_FUNCTION_ARGS) -+ { -+ PG_RETURN_INT32(security_reclaim(PG_GETARG_OID(0), SECKIND_SECURITY_LABEL)); -+ } -+ -+ Datum -+ security_label_to_secid(PG_FUNCTION_ARGS) -+ { -+ HeapTupleHeader tuphdr = PG_GETARG_HEAPTUPLEHEADER(0); -+ -+ PG_RETURN_OID(HeapTupleHeaderGetSecid(tuphdr)); -+ } -diff -Nrpc base/src/backend/catalog/pg_shdepend.c sepgsql/src/backend/catalog/pg_shdepend.c -*** base/src/backend/catalog/pg_shdepend.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/pg_shdepend.c Tue Sep 8 23:55:48 2009 -*************** -*** 36,41 **** ---- 36,42 ---- - #include "commands/schemacmds.h" - #include "commands/tablecmds.h" - #include "commands/typecmds.h" -+ #include "security/sepgsql.h" - #include "storage/lmgr.h" - #include "miscadmin.h" - #include "utils/acl.h" -*************** shdepReassignOwned(List *roleids, Oid ne -*** 1336,1341 **** ---- 1337,1355 ---- - break; - - case TypeRelationId: -+ /* -+ * NOTE: SELinux does not check anything inside -+ * AlterTypeOwnerInternal() -+ */ -+ tuple = SearchSysCache(TYPEOID, -+ ObjectIdGetDatum(sdepForm->objid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for type: %u", sdepForm->objid); -+ sepgsqlCheckSysobjSetattr(TypeRelationId, -+ HeapTupleGetSecid(tuple), -+ NameStr(((Form_pg_type) GETSTRUCT(tuple))->typname)); -+ ReleaseSysCache(tuple); - AlterTypeOwnerInternal(sdepForm->objid, newrole, true); - break; - -*************** shdepReassignOwned(List *roleids, Oid ne -*** 1348,1354 **** - break; - - case RelationRelationId: -! - /* - * Pass recursing = true so that we don't fail on indexes, - * owned sequences, etc when we happen to visit them ---- 1362,1368 ---- - break; - - case RelationRelationId: -! sepgsqlCheckTableSetattr(sdepForm->objid); - /* - * Pass recursing = true so that we don't fail on indexes, - * owned sequences, etc when we happen to visit them -diff -Nrpc base/src/backend/catalog/pg_type.c sepgsql/src/backend/catalog/pg_type.c -*** base/src/backend/catalog/pg_type.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/catalog/pg_type.c Tue Sep 8 23:55:48 2009 -*************** -*** 25,30 **** ---- 25,31 ---- - #include "commands/typecmds.h" - #include "miscadmin.h" - #include "parser/scansup.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/fmgroids.h" -*************** TypeShellMake(const char *typeName, Oid -*** 56,65 **** ---- 57,72 ---- - Datum values[Natts_pg_type]; - bool nulls[Natts_pg_type]; - Oid typoid; -+ Oid typsid; - NameData name; - - Assert(PointerIsValid(typeName)); - -+ /* SELinux check permission to create a shell type */ -+ typsid = sepgsqlCheckSysobjCreate(TypeRelationId, typeName); -+ sepgsqlCheckProcedureInstall(F_SHELL_IN); -+ sepgsqlCheckProcedureInstall(F_SHELL_OUT); -+ - /* - * open pg_type - */ -*************** TypeCreate(Oid newTypeOid, -*** 201,206 **** ---- 208,214 ---- - { - Relation pg_type_desc; - Oid typeObjectId; -+ Oid typeSecid = InvalidOid; - bool rebuildDeps = false; - HeapTuple tup; - bool nulls[Natts_pg_type]; -*************** TypeCreate(Oid newTypeOid, -*** 367,372 **** ---- 375,394 ---- - CStringGetDatum(typeName), - ObjectIdGetDatum(typeNamespace), - 0, 0); -+ -+ /* SELinux checks to create/replace type */ -+ if (!isImplicitArray && typeType != TYPTYPE_COMPOSITE) -+ { -+ if (!HeapTupleIsValid(tup)) -+ typeSecid = sepgsqlCheckSysobjCreate(TypeRelationId, typeName); -+ else -+ { -+ typeSecid = HeapTupleGetSecid(tup); -+ sepgsqlCheckSysobjSetattr(TypeRelationId, typeSecid, typeName); -+ } -+ sepgsqlCheckSchemaAddName(typeNamespace); -+ } -+ - if (HeapTupleIsValid(tup)) - { - /* -*************** TypeCreate(Oid newTypeOid, -*** 412,417 **** ---- 434,441 ---- - /* Force the OID if requested by caller, else heap_insert does it */ - if (OidIsValid(newTypeOid)) - HeapTupleSetOid(tup, newTypeOid); -+ if (HeapTupleHasSecid(tup)) -+ HeapTupleSetSecid(tup, typeSecid); - - typeObjectId = simple_heap_insert(pg_type_desc, tup); - } -diff -Nrpc base/src/backend/catalog/toasting.c sepgsql/src/backend/catalog/toasting.c -*** base/src/backend/catalog/toasting.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/catalog/toasting.c Wed Jul 15 19:35:52 2009 -*************** -*** 28,33 **** ---- 28,34 ---- - #include "catalog/toasting.h" - #include "miscadmin.h" - #include "nodes/makefuncs.h" -+ #include "security/sepgsql.h" - #include "utils/builtins.h" - #include "utils/syscache.h" - -*************** create_toast_table(Relation rel, Oid toa -*** 125,130 **** ---- 126,132 ---- - char toast_relname[NAMEDATALEN]; - char toast_idxname[NAMEDATALEN]; - IndexInfo *indexInfo; -+ Oid *secLabels; - Oid classObjectId[2]; - int16 coloptions[2]; - ObjectAddress baseobject, -*************** create_toast_table(Relation rel, Oid toa -*** 199,204 **** ---- 201,210 ---- - else - namespaceid = PG_TOAST_NAMESPACE; - -+ secLabels = sepgsqlCreateTableColumns(NULL, -+ toast_relname, namespaceid, -+ tupdesc, RELKIND_TOASTVALUE); -+ - toast_relid = heap_create_with_catalog(toast_relname, - namespaceid, - rel->rd_rel->reltablespace, -*************** create_toast_table(Relation rel, Oid toa -*** 212,218 **** - 0, - ONCOMMIT_NOOP, - reloptions, -! true); - - /* make the toast relation visible, else index creation will fail */ - CommandCounterIncrement(); ---- 218,225 ---- - 0, - ONCOMMIT_NOOP, - reloptions, -! true, -! secLabels); - - /* make the toast relation visible, else index creation will fail */ - CommandCounterIncrement(); -diff -Nrpc base/src/backend/commands/aggregatecmds.c sepgsql/src/backend/commands/aggregatecmds.c -*** base/src/backend/commands/aggregatecmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/aggregatecmds.c Mon Sep 7 00:55:45 2009 -*************** -*** 32,37 **** ---- 32,38 ---- - #include "miscadmin.h" - #include "parser/parse_func.h" - #include "parser/parse_type.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/lsyscache.h" -*************** RenameAggregate(List *name, List *args, -*** 311,316 **** ---- 312,322 ---- - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - -+ /* SELinux permission checks */ -+ sepgsqlCheckProcedureSetattr(procOid); -+ sepgsqlCheckSchemaRemoveName(namespaceOid); -+ sepgsqlCheckSchemaAddName(namespaceOid); -+ - /* rename */ - namestrcpy(&(((Form_pg_proc) GETSTRUCT(tup))->proname), newname); - simple_heap_update(rel, &tup->t_self, tup); -diff -Nrpc base/src/backend/commands/alter.c sepgsql/src/backend/commands/alter.c -*** base/src/backend/commands/alter.c Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/commands/alter.c Thu Jul 16 17:22:29 2009 -*************** -*** 28,33 **** ---- 28,34 ---- - #include "commands/user.h" - #include "miscadmin.h" - #include "parser/parse_clause.h" -+ #include "security/sepgsql.h" - #include "tcop/utility.h" - #include "utils/acl.h" - #include "utils/lsyscache.h" -*************** ExecRenameStmt(RenameStmt *stmt) -*** 117,122 **** ---- 118,126 ---- - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceId)); - -+ /* SELinux checks db_table/db_sequence:{setattr} */ -+ sepgsqlCheckTableSetattr(relid); -+ - RenameRelation(relid, stmt->newname, stmt->renameType); - break; - } -*************** ExecAlterOwnerStmt(AlterOwnerStmt *stmt) -*** 284,286 **** ---- 288,319 ---- - (int) stmt->objectType); - } - } -+ -+ void -+ ExecAlterSecLabelStmt(AlterSecLabelStmt *stmt) -+ { -+ DefElem *seclabel = (DefElem *)stmt->secLabel; -+ -+ switch (stmt->objectType) -+ { -+ case OBJECT_DATABASE: -+ AlterDatabaseSecLabel(strVal(linitial(stmt->object)), seclabel); -+ break; -+ case OBJECT_SCHEMA: -+ AlterSchemaSecLabel(strVal(linitial(stmt->object)), seclabel); -+ break; -+ case OBJECT_TABLE: -+ case OBJECT_SEQUENCE: -+ case OBJECT_COLUMN: -+ CheckRelationOwnership(stmt->relation, true); -+ AlterRelationSecLabel(stmt->relation, stmt->subname, -+ stmt->objectType, seclabel); -+ break; -+ case OBJECT_FUNCTION: -+ AlterFunctionSecLabel(stmt->object, stmt->objarg, seclabel); -+ break; -+ default: -+ elog(ERROR, "unrecognized AlterSecLabelStmt type: %d", -+ (int) stmt->objectType); -+ } -+ } -diff -Nrpc base/src/backend/commands/cluster.c sepgsql/src/backend/commands/cluster.c -*** base/src/backend/commands/cluster.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/cluster.c Tue Sep 8 23:55:48 2009 -*************** -*** 36,41 **** ---- 36,42 ---- - #include "commands/trigger.h" - #include "commands/vacuum.h" - #include "miscadmin.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/procarray.h" - #include "utils/acl.h" -*************** rebuild_relation(Relation OldHeap, Oid i -*** 617,624 **** - /* - * The new relation is local to our transaction and we know nothing - * depends on it, so DROP_RESTRICT should be OK. - */ -! performDeletion(&object, DROP_RESTRICT); - - /* performDeletion does CommandCounterIncrement at end */ - ---- 618,626 ---- - /* - * The new relation is local to our transaction and we know nothing - * depends on it, so DROP_RESTRICT should be OK. -+ * SELinux does not check any permissions here. - */ -! performDeletionNoPerms(&object, DROP_RESTRICT); - - /* performDeletion does CommandCounterIncrement at end */ - -*************** make_new_heap(Oid OIDOldHeap, const char -*** 712,718 **** - 0, - ONCOMMIT_NOOP, - reloptions, -! allowSystemTableMods); - - ReleaseSysCache(tuple); - ---- 714,721 ---- - 0, - ONCOMMIT_NOOP, - reloptions, -! allowSystemTableMods, -! sepgsqlCopyTableColumns(OldHeap)); - - ReleaseSysCache(tuple); - -*************** copy_heap_data(Oid OIDNewHeap, Oid OIDOl -*** 924,929 **** ---- 927,936 ---- - if (NewHeap->rd_rel->relhasoids) - HeapTupleSetOid(copiedTuple, HeapTupleGetOid(tuple)); - -+ /* Preserve SID, if any */ -+ if (HeapTupleHasSecid(copiedTuple)) -+ HeapTupleSetSecid(copiedTuple, HeapTupleGetSecid(tuple)); -+ - /* The heap rewrite module does the rest */ - rewrite_heap_tuple(rwstate, tuple, copiedTuple); - -diff -Nrpc base/src/backend/commands/conversioncmds.c sepgsql/src/backend/commands/conversioncmds.c -*** base/src/backend/commands/conversioncmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/conversioncmds.c Wed Jul 15 19:48:58 2009 -*************** -*** 24,29 **** ---- 24,30 ---- - #include "mb/pg_wchar.h" - #include "miscadmin.h" - #include "parser/parse_func.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/lsyscache.h" -*************** CreateConversionCommand(CreateConversion -*** 96,101 **** ---- 97,105 ---- - aclcheck_error(aclresult, ACL_KIND_PROC, - NameListToString(func_name)); - -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(funcoid); -+ - /* - * Check that the conversion function is suitable for the requested source - * and target encodings. We do that by calling the function with an empty -diff -Nrpc base/src/backend/commands/copy.c sepgsql/src/backend/commands/copy.c -*** base/src/backend/commands/copy.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/copy.c Thu Sep 10 15:18:03 2009 -*************** -*** 21,28 **** ---- 21,31 ---- - #include - - #include "access/heapam.h" -+ #include "access/sysattr.h" - #include "access/xact.h" -+ #include "catalog/heap.h" - #include "catalog/namespace.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_type.h" - #include "commands/copy.h" - #include "commands/trigger.h" -*************** -*** 34,39 **** ---- 37,44 ---- - #include "optimizer/planner.h" - #include "parser/parse_relation.h" - #include "rewrite/rewriteHandler.h" -+ #include "security/rowlevel.h" -+ #include "security/sepgsql.h" - #include "storage/fd.h" - #include "tcop/tcopprot.h" - #include "utils/acl.h" -*************** typedef struct CopyStateData -*** 160,165 **** ---- 165,174 ---- - char *raw_buf; - int raw_buf_index; /* next byte to process */ - int raw_buf_len; /* total # of bytes stored */ -+ -+ /* dump/restore support for security_label */ -+ FmgrInfo seclabel_out_function; -+ bool seclabel_force_quot; - } CopyStateData; - - typedef CopyStateData *CopyState; -*************** static const char BinarySignature[11] = -*** 243,250 **** - /* non-export function prototypes */ - static void DoCopyTo(CopyState cstate); - static void CopyTo(CopyState cstate); -! static void CopyOneRowTo(CopyState cstate, Oid tupleOid, -! Datum *values, bool *nulls); - static void CopyFrom(CopyState cstate); - static bool CopyReadLine(CopyState cstate); - static bool CopyReadLineText(CopyState cstate); ---- 252,259 ---- - /* non-export function prototypes */ - static void DoCopyTo(CopyState cstate); - static void CopyTo(CopyState cstate); -! static void CopyOneRowTo(CopyState cstate, HeapTuple tuple, -! Datum *values, bool *nulls); - static void CopyFrom(CopyState cstate); - static bool CopyReadLine(CopyState cstate); - static bool CopyReadLineText(CopyState cstate); -*************** DoCopy(const CopyStmt *stmt, const char -*** 1090,1095 **** ---- 1099,1107 ---- - - num_phys_attrs = tupDesc->natts; - -+ /* SELinux: check table/column level permission */ -+ sepgsqlCheckCopyTable(cstate->rel, cstate->attnumlist, is_from); -+ - /* Convert FORCE QUOTE name list to per-column flags, check validity */ - cstate->force_quote_flags = (bool *) palloc0(num_phys_attrs * sizeof(bool)); - if (force_quote) -*************** DoCopy(const CopyStmt *stmt, const char -*** 1104,1114 **** - int attnum = lfirst_int(cur); - - if (!list_member_int(cstate->attnumlist, attnum)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("FORCE QUOTE column \"%s\" not referenced by COPY", -! NameStr(tupDesc->attrs[attnum - 1]->attname)))); -! cstate->force_quote_flags[attnum - 1] = true; - } - } - ---- 1116,1146 ---- - int attnum = lfirst_int(cur); - - if (!list_member_int(cstate->attnumlist, attnum)) -+ { -+ Form_pg_attribute attForm; -+ -+ if (SystemAttributeIsWritable(attnum)) -+ attForm = SystemAttributeDefinition(attnum, true); -+ else -+ attForm = tupDesc->attrs[attnum - 1]; -+ -+ Assert(attForm != NULL); -+ - ereport(ERROR, - (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("FORCE QUOTE column \"%s\" not referenced by COPY", -! NameStr(attForm->attname)))); -! } -! -! switch (attnum) -! { -! case SecurityAttributeNumber: -! cstate->seclabel_force_quot = true; -! break; -! default: -! cstate->force_quote_flags[attnum - 1] = true; -! break; -! } - } - } - -*************** DoCopy(const CopyStmt *stmt, const char -*** 1126,1135 **** - int attnum = lfirst_int(cur); - - if (!list_member_int(cstate->attnumlist, attnum)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("FORCE NOT NULL column \"%s\" not referenced by COPY", -! NameStr(tupDesc->attrs[attnum - 1]->attname)))); - cstate->force_notnull_flags[attnum - 1] = true; - } - } ---- 1158,1180 ---- - int attnum = lfirst_int(cur); - - if (!list_member_int(cstate->attnumlist, attnum)) -+ { -+ Form_pg_attribute attForm; -+ -+ if (SystemAttributeIsWritable(attnum)) -+ attForm = SystemAttributeDefinition(attnum, true); -+ else -+ attForm = tupDesc->attrs[attnum - 1]; -+ -+ Assert(attForm != NULL); -+ - ereport(ERROR, - (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), - errmsg("FORCE NOT NULL column \"%s\" not referenced by COPY", -! NameStr(attForm->attname)))); -! } -! if (SystemAttributeIsWritable(attnum)) -! continue; /* ignore, if specified */ - cstate->force_notnull_flags[attnum - 1] = true; - } - } -*************** DoCopyTo(CopyState cstate) -*** 1258,1263 **** ---- 1303,1311 ---- - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is a directory", cstate->filename))); -+ -+ /* SELinux checks file:{write} permission */ -+ sepgsqlCheckFileWrite(fileno(cstate->copy_file), cstate->filename); - } - - PG_TRY(); -*************** CopyTo(CopyState cstate) -*** 1321,1336 **** - int attnum = lfirst_int(cur); - Oid out_func_oid; - bool isvarlena; - - if (cstate->binary) -! getTypeBinaryOutputInfo(attr[attnum - 1]->atttypid, - &out_func_oid, - &isvarlena); - else -! getTypeOutputInfo(attr[attnum - 1]->atttypid, - &out_func_oid, - &isvarlena); -! fmgr_info(out_func_oid, &cstate->out_functions[attnum - 1]); - } - - /* ---- 1369,1399 ---- - int attnum = lfirst_int(cur); - Oid out_func_oid; - bool isvarlena; -+ FmgrInfo *out_fmgr; -+ Form_pg_attribute attForm; -+ -+ switch (attnum) -+ { -+ case SecurityAttributeNumber: -+ attForm = SystemAttributeDefinition(attnum, true); -+ out_fmgr = &cstate->seclabel_out_function; -+ break; -+ -+ default: -+ attForm = attr[attnum - 1]; -+ out_fmgr = &cstate->out_functions[attnum - 1]; -+ break; -+ } - - if (cstate->binary) -! getTypeBinaryOutputInfo(attForm->atttypid, - &out_func_oid, - &isvarlena); - else -! getTypeOutputInfo(attForm->atttypid, - &out_func_oid, - &isvarlena); -! fmgr_info(out_func_oid, out_fmgr); - } - - /* -*************** CopyTo(CopyState cstate) -*** 1385,1391 **** - CopySendChar(cstate, cstate->delim[0]); - hdr_delim = true; - -! colname = NameStr(attr[attnum - 1]->attname); - - CopyAttributeOutCSV(cstate, colname, false, - list_length(cstate->attnumlist) == 1); ---- 1448,1461 ---- - CopySendChar(cstate, cstate->delim[0]); - hdr_delim = true; - -! if (SystemAttributeIsWritable(attnum)) -! { -! Form_pg_attribute attForm -! = SystemAttributeDefinition(attnum, true); -! colname = NameStr(attForm->attname); -! } -! else -! colname = NameStr(attr[attnum - 1]->attname); - - CopyAttributeOutCSV(cstate, colname, false, - list_length(cstate->attnumlist) == 1); -*************** CopyTo(CopyState cstate) -*** 1411,1421 **** - { - CHECK_FOR_INTERRUPTS(); - - /* Deconstruct the tuple ... faster than repeated heap_getattr */ - heap_deform_tuple(tuple, tupDesc, values, nulls); - - /* Format and send the data */ -! CopyOneRowTo(cstate, HeapTupleGetOid(tuple), values, nulls); - } - - heap_endscan(scandesc); ---- 1481,1495 ---- - { - CHECK_FOR_INTERRUPTS(); - -+ /* check Row-level permission on the tuple */ -+ if (!rowlvCopyToTuple(cstate->rel, tuple)) -+ continue; -+ - /* Deconstruct the tuple ... faster than repeated heap_getattr */ - heap_deform_tuple(tuple, tupDesc, values, nulls); - - /* Format and send the data */ -! CopyOneRowTo(cstate, tuple, values, nulls); - } - - heap_endscan(scandesc); -*************** CopyTo(CopyState cstate) -*** 1441,1447 **** - * Emit one row during CopyTo(). - */ - static void -! CopyOneRowTo(CopyState cstate, Oid tupleOid, Datum *values, bool *nulls) - { - bool need_delim = false; - FmgrInfo *out_functions = cstate->out_functions; ---- 1515,1522 ---- - * Emit one row during CopyTo(). - */ - static void -! CopyOneRowTo(CopyState cstate, HeapTuple tuple, -! Datum *values, bool *nulls) - { - bool need_delim = false; - FmgrInfo *out_functions = cstate->out_functions; -*************** CopyOneRowTo(CopyState cstate, Oid tuple -*** 1461,1467 **** - { - /* Hack --- assume Oid is same size as int32 */ - CopySendInt32(cstate, sizeof(int32)); -! CopySendInt32(cstate, tupleOid); - } - } - else ---- 1536,1542 ---- - { - /* Hack --- assume Oid is same size as int32 */ - CopySendInt32(cstate, sizeof(int32)); -! CopySendInt32(cstate, HeapTupleGetOid(tuple)); - } - } - else -*************** CopyOneRowTo(CopyState cstate, Oid tuple -*** 1471,1477 **** - if (cstate->oids) - { - string = DatumGetCString(DirectFunctionCall1(oidout, -! ObjectIdGetDatum(tupleOid))); - CopySendString(cstate, string); - need_delim = true; - } ---- 1546,1552 ---- - if (cstate->oids) - { - string = DatumGetCString(DirectFunctionCall1(oidout, -! ObjectIdGetDatum(HeapTupleGetOid(tuple)))); - CopySendString(cstate, string); - need_delim = true; - } -*************** CopyOneRowTo(CopyState cstate, Oid tuple -*** 1480,1487 **** - foreach(cur, cstate->attnumlist) - { - int attnum = lfirst_int(cur); -! Datum value = values[attnum - 1]; -! bool isnull = nulls[attnum - 1]; - - if (!cstate->binary) - { ---- 1555,1565 ---- - foreach(cur, cstate->attnumlist) - { - int attnum = lfirst_int(cur); -! Oid relid; -! Datum value; -! bool isnull; -! bool force_quot; -! FmgrInfo *out_fmgr; - - if (!cstate->binary) - { -*************** CopyOneRowTo(CopyState cstate, Oid tuple -*** 1490,1495 **** ---- 1568,1591 ---- - need_delim = true; - } - -+ switch (attnum) -+ { -+ case SecurityAttributeNumber: -+ relid = RelationGetRelid(cstate->rel); -+ value = securitySysattSecLabelOut(relid, tuple); -+ isnull = false; -+ force_quot = cstate->seclabel_force_quot; -+ out_fmgr = &cstate->seclabel_out_function; -+ break; -+ -+ default: -+ value = values[attnum - 1]; -+ isnull = nulls[attnum - 1]; -+ force_quot = cstate->force_quote_flags[attnum - 1]; -+ out_fmgr = &out_functions[attnum - 1]; -+ break; -+ } -+ - if (isnull) - { - if (!cstate->binary) -*************** CopyOneRowTo(CopyState cstate, Oid tuple -*** 1501,1511 **** - { - if (!cstate->binary) - { -! string = OutputFunctionCall(&out_functions[attnum - 1], -! value); - if (cstate->csv_mode) -! CopyAttributeOutCSV(cstate, string, -! cstate->force_quote_flags[attnum - 1], - list_length(cstate->attnumlist) == 1); - else - CopyAttributeOutText(cstate, string); ---- 1597,1605 ---- - { - if (!cstate->binary) - { -! string = OutputFunctionCall(out_fmgr, value); - if (cstate->csv_mode) -! CopyAttributeOutCSV(cstate, string, force_quot, - list_length(cstate->attnumlist) == 1); - else - CopyAttributeOutText(cstate, string); -*************** CopyOneRowTo(CopyState cstate, Oid tuple -*** 1514,1521 **** - { - bytea *outputbytes; - -! outputbytes = SendFunctionCall(&out_functions[attnum - 1], -! value); - CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ); - CopySendData(cstate, VARDATA(outputbytes), - VARSIZE(outputbytes) - VARHDRSZ); ---- 1608,1614 ---- - { - bytea *outputbytes; - -! outputbytes = SendFunctionCall(out_fmgr, value); - CopySendInt32(cstate, VARSIZE(outputbytes) - VARHDRSZ); - CopySendData(cstate, VARDATA(outputbytes), - VARSIZE(outputbytes) - VARHDRSZ); -*************** CopyFrom(CopyState cstate) -*** 1649,1656 **** ---- 1742,1751 ---- - num_defaults; - FmgrInfo *in_functions; - FmgrInfo oid_in_function; -+ FmgrInfo seclabel_in_function; - Oid *typioparams; - Oid oid_typioparam; -+ Oid seclabel_typioparam; - int attnum; - int i; - Oid in_func_oid; -*************** CopyFrom(CopyState cstate) -*** 1753,1758 **** ---- 1848,1856 ---- - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), - errmsg("\"%s\" is a directory", cstate->filename))); -+ -+ /* SELinux checks file:{read} permission */ -+ sepgsqlCheckFileRead(fileno(cstate->copy_file), cstate->filename); - } - - tupDesc = RelationGetDescr(cstate->rel); -*************** CopyFrom(CopyState cstate) -*** 1888,1893 **** ---- 1986,2003 ---- - fmgr_info(in_func_oid, &oid_in_function); - } - -+ if (list_member_int(cstate->attnumlist, -+ SecurityAttributeNumber)) -+ { -+ if (!cstate->binary) -+ getTypeInputInfo(TEXTOID, -+ &in_func_oid, &seclabel_typioparam); -+ else -+ getTypeBinaryInputInfo(TEXTOID, -+ &in_func_oid, &seclabel_typioparam); -+ fmgr_info(in_func_oid, &seclabel_in_function); -+ } -+ - values = (Datum *) palloc(num_phys_attrs * sizeof(Datum)); - nulls = (bool *) palloc(num_phys_attrs * sizeof(bool)); - -*************** CopyFrom(CopyState cstate) -*** 1922,1927 **** ---- 2032,2038 ---- - { - bool skip_tuple; - Oid loaded_oid = InvalidOid; -+ Oid loaded_seclabel = InvalidOid; - - CHECK_FOR_INTERRUPTS(); - -*************** CopyFrom(CopyState cstate) -*** 1993,2006 **** - /* Loop to read the user attributes on the line. */ - foreach(cur, cstate->attnumlist) - { - int attnum = lfirst_int(cur); - int m = attnum - 1; - - if (fieldno >= fldct) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("missing data for column \"%s\"", -! NameStr(attr[m]->attname)))); - string = field_strings[fieldno++]; - - if (cstate->csv_mode && string == NULL && ---- 2104,2124 ---- - /* Loop to read the user attributes on the line. */ - foreach(cur, cstate->attnumlist) - { -+ Form_pg_attribute attForm; -+ Datum dat; - int attnum = lfirst_int(cur); - int m = attnum - 1; - -+ if (SystemAttributeIsWritable(attnum)) -+ attForm = SystemAttributeDefinition(attnum, true); -+ else -+ attForm = attr[m]; -+ - if (fieldno >= fldct) - ereport(ERROR, - (errcode(ERRCODE_BAD_COPY_FILE_FORMAT), - errmsg("missing data for column \"%s\"", -! NameStr(attForm->attname)))); - string = field_strings[fieldno++]; - - if (cstate->csv_mode && string == NULL && -*************** CopyFrom(CopyState cstate) -*** 2010,2023 **** - string = cstate->null_print; - } - -! cstate->cur_attname = NameStr(attr[m]->attname); - cstate->cur_attval = string; -! values[m] = InputFunctionCall(&in_functions[m], -! string, -! typioparams[m], -! attr[m]->atttypmod); -! if (string != NULL) -! nulls[m] = false; - cstate->cur_attname = NULL; - cstate->cur_attval = NULL; - } ---- 2128,2167 ---- - string = cstate->null_print; - } - -! cstate->cur_attname = NameStr(attForm->attname); - cstate->cur_attval = string; -! -! switch (attnum) -! { -! case SecurityAttributeNumber: -! if (!string) -! break; -! -! dat = InputFunctionCall(&seclabel_in_function, -! string, -! seclabel_typioparam, -! attForm->atttypmod); -! loaded_seclabel -! = securityTransSecLabelIn(RelationGetRelid(cstate->rel), -! TextDatumGetCString(dat)); -! break; -! -! default: -! if (cstate->csv_mode && string == NULL && -! cstate->force_notnull_flags[m]) -! { -! /* Go ahead and read the NULL string */ -! string = cstate->null_print; -! } -! -! values[m] = InputFunctionCall(&in_functions[m], -! string, -! typioparams[m], -! attForm->atttypmod); -! if (string != NULL) -! nulls[m] = false; -! break; -! } - cstate->cur_attname = NULL; - cstate->cur_attval = NULL; - } -*************** CopyFrom(CopyState cstate) -*** 2063,2079 **** - i = 0; - foreach(cur, cstate->attnumlist) - { - int attnum = lfirst_int(cur); - int m = attnum - 1; - -! cstate->cur_attname = NameStr(attr[m]->attname); - i++; -! values[m] = CopyReadBinaryAttribute(cstate, -! i, -! &in_functions[m], -! typioparams[m], -! attr[m]->atttypmod, -! &nulls[m]); - cstate->cur_attname = NULL; - } - } ---- 2207,2247 ---- - i = 0; - foreach(cur, cstate->attnumlist) - { -+ Form_pg_attribute attForm; -+ Datum dat; - int attnum = lfirst_int(cur); - int m = attnum - 1; - -! if (SystemAttributeIsWritable(attnum)) -! attForm = SystemAttributeDefinition(attnum, false); -! else -! attForm = attr[m]; -! -! cstate->cur_attname = NameStr(attForm->attname); - i++; -! -! switch (attnum) -! { -! case SecurityAttributeNumber: -! dat = CopyReadBinaryAttribute(cstate, i, -! &seclabel_in_function, -! seclabel_typioparam, -! attForm->atttypmod, -! &isnull); -! if (!isnull) -! loaded_seclabel -! = securityTransSecLabelIn(RelationGetRelid(cstate->rel), -! TextDatumGetCString(dat)); -! break; -! -! default: -! values[m] = CopyReadBinaryAttribute(cstate, i, -! &in_functions[m], -! typioparams[m], -! attr[m]->atttypmod, -! &nulls[m]); -! break; -! } - cstate->cur_attname = NULL; - } - } -*************** CopyFrom(CopyState cstate) -*** 2094,2099 **** ---- 2262,2269 ---- - - if (cstate->oids && file_has_oids) - HeapTupleSetOid(tuple, loaded_oid); -+ if (HeapTupleHasSecid(tuple)) -+ HeapTupleSetSecid(tuple, loaded_seclabel); - - /* Triggers and stuff need to be invoked in query context. */ - MemoryContextSwitchTo(oldcontext); -*************** CopyFrom(CopyState cstate) -*** 2118,2123 **** ---- 2288,2296 ---- - } - - if (!skip_tuple) -+ sepgsqlHeapTupleInsert(cstate->rel, tuple, false); -+ -+ if (!skip_tuple) - { - /* Place tuple in tuple slot */ - ExecStoreTuple(tuple, slot, InvalidBuffer, false); -*************** CopyGetAttnums(TupleDesc tupDesc, Relati -*** 3398,3403 **** ---- 3571,3583 ---- - } - if (attnum == InvalidAttrNumber) - { -+ Form_pg_attribute attForm -+ = SystemAttributeByName(name, tupDesc->tdhasoid); -+ if (attForm && SystemAttributeIsWritable(attForm->attnum)) -+ attnum = attForm->attnum; -+ } -+ if (attnum == InvalidAttrNumber) -+ { - if (rel != NULL) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), -*************** copy_dest_receive(TupleTableSlot *slot, -*** 3445,3451 **** - slot_getallattrs(slot); - - /* And send the data */ -! CopyOneRowTo(cstate, InvalidOid, slot->tts_values, slot->tts_isnull); - } - - /* ---- 3625,3632 ---- - slot_getallattrs(slot); - - /* And send the data */ -! CopyOneRowTo(cstate, slot->tts_tuple, -! slot->tts_values, slot->tts_isnull); - } - - /* -diff -Nrpc base/src/backend/commands/dbcommands.c sepgsql/src/backend/commands/dbcommands.c -*** base/src/backend/commands/dbcommands.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/dbcommands.c Tue Sep 8 23:55:48 2009 -*************** -*** 33,38 **** ---- 33,39 ---- - #include "catalog/indexing.h" - #include "catalog/pg_authid.h" - #include "catalog/pg_database.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_tablespace.h" - #include "commands/comment.h" - #include "commands/dbcommands.h" -*************** -*** 41,46 **** ---- 42,48 ---- - #include "miscadmin.h" - #include "pgstat.h" - #include "postmaster/bgwriter.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/fd.h" - #include "storage/lmgr.h" -*************** createdb(const CreatedbStmt *stmt) -*** 111,116 **** ---- 113,119 ---- - bool new_record_nulls[Natts_pg_database]; - Oid dboid; - Oid datdba; -+ Oid datsecid; - ListCell *option; - DefElem *dtablespacename = NULL; - DefElem *downer = NULL; -*************** createdb(const CreatedbStmt *stmt) -*** 119,124 **** ---- 122,128 ---- - DefElem *dcollate = NULL; - DefElem *dctype = NULL; - DefElem *dconnlimit = NULL; -+ DefElem *dseclabel = NULL; - char *dbname = stmt->dbname; - char *dbowner = NULL; - const char *dbtemplate = NULL; -*************** createdb(const CreatedbStmt *stmt) -*** 200,205 **** ---- 204,217 ---- - errmsg("LOCATION is not supported anymore"), - errhint("Consider using tablespaces instead."))); - } -+ else if (strcmp(defel->defname, "security_context") == 0) -+ { -+ if (dseclabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SYNTAX_ERROR), -+ errmsg("conflicting or redundant options"))); -+ dseclabel = defel; -+ } - else - elog(ERROR, "option \"%s\" not recognized", - defel->defname); -*************** createdb(const CreatedbStmt *stmt) -*** 272,277 **** ---- 284,292 ---- - - check_is_member_of_role(GetUserId(), datdba); - -+ /* SELinux checks db_database:{create} */ -+ datsecid = sepgsqlCheckDatabaseCreate(dbname, dseclabel); -+ - /* - * Lookup database (template) to be cloned, and obtain share lock on it. - * ShareLock allows two CREATE DATABASEs to work from the same template -*************** createdb(const CreatedbStmt *stmt) -*** 557,562 **** ---- 572,579 ---- - new_record, new_record_nulls); - - HeapTupleSetOid(tuple, dboid); -+ if (HeapTupleHasSecid(tuple)) -+ HeapTupleSetSecid(tuple, datsecid); - - simple_heap_insert(pg_database_rel, tuple); - -*************** createdb(const CreatedbStmt *stmt) -*** 573,578 **** ---- 590,598 ---- - /* Create pg_shdepend entries for objects within database */ - copyTemplateDependencies(src_dboid, dboid); - -+ /* Create pg_security entries for objects within database */ -+ securityOnCreateDatabase(src_dboid, dboid); -+ - /* - * Force a checkpoint before starting the copy. This will force dirty - * buffers out to disk, to ensure source database is up-to-date on disk -*************** dropdb(const char *dbname, bool missing_ -*** 776,781 **** ---- 796,804 ---- - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - dbname); - -+ /* SELinux checks db_database:{drop} permission */ -+ sepgsqlCheckDatabaseDrop(db_id); -+ - /* - * Disallow dropping a DB that is marked istemplate. This is just to - * prevent people from accidentally dropping template0 or template1; they -*************** dropdb(const char *dbname, bool missing_ -*** 829,834 **** ---- 852,862 ---- - dropDatabaseDependencies(db_id); - - /* -+ * Remove pg_security entries for the database. -+ */ -+ securityOnDropDatabase(db_id); -+ -+ /* - * Drop pages for this database that are in the shared buffer cache. This - * is important to ensure that no remaining backend tries to write out a - * dirty buffer to the dead database later... -*************** RenameDatabase(const char *oldname, cons -*** 913,918 **** ---- 941,949 ---- - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to rename database"))); - -+ /* SELinux: check db_database:{setattr} */ -+ sepgsqlCheckDatabaseSetattr(db_id); -+ - /* - * Make sure the new name doesn't exist. See notes for same error in - * CREATE DATABASE. -*************** movedb(const char *dbname, const char *t -*** 1025,1030 **** ---- 1056,1064 ---- - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - dbname); - -+ /* SELinux checks db_database:{setattr} */ -+ sepgsqlCheckDatabaseSetattr(db_id); -+ - /* - * Obviously can't move the tables of my own database - */ -*************** AlterDatabase(AlterDatabaseStmt *stmt, b -*** 1377,1382 **** ---- 1411,1419 ---- - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - stmt->dbname); - -+ /* SELinux checks db_database:{setattr} */ -+ sepgsqlCheckDatabaseSetattr(HeapTupleGetOid(tuple)); -+ - /* - * Build an updated tuple, perusing the information just obtained - */ -*************** AlterDatabaseSet(AlterDatabaseSetStmt *s -*** 1449,1454 **** ---- 1486,1494 ---- - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, - stmt->dbname); - -+ /* SELinux checks db_database:{setattr} */ -+ sepgsqlCheckDatabaseSetattr(HeapTupleGetOid(tuple)); -+ - memset(repl_repl, false, sizeof(repl_repl)); - repl_repl[Anum_pg_database_datconfig - 1] = true; - -*************** AlterDatabaseOwner(const char *dbname, O -*** 1571,1576 **** ---- 1611,1619 ---- - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied to change owner of database"))); - -+ /* SELinux checks db_database:{setattr} */ -+ sepgsqlCheckDatabaseSetattr(HeapTupleGetOid(tuple)); -+ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - -*************** AlterDatabaseOwner(const char *dbname, O -*** 1615,1620 **** ---- 1658,1715 ---- - */ - } - -+ /* -+ * ALTER DATABASE name SECURITY_LABEL [=] newlabel -+ */ -+ void -+ AlterDatabaseSecLabel(const char *dbname, DefElem *seclabel) -+ { -+ Relation rel; -+ HeapTuple oldtup; -+ HeapTuple newtup; -+ ScanKeyData scankey; -+ SysScanDesc scan; -+ Oid secid; -+ bool replaces[Natts_pg_database]; -+ -+ /* Fetch the old tuple */ -+ rel = heap_open(DatabaseRelationId, RowExclusiveLock); -+ ScanKeyInit(&scankey, -+ Anum_pg_database_datname, -+ BTEqualStrategyNumber, F_NAMEEQ, -+ NameGetDatum(dbname)); -+ scan = systable_beginscan(rel, DatabaseNameIndexId, true, -+ SnapshotNow, 1, &scankey); -+ oldtup = systable_getnext(scan); -+ if (!HeapTupleIsValid(oldtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_UNDEFINED_DATABASE), -+ errmsg("database \"%s\" does not exist", dbname))); -+ -+ memset(replaces, false, sizeof(replaces)); -+ newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), -+ NULL, NULL, replaces); -+ systable_endscan(scan); -+ -+ /* check DAC permission */ -+ if (!pg_database_ownercheck(HeapTupleGetOid(newtup), GetUserId())) -+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE, dbname); -+ -+ /* SELinux checks db_database:{setattr relabelfrom relabelto} */ -+ secid = sepgsqlCheckDatabaseRelabel(HeapTupleGetOid(newtup), seclabel); -+ if (!HeapTupleHasSecid(newtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s\"", dbname))); -+ HeapTupleSetSecid(newtup, secid); -+ -+ simple_heap_update(rel, &newtup->t_self, newtup); -+ CatalogUpdateIndexes(rel, newtup); -+ -+ heap_freetuple(newtup); -+ -+ heap_close(rel, RowExclusiveLock); -+ } - - /* - * Helper functions -diff -Nrpc base/src/backend/commands/foreigncmds.c sepgsql/src/backend/commands/foreigncmds.c -*** base/src/backend/commands/foreigncmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/foreigncmds.c Wed Jul 15 19:48:58 2009 -*************** -*** 27,32 **** ---- 27,33 ---- - #include "foreign/foreign.h" - #include "miscadmin.h" - #include "parser/parse_func.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/lsyscache.h" -*************** CreateForeignDataWrapper(CreateFdwStmt * -*** 380,385 **** ---- 381,389 ---- - else - fdwvalidator = InvalidOid; - -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(fdwvalidator); -+ - values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = fdwvalidator; - - nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true; -*************** AlterForeignDataWrapper(AlterFdwStmt *st -*** 473,478 **** ---- 477,485 ---- - ereport(WARNING, - (errmsg("changing the foreign-data wrapper validator can cause " - "the options for dependent objects to become invalid"))); -+ -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(fdwvalidator); - } - else - { -diff -Nrpc base/src/backend/commands/functioncmds.c sepgsql/src/backend/commands/functioncmds.c -*** base/src/backend/commands/functioncmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/functioncmds.c Tue Sep 8 23:55:48 2009 -*************** -*** 53,58 **** ---- 53,59 ---- - #include "parser/parse_expr.h" - #include "parser/parse_func.h" - #include "parser/parse_type.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/fmgroids.h" -*************** compute_attributes_sql_style(List *optio -*** 517,523 **** - bool *security_definer, - ArrayType **proconfig, - float4 *procost, -! float4 *prorows) - { - ListCell *option; - DefElem *as_item = NULL; ---- 518,525 ---- - bool *security_definer, - ArrayType **proconfig, - float4 *procost, -! float4 *prorows, -! Node **proseclabel) - { - ListCell *option; - DefElem *as_item = NULL; -*************** compute_attributes_sql_style(List *optio -*** 529,534 **** ---- 531,537 ---- - List *set_items = NIL; - DefElem *cost_item = NULL; - DefElem *rows_item = NULL; -+ DefElem *seclabel_item = NULL; - - foreach(option, options) - { -*************** compute_attributes_sql_style(List *optio -*** 558,563 **** ---- 561,574 ---- - errmsg("conflicting or redundant options"))); - windowfunc_item = defel; - } -+ else if (strcmp(defel->defname, "security_context") == 0) -+ { -+ if (seclabel_item) -+ ereport(ERROR, -+ (errcode(ERRCODE_SYNTAX_ERROR), -+ errmsg("conflicting or redundant options"))); -+ seclabel_item = defel; -+ } - else if (compute_common_attribute(defel, - &volatility_item, - &strict_item, -*************** compute_attributes_sql_style(List *optio -*** 622,627 **** ---- 633,640 ---- - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("ROWS must be positive"))); - } -+ if (seclabel_item) -+ *proseclabel = (Node *)seclabel_item; - } - - -*************** CreateFunction(CreateFunctionStmt *stmt, -*** 762,767 **** ---- 775,781 ---- - ArrayType *proconfig; - float4 procost; - float4 prorows; -+ Node *proseclabel; - HeapTuple languageTuple; - Form_pg_language languageStruct; - List *as_clause; -*************** CreateFunction(CreateFunctionStmt *stmt, -*** 784,796 **** - proconfig = NULL; - procost = -1; /* indicates not set */ - prorows = -1; /* indicates not set */ - - /* override attributes from explicit list */ - compute_attributes_sql_style(stmt->options, - &as_clause, &language, - &isWindowFunc, &volatility, - &isStrict, &security, -! &proconfig, &procost, &prorows); - - /* Convert language name to canonical case */ - languageName = case_translate_language_name(language); ---- 798,811 ---- - proconfig = NULL; - procost = -1; /* indicates not set */ - prorows = -1; /* indicates not set */ -+ proseclabel = NULL; - - /* override attributes from explicit list */ - compute_attributes_sql_style(stmt->options, - &as_clause, &language, - &isWindowFunc, &volatility, - &isStrict, &security, -! &proconfig, &procost, &prorows, &proseclabel); - - /* Convert language name to canonical case */ - languageName = case_translate_language_name(language); -*************** CreateFunction(CreateFunctionStmt *stmt, -*** 926,932 **** - parameterDefaults, - PointerGetDatum(proconfig), - procost, -! prorows); - } - - ---- 941,948 ---- - parameterDefaults, - PointerGetDatum(proconfig), - procost, -! prorows, -! proseclabel); - } - - -*************** RenameFunction(List *name, List *argtype -*** 1112,1117 **** ---- 1128,1138 ---- - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - -+ /* SELinux permission checks */ -+ sepgsqlCheckProcedureSetattr(procOid); -+ sepgsqlCheckSchemaRemoveName(namespaceOid); -+ sepgsqlCheckSchemaAddName(namespaceOid); -+ - /* rename */ - namestrcpy(&(procForm->proname), newname); - simple_heap_update(rel, &tup->t_self, tup); -*************** AlterFunctionOwner_internal(Relation rel -*** 1220,1225 **** ---- 1241,1248 ---- - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(procForm->pronamespace)); - } -+ /* SELinux permission checks */ -+ sepgsqlCheckProcedureSetattr(procOid); - - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); -*************** AlterFunctionOwner_internal(Relation rel -*** 1258,1263 **** ---- 1281,1337 ---- - } - - /* -+ * ALTER FUNCTION name(args,...) SECURITY_LABEL [=] newlabel -+ */ -+ void -+ AlterFunctionSecLabel(List *name, List *argtypes, DefElem *seclabel) -+ { -+ Relation rel; -+ HeapTuple oldtup; -+ HeapTuple newtup; -+ Oid procOid; -+ Oid secid; -+ bool replaces[Natts_pg_proc]; -+ -+ /* open pg_proc system catalog */ -+ rel = heap_open(ProcedureRelationId, RowExclusiveLock); -+ -+ procOid = LookupFuncNameTypeNames(name, argtypes, false); -+ -+ oldtup = SearchSysCache(PROCOID, -+ ObjectIdGetDatum(procOid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(oldtup)) -+ elog(ERROR, "cache lookup failed for function %u", procOid); -+ -+ memset(replaces, false, sizeof(replaces)); -+ newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), -+ NULL, NULL, replaces); -+ ReleaseSysCache(oldtup); -+ -+ /* DAC permission checks */ -+ if (!pg_proc_ownercheck(HeapTupleGetOid(newtup), GetUserId())) -+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, -+ get_func_name(HeapTupleGetOid(newtup))); -+ -+ /* SELinux permission checks */ -+ secid = sepgsqlCheckProcedureRelabel(procOid, seclabel); -+ if (!HeapTupleHasSecid(newtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s\"", -+ get_func_name(procOid)))); -+ HeapTupleSetSecid(newtup, secid); -+ -+ simple_heap_update(rel, &newtup->t_self, newtup); -+ CatalogUpdateIndexes(rel, newtup); -+ -+ heap_freetuple(newtup); -+ -+ heap_close(rel, RowExclusiveLock); -+ } -+ -+ /* - * Implements the ALTER FUNCTION utility command (except for the - * RENAME and OWNER clauses, which are handled as part of the generic - * ALTER framework). -*************** AlterFunction(AlterFunctionStmt *stmt) -*** 1296,1301 **** ---- 1370,1378 ---- - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC, - NameListToString(stmt->func->funcname)); - -+ /* SELinux checks permissions */ -+ sepgsqlCheckProcedureSetattr(funcOid); -+ - if (procForm->proisagg) - ereport(ERROR, - (errcode(ERRCODE_WRONG_OBJECT_TYPE), -*************** CreateCast(CreateCastStmt *stmt) -*** 1580,1585 **** ---- 1657,1665 ---- - errmsg("cast function must not return a set"))); - - ReleaseSysCache(tuple); -+ -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(funcid); - } - else - { -*************** AlterFunctionNamespace(List *name, List -*** 1897,1902 **** ---- 1977,1987 ---- - NameStr(proc->proname), - newschema))); - -+ /* SELinux checks permissions */ -+ sepgsqlCheckProcedureSetattr(procOid); -+ sepgsqlCheckSchemaRemoveName(oldNspOid); -+ sepgsqlCheckSchemaAddName(nspOid); -+ - /* OK, modify the pg_proc row */ - - /* tup is a copy, so we can scribble directly on it */ -diff -Nrpc base/src/backend/commands/lockcmds.c sepgsql/src/backend/commands/lockcmds.c -*** base/src/backend/commands/lockcmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/lockcmds.c Wed Jul 15 19:35:52 2009 -*************** -*** 20,25 **** ---- 20,26 ---- - #include "commands/lockcmds.h" - #include "miscadmin.h" - #include "parser/parse_clause.h" -+ #include "security/sepgsql.h" - #include "storage/lmgr.h" - #include "utils/acl.h" - #include "utils/lsyscache.h" -*************** LockTableRecurse(Oid reloid, RangeVar *r -*** 140,145 **** ---- 141,149 ---- - errmsg("\"%s\" is not a table", - RelationGetRelationName(rel)))); - -+ /* SELinux: check db_table:{lock} permission */ -+ sepgsqlCheckTableLock(reloid); -+ - /* - * If requested, recurse to children. We use find_inheritance_children - * not find_all_inheritors to avoid taking locks far in advance of -diff -Nrpc base/src/backend/commands/proclang.c sepgsql/src/backend/commands/proclang.c -*** base/src/backend/commands/proclang.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/proclang.c Wed Jul 15 19:48:58 2009 -*************** -*** 30,35 **** ---- 30,36 ---- - #include "miscadmin.h" - #include "parser/gramparse.h" - #include "parser/parse_func.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/fmgroids.h" -*************** CreateProceduralLanguage(CreatePLangStmt -*** 151,157 **** - NIL, - PointerGetDatum(NULL), - 1, -! 0); - } - - /* ---- 152,159 ---- - NIL, - PointerGetDatum(NULL), - 1, -! 0, -! NULL); - } - - /* -*************** CreateProceduralLanguage(CreatePLangStmt -*** 186,197 **** - NIL, - PointerGetDatum(NULL), - 1, -! 0); - } - } - else - valOid = InvalidOid; - - /* ok, create it */ - create_proc_lang(languageName, GetUserId(), handlerOid, valOid, - pltemplate->tmpltrusted); ---- 188,204 ---- - NIL, - PointerGetDatum(NULL), - 1, -! 0, -! NULL); - } - } - else - valOid = InvalidOid; - -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(handlerOid); -+ sepgsqlCheckProcedureInstall(valOid); -+ - /* ok, create it */ - create_proc_lang(languageName, GetUserId(), handlerOid, valOid, - pltemplate->tmpltrusted); -*************** CreateProceduralLanguage(CreatePLangStmt -*** 256,261 **** ---- 263,272 ---- - else - valOid = InvalidOid; - -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(handlerOid); -+ sepgsqlCheckProcedureInstall(valOid); -+ - /* ok, create it */ - create_proc_lang(languageName, GetUserId(), handlerOid, valOid, - stmt->pltrusted); -diff -Nrpc base/src/backend/commands/schemacmds.c sepgsql/src/backend/commands/schemacmds.c -*** base/src/backend/commands/schemacmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/schemacmds.c Tue Sep 8 23:55:48 2009 -*************** -*** 25,30 **** ---- 25,31 ---- - #include "commands/schemacmds.h" - #include "miscadmin.h" - #include "parser/parse_utilcmd.h" -+ #include "security/sepgsql.h" - #include "tcop/utility.h" - #include "utils/acl.h" - #include "utils/builtins.h" -*************** CreateSchemaCommand(CreateSchemaStmt *st -*** 48,53 **** ---- 49,55 ---- - ListCell *parsetree_item; - Oid owner_uid; - Oid saved_uid; -+ Oid nspsecid; - bool saved_secdefcxt; - AclResult aclresult; - -*************** CreateSchemaCommand(CreateSchemaStmt *st -*** 75,80 **** ---- 77,85 ---- - - check_is_member_of_role(saved_uid, owner_uid); - -+ /* SELinux checks db_schema:{create} */ -+ nspsecid = sepgsqlCheckSchemaCreate(schemaName, (DefElem *)stmt->secLabel, false); -+ - /* Additional check to protect reserved schema names */ - if (!allowSystemTableMods && IsReservedName(schemaName)) - ereport(ERROR, -*************** CreateSchemaCommand(CreateSchemaStmt *st -*** 94,100 **** - SetUserIdAndContext(owner_uid, true); - - /* Create the schema's namespace */ -! namespaceId = NamespaceCreate(schemaName, owner_uid); - - /* Advance cmd counter to make the namespace visible */ - CommandCounterIncrement(); ---- 99,105 ---- - SetUserIdAndContext(owner_uid, true); - - /* Create the schema's namespace */ -! namespaceId = NamespaceCreate(schemaName, owner_uid, nspsecid); - - /* Advance cmd counter to make the namespace visible */ - CommandCounterIncrement(); -*************** RenameSchema(const char *oldname, const -*** 267,274 **** - errmsg("schema \"%s\" does not exist", oldname))); - - /* make sure the new name doesn't exist */ -! if (HeapTupleIsValid( -! SearchSysCache(NAMESPACENAME, - CStringGetDatum(newname), - 0, 0, 0))) - ereport(ERROR, ---- 272,278 ---- - errmsg("schema \"%s\" does not exist", oldname))); - - /* make sure the new name doesn't exist */ -! if (HeapTupleIsValid(SearchSysCache(NAMESPACENAME, - CStringGetDatum(newname), - 0, 0, 0))) - ereport(ERROR, -*************** RenameSchema(const char *oldname, const -*** 286,291 **** ---- 290,298 ---- - aclcheck_error(aclresult, ACL_KIND_DATABASE, - get_database_name(MyDatabaseId)); - -+ /* SELinux checks db_schema:{setattr} */ -+ sepgsqlCheckSchemaSetattr(HeapTupleGetOid(tup)); -+ - if (!allowSystemTableMods && IsReservedName(newname)) - ereport(ERROR, - (errcode(ERRCODE_RESERVED_NAME), -*************** AlterSchemaOwner_internal(HeapTuple tup, -*** 397,402 **** ---- 404,412 ---- - aclcheck_error(aclresult, ACL_KIND_DATABASE, - get_database_name(MyDatabaseId)); - -+ /* SELinux checks db_schema:{setattr} */ -+ sepgsqlCheckSchemaSetattr(HeapTupleGetOid(tup)); -+ - memset(repl_null, false, sizeof(repl_null)); - memset(repl_repl, false, sizeof(repl_repl)); - -*************** AlterSchemaOwner_internal(HeapTuple tup, -*** 431,433 **** ---- 441,489 ---- - } - - } -+ -+ /* -+ * ALTER SCHEMA name SECURITY_LABEL [=] newlabel -+ */ -+ void -+ AlterSchemaSecLabel(const char *name, DefElem *secLabel) -+ { -+ Relation rel; -+ HeapTuple oldtup; -+ HeapTuple newtup; -+ Oid secid; -+ bool replaces[Natts_pg_namespace]; -+ -+ /* open pg_namespace relation */ -+ rel = heap_open(NamespaceRelationId, RowExclusiveLock); -+ oldtup = SearchSysCache(NAMESPACENAME, -+ CStringGetDatum(name), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(oldtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_UNDEFINED_SCHEMA), -+ errmsg("schema \"%s\" does not exist", name))); -+ -+ memset(replaces, false, sizeof(replaces)); -+ newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), -+ NULL, NULL, replaces); -+ ReleaseSysCache(oldtup); -+ -+ /* DAC permission check */ -+ if (!pg_namespace_ownercheck(HeapTupleGetOid(newtup), GetUserId())) -+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE, name); -+ /* SELinux checks db_schema:{setattr relabelfrom relabelto} */ -+ secid = sepgsqlCheckSchemaRelabel(HeapTupleGetOid(newtup), secLabel); -+ if (!HeapTupleHasSecid(newtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s\"", name))); -+ HeapTupleSetSecid(newtup, secid); -+ -+ simple_heap_update(rel, &newtup->t_self, newtup); -+ CatalogUpdateIndexes(rel, newtup); -+ -+ heap_freetuple(newtup); -+ -+ heap_close(rel, RowExclusiveLock); -+ } -diff -Nrpc base/src/backend/commands/sequence.c sepgsql/src/backend/commands/sequence.c -*** base/src/backend/commands/sequence.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/sequence.c Wed Jul 15 19:37:35 2009 -*************** -*** 26,31 **** ---- 26,32 ---- - #include "commands/tablecmds.h" - #include "miscadmin.h" - #include "nodes/makefuncs.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/lmgr.h" - #include "storage/proc.h" -*************** DefineSequence(CreateSeqStmt *seq) -*** 201,206 **** ---- 202,208 ---- - stmt->options = list_make1(defWithOids(false)); - stmt->oncommit = ONCOMMIT_NOOP; - stmt->tablespacename = NULL; -+ stmt->secLabel = seq->secLabel; - - seqoid = DefineRelation(stmt, RELKIND_SEQUENCE); - -*************** AlterSequence(AlterSeqStmt *stmt) -*** 328,333 **** ---- 330,337 ---- - if (!pg_class_ownercheck(relid, GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, - stmt->sequence->relname); -+ /* SELinux checks db_sequence:{setattr} */ -+ sepgsqlCheckTableSetattr(relid); - - /* do the work */ - AlterSequenceInternal(relid, stmt->options); -*************** nextval_internal(Oid relid) -*** 467,472 **** ---- 471,479 ---- - errmsg("permission denied for sequence %s", - RelationGetRelationName(seqrel)))); - -+ /* SELinux check db_sequence:{next_value} */ -+ sepgsqlCheckSequenceNextValue(elm->relid); -+ - if (elm->last != elm->cached) /* some numbers were cached */ - { - Assert(elm->last_valid); -*************** currval_oid(PG_FUNCTION_ARGS) -*** 662,667 **** ---- 669,677 ---- - errmsg("permission denied for sequence %s", - RelationGetRelationName(seqrel)))); - -+ /* SELinux check db_sequence:{get_value} */ -+ sepgsqlCheckSequenceGetValue(elm->relid); -+ - if (!elm->last_valid) - ereport(ERROR, - (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), -*************** lastval(PG_FUNCTION_ARGS) -*** 706,711 **** ---- 716,724 ---- - errmsg("permission denied for sequence %s", - RelationGetRelationName(seqrel)))); - -+ /* SELinux check db_sequence:{get_value} */ -+ sepgsqlCheckSequenceGetValue(last_used_seq->relid); -+ - result = last_used_seq->last; - relation_close(seqrel, NoLock); - -*************** do_setval(Oid relid, int64 next, bool is -*** 742,747 **** ---- 755,763 ---- - errmsg("permission denied for sequence %s", - RelationGetRelationName(seqrel)))); - -+ /* SELinux check db_sequence:{set_value} */ -+ sepgsqlCheckSequenceSetValue(elm->relid); -+ - /* lock page' buffer and read tuple */ - seq = read_info(elm, seqrel, &buf); - -diff -Nrpc base/src/backend/commands/tablecmds.c sepgsql/src/backend/commands/tablecmds.c -*** base/src/backend/commands/tablecmds.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/commands/tablecmds.c Tue Sep 8 23:55:48 2009 -*************** -*** 62,67 **** ---- 62,68 ---- - #include "parser/parser.h" - #include "rewrite/rewriteDefine.h" - #include "rewrite/rewriteHandler.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/lmgr.h" - #include "storage/smgr.h" -*************** DefineRelation(CreateStmt *stmt, char re -*** 351,356 **** ---- 352,358 ---- - List *rawDefaults; - List *cookedDefaults; - Datum reloptions; -+ Oid *secLabels; - ListCell *listptr; - AttrNumber attnum; - static char *validnsps[] = HEAP_RELOPT_NAMESPACES; -*************** DefineRelation(CreateStmt *stmt, char re -*** 444,449 **** ---- 446,455 ---- - localHasOids = interpretOidsOption(stmt->options); - descriptor->tdhasoid = (localHasOids || parentOidCount > 0); - -+ /* SELinux checks db_table:{create} and db_column:{create} */ -+ secLabels = sepgsqlCreateTableColumns(stmt, relname, namespaceId, -+ descriptor, relkind); -+ - /* - * Find columns with default values and prepare for insertion of the - * defaults. Pre-cooked (that is, inherited) defaults go into a list of -*************** DefineRelation(CreateStmt *stmt, char re -*** 513,519 **** - parentOidCount, - stmt->oncommit, - reloptions, -! allowSystemTableMods); - - StoreCatalogInheritance(relationId, inheritOids); - ---- 519,526 ---- - parentOidCount, - stmt->oncommit, - reloptions, -! allowSystemTableMods, -! secLabels); - - StoreCatalogInheritance(relationId, inheritOids); - -*************** truncate_check_rel(Relation rel) -*** 1042,1047 **** ---- 1049,1057 ---- - errmsg("permission denied: \"%s\" is a system catalog", - RelationGetRelationName(rel)))); - -+ /* SELinux: check db_table:{delete} permission */ -+ sepgsqlCheckTableTruncate(rel); -+ - /* - * We can never allow truncation of shared or nailed-in-cache relations, - * because we can't support changing their relfilenode values. -*************** renameatt(Oid myrelid, -*** 1921,1926 **** ---- 1931,1939 ---- - errmsg("cannot rename system column \"%s\"", - oldattname))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(myrelid, attnum); -+ - /* - * if the attribute is inherited, forbid the renaming, unless we are - * already inside a recursive rename. -*************** ATRewriteTables(List **wqueue) -*** 2850,2857 **** - /* - * The new relation is local to our transaction and we know - * nothing depends on it, so DROP_RESTRICT should be OK. - */ -! performDeletion(&object, DROP_RESTRICT); - /* performDeletion does CommandCounterIncrement at end */ - - /* ---- 2863,2871 ---- - /* - * The new relation is local to our transaction and we know - * nothing depends on it, so DROP_RESTRICT should be OK. -+ * SELinux does not apply any permission checks here. - */ -! performDeletionNoPerms(&object, DROP_RESTRICT); - /* performDeletion does CommandCounterIncrement at end */ - - /* -*************** ATRewriteTable(AlteredTableInfo *tab, Oi -*** 3076,3086 **** ---- 3090,3103 ---- - if (newrel) - { - Oid tupOid = InvalidOid; -+ Oid tupSecid = InvalidOid; - - /* Extract data from old tuple */ - heap_deform_tuple(tuple, oldTupDesc, values, isnull); - if (oldTupDesc->tdhasoid) - tupOid = HeapTupleGetOid(tuple); -+ if (HeapTupleHasSecid(tuple)) -+ tupSecid = HeapTupleGetSecid(tuple); - - /* Set dropped attributes to null in new tuple */ - foreach(lc, dropped_attrs) -*************** ATRewriteTable(AlteredTableInfo *tab, Oi -*** 3112,3117 **** ---- 3129,3137 ---- - /* Preserve OID, if any */ - if (newTupDesc->tdhasoid) - HeapTupleSetOid(tuple, tupOid); -+ /* Preserve SID, if any */ -+ if (HeapTupleHasSecid(tuple)) -+ HeapTupleSetSecid(tuple, tupSecid); - } - - /* Now check any constraints on the possibly-changed tuple */ -*************** ATSimplePermissions(Relation rel, bool a -*** 3242,3247 **** ---- 3262,3270 ---- - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied: \"%s\" is a system catalog", - RelationGetRelationName(rel)))); -+ -+ /* SELinux checks db_table:{setattr} */ -+ sepgsqlCheckTableSetattr(RelationGetRelid(rel)); - } - - /* -*************** ATSimplePermissionsRelationOrIndex(Relat -*** 3271,3276 **** ---- 3294,3302 ---- - (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), - errmsg("permission denied: \"%s\" is a system catalog", - RelationGetRelationName(rel)))); -+ -+ /* SELinux checks db_table:{setattr} */ -+ sepgsqlCheckTableSetattr(RelationGetRelid(rel)); - } - - /* -*************** ATExecAddColumn(AlteredTableInfo *tab, R -*** 3509,3514 **** ---- 3535,3541 ---- - HeapTuple typeTuple; - Oid typeOid; - int32 typmod; -+ Oid attsecid; - Form_pg_type tform; - Expr *defval; - -*************** ATExecAddColumn(AlteredTableInfo *tab, R -*** 3546,3551 **** ---- 3573,3581 ---- - errmsg("child table \"%s\" has a conflicting \"%s\" column", - RelationGetRelationName(rel), colDef->colname))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(myrelid, childatt->attnum); -+ - /* Bump the existing child att's inhcount */ - childatt->attinhcount++; - simple_heap_update(attrdesc, &tuple->t_self, tuple); -*************** ATExecAddColumn(AlteredTableInfo *tab, R -*** 3585,3590 **** ---- 3615,3624 ---- - errmsg("column \"%s\" of relation \"%s\" already exists", - colDef->colname, RelationGetRelationName(rel)))); - -+ /* SELinux checks db_column:{create} */ -+ attsecid = sepgsqlCheckColumnCreate(myrelid, colDef->colname, -+ (DefElem *)colDef->secLabel); -+ - /* Determine the new attribute's number */ - if (isOid) - newattnum = ObjectIdAttributeNumber; -*************** ATExecAddColumn(AlteredTableInfo *tab, R -*** 3627,3633 **** - - ReleaseSysCache(typeTuple); - -! InsertPgAttributeTuple(attrdesc, &attribute, NULL); - - heap_close(attrdesc, RowExclusiveLock); - ---- 3661,3667 ---- - - ReleaseSysCache(typeTuple); - -! InsertPgAttributeTuple(attrdesc, &attribute, NULL, attsecid); - - heap_close(attrdesc, RowExclusiveLock); - -*************** ATExecDropNotNull(Relation rel, const ch -*** 3832,3837 **** ---- 3866,3874 ---- - errmsg("cannot alter system column \"%s\"", - colName))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(RelationGetRelid(rel), attnum); -+ - /* - * Check that the attribute is not in a primary key - */ -*************** ATExecSetNotNull(AlteredTableInfo *tab, -*** 3924,3929 **** ---- 3961,3969 ---- - errmsg("cannot alter system column \"%s\"", - colName))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(RelationGetRelid(rel), attnum); -+ - /* - * Okay, actually perform the catalog change ... if needed - */ -*************** ATExecColumnDefault(Relation rel, const -*** 3969,3974 **** ---- 4009,4017 ---- - errmsg("cannot alter system column \"%s\"", - colName))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(RelationGetRelid(rel), attnum); -+ - /* - * Remove any old default for the column. We use RESTRICT here for - * safety, but at present we do not expect anything to depend on the -*************** ATPrepSetStatistics(Relation rel, const -*** 4016,4021 **** ---- 4059,4066 ---- - if (!pg_class_ownercheck(RelationGetRelid(rel), GetUserId())) - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, - RelationGetRelationName(rel)); -+ /* SELinux checks db_table:{setatr} */ -+ sepgsqlCheckTableSetattr(RelationGetRelid(rel)); - } - - static void -*************** ATExecSetStatistics(Relation rel, const -*** 4065,4070 **** ---- 4110,4118 ---- - errmsg("cannot alter system column \"%s\"", - colName))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(RelationGetRelid(rel), attrtuple->attnum); -+ - attrtuple->attstattarget = newtarget; - - simple_heap_update(attrelation, &tuple->t_self, tuple); -*************** ATExecSetStorage(Relation rel, const cha -*** 4126,4131 **** ---- 4174,4182 ---- - errmsg("cannot alter system column \"%s\"", - colName))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(RelationGetRelid(rel), attrtuple->attnum); -+ - /* - * safety check: do not allow toasted storage modes unless column datatype - * is TOAST-aware. -*************** ATExecDropColumn(List **wqueue, Relation -*** 4202,4207 **** ---- 4253,4261 ---- - - ReleaseSysCache(tuple); - -+ /* SELinux checks db_column:{drop} */ -+ sepgsqlCheckColumnDrop(RelationGetRelid(rel), attnum); -+ - /* - * Propagate to children as appropriate. Unlike most other ALTER - * routines, we have to do this one level of recursion at a time; we can't -*************** checkFkeyPermissions(Relation rel, int16 -*** 5102,5108 **** - aclresult = pg_class_aclcheck(RelationGetRelid(rel), roleid, - ACL_REFERENCES); - if (aclresult == ACLCHECK_OK) -! return; - /* Else we must have REFERENCES on each column */ - for (i = 0; i < natts; i++) - { ---- 5156,5162 ---- - aclresult = pg_class_aclcheck(RelationGetRelid(rel), roleid, - ACL_REFERENCES); - if (aclresult == ACLCHECK_OK) -! goto ok; - /* Else we must have REFERENCES on each column */ - for (i = 0; i < natts; i++) - { -*************** checkFkeyPermissions(Relation rel, int16 -*** 5112,5117 **** ---- 5166,5174 ---- - aclcheck_error(aclresult, ACL_KIND_CLASS, - RelationGetRelationName(rel)); - } -+ ok: -+ /* SELinux: check db_table/db_column:{reference} */ -+ sepgsqlCheckTableReference(rel, attnums, natts); - } - - /* -*************** ATExecAlterColumnType(AlteredTableInfo * -*** 5715,5720 **** ---- 5772,5780 ---- - errmsg("cannot alter type of column \"%s\" twice", - colName))); - -+ /* SELinux checks db_column:{setattr} */ -+ sepgsqlCheckColumnSetattr(RelationGetRelid(rel), attnum); -+ - /* Look up the target type (should not fail, since prep found it) */ - typeTuple = typenameType(NULL, typename, &targettypmod); - tform = (Form_pg_type) GETSTRUCT(typeTuple); -*************** ATExecChangeOwner(Oid relationOid, Oid n -*** 6308,6313 **** ---- 6368,6375 ---- - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceOid)); - } -+ /* SELinux checks db_table:{setattr} */ -+ sepgsqlCheckTableSetattr(relationOid); - } - - memset(repl_null, false, sizeof(repl_null)); -*************** AlterSeqNamespaces(Relation classRel, Re -*** 7762,7767 **** ---- 7824,7951 ---- - relation_close(depRel, AccessShareLock); - } - -+ /* -+ * ALTER TABLE/SEQUENCE name SECURITY_LABEL [=] newlabel -+ * ALTER TABLE/SEQUENCE name ALTER column SECURITY_LABEL [=] newlabel -+ */ -+ static void -+ ExecRelationSetSecLabel(Oid relid, DefElem *seclabel) -+ { -+ Relation rel; -+ HeapTuple oldtup; -+ HeapTuple newtup; -+ Oid secid; -+ bool replaces[Natts_pg_class]; -+ -+ rel = heap_open(RelationRelationId, RowExclusiveLock); -+ oldtup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(relid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(oldtup)) -+ elog(ERROR, "cache lookup failed for relation: %u", relid); -+ -+ memset(replaces, false, sizeof(replaces)); -+ newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), -+ NULL, NULL, replaces); -+ ReleaseSysCache(oldtup); -+ -+ /* SELinux checks db_table:{setattr relabelfrom relabelto} */ -+ secid = sepgsqlCheckTableRelabel(relid, seclabel); -+ if (!HeapTupleHasSecid(newtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s\"", -+ get_rel_name(relid)))); -+ HeapTupleSetSecid(newtup, secid); -+ -+ simple_heap_update(rel, &newtup->t_self, newtup); -+ CatalogUpdateIndexes(rel, newtup); -+ -+ heap_freetuple(newtup); -+ -+ heap_close(rel, RowExclusiveLock); -+ } -+ -+ static void -+ ExecAttributeSetSecLabel(Oid relid, const char *attname, DefElem *seclabel) -+ { -+ Relation rel; -+ HeapTuple oldtup; -+ HeapTuple newtup; -+ AttrNumber attnum; -+ Oid secid; -+ bool replaces[Natts_pg_attribute]; -+ -+ rel = heap_open(AttributeRelationId, RowExclusiveLock); -+ oldtup = SearchSysCacheAttName(relid, attname); -+ if (!HeapTupleIsValid(oldtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_UNDEFINED_COLUMN), -+ errmsg("column \"%s\" of relation \"%s\" does not exist", -+ attname, get_rel_name(relid)))); -+ attnum = ((Form_pg_attribute) GETSTRUCT(oldtup))->attnum; -+ -+ memset(replaces, false, sizeof(replaces)); -+ newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel), -+ NULL, NULL, replaces); -+ ReleaseSysCache(oldtup); -+ -+ /* SELinux checks db_column:{setattr relabelfrom relabelto} */ -+ secid = sepgsqlCheckColumnRelabel(relid, attnum, seclabel); -+ if (!HeapTupleHasSecid(newtup)) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s.%s\"", -+ get_rel_name(relid), attname))); -+ HeapTupleSetSecid(newtup, secid); -+ -+ simple_heap_update(rel, &newtup->t_self, newtup); -+ CatalogUpdateIndexes(rel, newtup); -+ -+ heap_freetuple(newtup); -+ -+ heap_close(rel, RowExclusiveLock); -+ } -+ -+ void -+ AlterRelationSecLabel(RangeVar *relation, const char *attname, -+ ObjectType objtype, DefElem *seclabel) -+ { -+ Oid relid; -+ char relkind; -+ -+ /* Check relation type against type specified in the ALTER command */ -+ relid = RangeVarGetRelid(relation, false); -+ relkind = get_rel_relkind(relid); -+ -+ switch (objtype) -+ { -+ case OBJECT_TABLE: -+ case OBJECT_COLUMN: -+ if (relkind != RELKIND_RELATION) -+ ereport(ERROR, -+ (errcode(ERRCODE_WRONG_OBJECT_TYPE), -+ errmsg("\"%s\" is not a table", get_rel_name(relid)))); -+ break; -+ -+ case OBJECT_SEQUENCE: -+ if (relkind != RELKIND_SEQUENCE) -+ ereport(ERROR, -+ (errcode(ERRCODE_WRONG_OBJECT_TYPE), -+ errmsg("\"%s\" is not a sequence", get_rel_name(relid)))); -+ break; -+ -+ default: -+ elog(ERROR, "unrecognized object type: %d", (int)objtype); -+ break; -+ } -+ -+ /* Exec set security label */ -+ if (objtype != OBJECT_COLUMN) -+ ExecRelationSetSecLabel(relid, seclabel); -+ else -+ ExecAttributeSetSecLabel(relid, attname, seclabel); -+ } - - /* - * This code supports -diff -Nrpc base/src/backend/commands/trigger.c sepgsql/src/backend/commands/trigger.c -*** base/src/backend/commands/trigger.c Fri Jun 19 13:40:37 2009 ---- sepgsql/src/backend/commands/trigger.c Thu Jul 16 17:22:29 2009 -*************** -*** 33,38 **** ---- 33,39 ---- - #include "nodes/makefuncs.h" - #include "parser/parse_func.h" - #include "pgstat.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "tcop/utility.h" - #include "utils/acl.h" -*************** CreateTrigger(CreateTrigStmt *stmt, Oid -*** 182,187 **** ---- 183,191 ---- - NameListToString(stmt->funcname)))); - } - -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(funcoid); -+ - /* - * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that - * references one of the built-in RI_FKey trigger functions, assume it is -diff -Nrpc base/src/backend/commands/tsearchcmds.c sepgsql/src/backend/commands/tsearchcmds.c -*** base/src/backend/commands/tsearchcmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/tsearchcmds.c Wed Jul 15 19:48:58 2009 -*************** -*** 35,40 **** ---- 35,41 ---- - #include "miscadmin.h" - #include "nodes/makefuncs.h" - #include "parser/parse_func.h" -+ #include "security/sepgsql.h" - #include "tsearch/ts_cache.h" - #include "tsearch/ts_public.h" - #include "tsearch/ts_utils.h" -*************** get_ts_parser_func(DefElem *defel, int a -*** 110,115 **** ---- 111,119 ---- - func_signature_string(funcName, nargs, typeId), - format_type_be(retTypeId)))); - -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(procOid); -+ - return ObjectIdGetDatum(procOid); - } - -*************** get_ts_template_func(DefElem *defel, int -*** 948,953 **** ---- 952,960 ---- - func_signature_string(funcName, nargs, typeId), - format_type_be(retTypeId)))); - -+ /* SELinux checks db_procedure:{install} */ -+ sepgsqlCheckProcedureInstall(procOid); -+ - return ObjectIdGetDatum(procOid); - } - -diff -Nrpc base/src/backend/commands/typecmds.c sepgsql/src/backend/commands/typecmds.c -*** base/src/backend/commands/typecmds.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/commands/typecmds.c Tue Sep 8 23:55:48 2009 -*************** -*** 56,61 **** ---- 56,62 ---- - #include "parser/parse_expr.h" - #include "parser/parse_func.h" - #include "parser/parse_type.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/fmgroids.h" -*************** AlterDomainDefault(List *names, Node *de -*** 1543,1548 **** ---- 1544,1551 ---- - - /* Check it's a domain and check user has permission for ALTER DOMAIN */ - checkDomainOwner(tup, typename); -+ sepgsqlCheckSysobjSetattr(TypeRelationId, HeapTupleGetSecid(tup), -+ format_type_be(domainoid)); - - /* Setup new tuple */ - MemSet(new_record, (Datum) 0, sizeof(new_record)); -*************** AlterDomainNotNull(List *names, bool not -*** 1671,1676 **** ---- 1674,1681 ---- - - /* Check it's a domain and check user has permission for ALTER DOMAIN */ - checkDomainOwner(tup, typename); -+ sepgsqlCheckSysobjSetattr(TypeRelationId, HeapTupleGetSecid(tup), -+ format_type_be(domainoid)); - - /* Is the domain already set to the desired constraint? */ - if (typTup->typnotnull == notNull) -*************** AlterDomainDropConstraint(List *names, c -*** 1772,1777 **** ---- 1777,1784 ---- - - /* Check it's a domain and check user has permission for ALTER DOMAIN */ - checkDomainOwner(tup, typename); -+ sepgsqlCheckSysobjSetattr(TypeRelationId, HeapTupleGetSecid(tup), -+ format_type_be(domainoid)); - - /* Grab an appropriate lock on the pg_constraint relation */ - conrel = heap_open(ConstraintRelationId, RowExclusiveLock); -*************** AlterDomainAddConstraint(List *names, No -*** 1848,1853 **** ---- 1855,1862 ---- - - /* Check it's a domain and check user has permission for ALTER DOMAIN */ - checkDomainOwner(tup, typename); -+ sepgsqlCheckSysobjSetattr(TypeRelationId, HeapTupleGetSecid(tup), -+ format_type_be(domainoid)); - - /* Check for unsupported constraint types */ - if (IsA(newConstraint, FkConstraint)) -*************** RenameType(List *names, const char *newT -*** 2470,2475 **** ---- 2479,2490 ---- - aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE, - format_type_be(typeOid)); - -+ /* SELinux check permission */ -+ sepgsqlCheckSysobjSetattr(TypeRelationId, HeapTupleGetSecid(tup), -+ format_type_be(typeOid)); -+ sepgsqlCheckSchemaRemoveName(typTup->typnamespace); -+ sepgsqlCheckSchemaAddName(typTup->typnamespace); -+ - /* - * If it's a composite type, we need to check that it really is a - * free-standing composite type, and not a table's rowtype. We want people -*************** AlterTypeOwner(List *names, Oid newOwner -*** 2590,2595 **** ---- 2605,2613 ---- - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(typTup->typnamespace)); - } -+ /* SELinux checks permissions */ -+ sepgsqlCheckSysobjSetattr(TypeRelationId, HeapTupleGetSecid(tup), -+ format_type_be(HeapTupleGetOid(tup))); - - /* - * If it's a composite type, invoke ATExecChangeOwner so that we fix -*************** void -*** 2680,2685 **** ---- 2698,2704 ---- - AlterTypeNamespace(List *names, const char *newschema) - { - TypeName *typename; -+ HeapTuple typtup; - Oid typeOid; - Oid nspOid; - Oid elemOid; -*************** AlterTypeNamespace(List *names, const ch -*** 2706,2711 **** ---- 2725,2742 ---- - errhint("You can alter type %s, which will alter the array type as well.", - format_type_be(elemOid)))); - -+ /* SELinux checks permissions */ -+ typtup = SearchSysCache(TYPEOID, -+ ObjectIdGetDatum(typeOid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(typtup)) -+ elog(ERROR, "cache lookup failed for type: %u", typeOid); -+ sepgsqlCheckSysobjSetattr(TypeRelationId, HeapTupleGetSecid(typtup), -+ format_type_be(typeOid)); -+ sepgsqlCheckSchemaRemoveName(((Form_pg_type) GETSTRUCT(typtup))->typnamespace); -+ sepgsqlCheckSchemaAddName(nspOid); -+ ReleaseSysCache(typtup); -+ - /* and do the work */ - AlterTypeNamespaceInternal(typeOid, nspOid, false, true); - } -diff -Nrpc base/src/backend/executor/execJunk.c sepgsql/src/backend/executor/execJunk.c -*** base/src/backend/executor/execJunk.c Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/executor/execJunk.c Wed Jul 15 19:30:50 2009 -*************** -*** 60,66 **** - * An optional resultSlot can be passed as well. - */ - JunkFilter * -! ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot) - { - JunkFilter *junkfilter; - TupleDesc cleanTupType; ---- 60,67 ---- - * An optional resultSlot can be passed as well. - */ - JunkFilter * -! ExecInitJunkFilter(List *targetList, bool hasoid, bool hasseclabel, -! TupleTableSlot *slot) - { - JunkFilter *junkfilter; - TupleDesc cleanTupType; -*************** ExecInitJunkFilter(List *targetList, boo -*** 72,78 **** - /* - * Compute the tuple descriptor for the cleaned tuple. - */ -! cleanTupType = ExecCleanTypeFromTL(targetList, hasoid); - - /* - * Use the given slot, or make a new slot if we weren't given one. ---- 73,79 ---- - /* - * Compute the tuple descriptor for the cleaned tuple. - */ -! cleanTupType = ExecCleanTypeFromTL(targetList, hasoid, hasseclabel); - - /* - * Use the given slot, or make a new slot if we weren't given one. -diff -Nrpc base/src/backend/executor/execMain.c sepgsql/src/backend/executor/execMain.c -*** base/src/backend/executor/execMain.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/executor/execMain.c Wed Sep 9 16:47:01 2009 -*************** -*** 39,44 **** ---- 39,45 ---- - #include "access/xact.h" - #include "catalog/heap.h" - #include "catalog/namespace.h" -+ #include "catalog/pg_security.h" - #include "catalog/toasting.h" - #include "commands/tablespace.h" - #include "commands/trigger.h" -*************** -*** 50,55 **** ---- 51,57 ---- - #include "optimizer/clauses.h" - #include "parser/parse_clause.h" - #include "parser/parsetree.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/lmgr.h" - #include "storage/smgr.h" -*************** ExecCheckRTPerms(List *rangeTable) -*** 442,448 **** - - foreach(l, rangeTable) - { -! ExecCheckRTEPerms((RangeTblEntry *) lfirst(l)); - } - } - ---- 444,453 ---- - - foreach(l, rangeTable) - { -! RangeTblEntry *rte = (RangeTblEntry *) lfirst(l); -! -! ExecCheckRTEPerms(rte); -! sepgsqlCheckRTEPerms(rte); - } - } - -*************** InitPlan(QueryDesc *queryDesc, int eflag -*** 901,916 **** - for (i = 0; i < as_nplans; i++) - { - PlanState *subplan = appendplans[i]; - JunkFilter *j; - - if (operation == CMD_UPDATE) -! ExecCheckPlanOutput(resultRelInfo->ri_RelationDesc, -! subplan->plan->targetlist); - - j = ExecInitJunkFilter(subplan->plan->targetlist, -! resultRelInfo->ri_RelationDesc->rd_att->tdhasoid, -! ExecAllocTableSlot(estate->es_tupleTable)); -! - /* - * Since it must be UPDATE/DELETE, there had better be a - * "ctid" junk attribute in the tlist ... but ctid could ---- 906,921 ---- - for (i = 0; i < as_nplans; i++) - { - PlanState *subplan = appendplans[i]; -+ Relation resultRel = resultRelInfo->ri_RelationDesc; - JunkFilter *j; - - if (operation == CMD_UPDATE) -! ExecCheckPlanOutput(resultRel, subplan->plan->targetlist); - - j = ExecInitJunkFilter(subplan->plan->targetlist, -! RelationGetDescr(resultRel)->tdhasoid, -! RelationGetDescr(resultRel)->tdhassecid, -! ExecAllocTableSlot(estate->es_tupleTable)); - /* - * Since it must be UPDATE/DELETE, there had better be a - * "ctid" junk attribute in the tlist ... but ctid could -*************** InitPlan(QueryDesc *queryDesc, int eflag -*** 953,958 **** ---- 958,964 ---- - - j = ExecInitJunkFilter(planstate->plan->targetlist, - tupType->tdhasoid, -+ tupType->tdhassecid, - ExecAllocTableSlot(estate->es_tupleTable)); - estate->es_junkFilter = j; - if (estate->es_result_relation_info) -*************** InitPlan(QueryDesc *queryDesc, int eflag -*** 1023,1029 **** - * We assume all the sublists will generate the same output tupdesc. - */ - tupType = ExecTypeFromTL((List *) linitial(plannedstmt->returningLists), -! false); - - /* Set up a slot for the output of the RETURNING projection(s) */ - slot = ExecAllocTableSlot(estate->es_tupleTable); ---- 1029,1035 ---- - * We assume all the sublists will generate the same output tupdesc. - */ - tupType = ExecTypeFromTL((List *) linitial(plannedstmt->returningLists), -! false, false); - - /* Set up a slot for the output of the RETURNING projection(s) */ - slot = ExecAllocTableSlot(estate->es_tupleTable); -*************** ExecContextForcesOids(PlanState *plansta -*** 1346,1351 **** ---- 1352,1388 ---- - return false; - } - -+ /* -+ * ExecContextForcesSecids -+ * -+ * We need to ensure that result tuples have space for security identifier. -+ * if the security feature need to store it within the given relation. -+ */ -+ bool ExecContextForcesSecids(PlanState *planstate, bool *hassecid) -+ { -+ if (planstate->state->es_select_into) -+ { -+ *hassecid = securityTupleDescHasSecid(InvalidOid, -+ RELKIND_RELATION); -+ return true; -+ } -+ else -+ { -+ ResultRelInfo *ri = planstate->state->es_result_relation_info; -+ -+ if (ri && ri->ri_RelationDesc) -+ { -+ Oid relid = RelationGetRelid(ri->ri_RelationDesc); -+ char relkind = RelationGetForm(ri->ri_RelationDesc)->relkind; -+ -+ *hassecid = securityTupleDescHasSecid(relid, relkind); -+ -+ return true; -+ } -+ } -+ return false; -+ } -+ - /* ---------------------------------------------------------------- - * ExecEndPlan - * -*************** ExecEndPlan(PlanState *planstate, EState -*** 1426,1431 **** ---- 1463,1520 ---- - } - } - -+ /* -+ * fetchWritableSystemAttribute() fetches writable system column data -+ * using Junkfilter, and saves them at TupleTableSlot temporary. -+ * -+ * storeWritableSystemAttribute() copies these fetched data into -+ * header structure of HeapTuple. -+ */ -+ static void -+ fetchWritableSystemAttribute(JunkFilter *junkfilter, TupleTableSlot *slot, -+ Datum *tts_seclabel) -+ { -+ AttrNumber attno; -+ Datum datum; -+ bool isnull; -+ -+ /* for Security Label */ -+ attno = ExecFindJunkAttribute(junkfilter, SecurityAttributeName); -+ if (attno != InvalidAttrNumber) -+ { -+ datum = ExecGetJunkAttribute(slot, attno, &isnull); -+ if (isnull) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set NULL on \"%s\"", -+ SecurityAttributeName))); -+ *tts_seclabel = datum; -+ } -+ } -+ -+ static void -+ storeWritableSystemAttribute(Relation rel, TupleTableSlot *slot, HeapTuple tuple) -+ { -+ Oid relid = RelationGetRelid(rel); -+ Oid secid; -+ -+ /* "security_label" */ -+ if (DatumGetPointer(slot->tts_seclabel) != NULL) -+ { -+ char *seclabel = TextDatumGetCString(slot->tts_seclabel); -+ -+ if (!HeapTupleHasSecid(tuple)) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to assign security label on \"%s\"", -+ RelationGetRelationName(rel)))); -+ secid = securityTransSecLabelIn(relid, seclabel); -+ HeapTupleSetSecid(tuple, secid); -+ } -+ else if (HeapTupleHasSecid(tuple)) -+ HeapTupleSetSecid(tuple, InvalidOid); -+ } -+ - /* ---------------------------------------------------------------- - * ExecutePlan - * -*************** ExecutePlan(EState *estate, -*** 1487,1492 **** ---- 1576,1583 ---- - */ - for (;;) - { -+ Datum tts_seclabel = PointerGetDatum(NULL); -+ - /* Reset the per-output-tuple exprcontext */ - ResetPerTupleExprContext(estate); - -*************** lnext: ; -*** 1631,1636 **** ---- 1722,1732 ---- - } - - /* -+ * extract writable system attribute -+ */ -+ fetchWritableSystemAttribute(junkfilter, slot, &tts_seclabel); -+ -+ /* - * extract the 'ctid' junk attribute. - */ - if (operation == CMD_UPDATE || operation == CMD_DELETE) -*************** lnext: ; -*** 1657,1662 **** ---- 1753,1759 ---- - if (operation != CMD_DELETE) - slot = ExecFilterJunk(junkfilter, slot); - } -+ slot->tts_seclabel = tts_seclabel; - - /* - * now that we have a tuple, do the appropriate thing with it.. either -*************** ExecInsert(TupleTableSlot *slot, -*** 1781,1786 **** ---- 1878,1885 ---- - if (resultRelationDesc->rd_rel->relhasoids) - HeapTupleSetOid(tuple, InvalidOid); - -+ storeWritableSystemAttribute(resultRelationDesc, slot, tuple); -+ - /* BEFORE ROW INSERT Triggers */ - if (resultRelInfo->ri_TrigDesc && - resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_INSERT] > 0) -*************** ExecInsert(TupleTableSlot *slot, -*** 1811,1816 **** ---- 1910,1921 ---- - } - - /* -+ * SELinux assigns default security label, and -+ * it also checks db_tuple:{insert} permission -+ */ -+ sepgsqlHeapTupleInsert(resultRelationDesc, tuple, false); -+ -+ /* - * Check the constraints of the tuple - */ - if (resultRelationDesc->rd_att->constr) -*************** ExecUpdate(TupleTableSlot *slot, -*** 2018,2023 **** ---- 2123,2130 ---- - resultRelInfo = estate->es_result_relation_info; - resultRelationDesc = resultRelInfo->ri_RelationDesc; - -+ storeWritableSystemAttribute(resultRelationDesc, slot, tuple); -+ - /* BEFORE ROW UPDATE Triggers */ - if (resultRelInfo->ri_TrigDesc && - resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE] > 0) -*************** ExecUpdate(TupleTableSlot *slot, -*** 2048,2053 **** ---- 2155,2163 ---- - } - } - -+ /* SELinux checks db_tuple:{relabelfrom relabelto}, if needed */ -+ sepgsqlHeapTupleUpdate(resultRelationDesc, tupleid, tuple); -+ - /* - * Check the constraints of the tuple - * -*************** OpenIntoRel(QueryDesc *queryDesc) -*** 2843,2848 **** ---- 2953,2959 ---- - Oid namespaceId; - Oid tablespaceId; - Datum reloptions; -+ Oid *secLabels; - AclResult aclresult; - Oid intoRelationId; - TupleDesc tupdesc; -*************** OpenIntoRel(QueryDesc *queryDesc) -*** 2871,2876 **** ---- 2982,2991 ---- - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(namespaceId)); - -+ /* SELinux checks db_table:{create} and db_column:{create} */ -+ secLabels = sepgsqlCreateTableColumns(NULL, intoName, namespaceId, -+ queryDesc->tupDesc, RELKIND_RELATION); -+ - /* - * Select tablespace to use. If not specified, use default tablespace - * (which may in turn default to database's default). -*************** OpenIntoRel(QueryDesc *queryDesc) -*** 2929,2935 **** - 0, - into->onCommit, - reloptions, -! allowSystemTableMods); - - FreeTupleDesc(tupdesc); - ---- 3044,3051 ---- - 0, - into->onCommit, - reloptions, -! allowSystemTableMods, -! secLabels); - - FreeTupleDesc(tupdesc); - -*************** OpenIntoRel(QueryDesc *queryDesc) -*** 2956,2961 **** ---- 3072,3082 ---- - AlterTableCreateToastTable(intoRelationId, InvalidOid, reloptions, false); - - /* -+ * SELinux: checks db_table/column:{insert} permission -+ */ -+ sepgsqlCheckSelectInto(intoRelationId); -+ -+ /* - * And open the constructed table for writing. - */ - intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock); -*************** intorel_receive(TupleTableSlot *slot, De -*** 3054,3059 **** ---- 3175,3184 ---- - if (myState->rel->rd_rel->relhasoids) - HeapTupleSetOid(tuple, InvalidOid); - -+ storeWritableSystemAttribute(myState->rel, slot, tuple); -+ /* SELinux checks db_tuple:{insert} */ -+ sepgsqlHeapTupleInsert(myState->rel, tuple, false); -+ - heap_insert(myState->rel, - tuple, - myState->estate->es_output_cid, -diff -Nrpc base/src/backend/executor/execQual.c sepgsql/src/backend/executor/execQual.c -*** base/src/backend/executor/execQual.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/executor/execQual.c Tue Sep 8 17:13:41 2009 -*************** -*** 47,52 **** ---- 47,53 ---- - #include "nodes/nodeFuncs.h" - #include "optimizer/planner.h" - #include "pgstat.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/lsyscache.h" -*************** init_fcache(Oid foid, FuncExprState *fca -*** 1034,1039 **** ---- 1035,1041 ---- - aclresult = pg_proc_aclcheck(foid, GetUserId(), ACL_EXECUTE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, get_func_name(foid)); -+ sepgsqlCheckProcedureExecute(foid); - - /* - * Safety check on nargs. Under normal circumstances this should never -*************** ExecEvalArrayCoerceExpr(ArrayCoerceExprS -*** 4032,4037 **** ---- 4034,4040 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(acoerce->elemfuncid)); -+ sepgsqlCheckProcedureExecute(acoerce->elemfuncid); - - /* Set up the primary fmgr lookup information */ - fmgr_info_cxt(acoerce->elemfuncid, &(astate->elemfunc), -diff -Nrpc base/src/backend/executor/execScan.c sepgsql/src/backend/executor/execScan.c -*** base/src/backend/executor/execScan.c Thu Apr 9 00:13:21 2009 ---- sepgsql/src/backend/executor/execScan.c Wed Sep 9 13:14:37 2009 -*************** -*** 20,25 **** ---- 20,26 ---- - - #include "executor/executor.h" - #include "miscadmin.h" -+ #include "security/rowlevel.h" - #include "utils/memutils.h" - - -*************** ExecScan(ScanState *node, -*** 53,58 **** ---- 54,60 ---- - ProjectionInfo *projInfo; - ExprDoneCond isDone; - TupleTableSlot *resultSlot; -+ Scan *scan = (Scan *)node->ps.plan; - - /* - * Fetch data from node -*************** ExecScan(ScanState *node, -*** 64,70 **** - * If we have neither a qual to check nor a projection to do, just skip - * all the overhead and return the raw scan tuple. - */ -! if (!qual && !projInfo) - return (*accessMtd) (node); - - /* ---- 66,72 ---- - * If we have neither a qual to check nor a projection to do, just skip - * all the overhead and return the raw scan tuple. - */ -! if (!qual && !projInfo && !scan->rowlvPerms) - return (*accessMtd) (node); - - /* -*************** ExecScan(ScanState *node, -*** 128,136 **** - * when the qual is nil ... saves only a few cycles, but they add up - * ... - */ -! if (!qual || ExecQual(qual, econtext, false)) - { - /* - * Found a satisfactory scan tuple. - */ - if (projInfo) ---- 130,147 ---- - * when the qual is nil ... saves only a few cycles, but they add up - * ... - */ -! if (rowlvExecScanFilter(scan, node->ss_currentRelation, slot) -! && (!qual || ExecQual(qual, econtext, false))) - { - /* -+ * NOTE: On FK checks, the Row-level feature needs to raise -+ * an error after evaluation of all the given quals to avoid -+ * incorrect error reporting. We assume FK implementation -+ * does not use malicious functions as the quals. -+ */ -+ rowlvExecScanAbort(scan, node->ss_currentRelation, slot); -+ -+ /* - * Found a satisfactory scan tuple. - */ - if (projInfo) -*************** tlist_matches_tupdesc(PlanState *ps, Lis -*** 197,202 **** ---- 208,214 ---- - int numattrs = tupdesc->natts; - int attrno; - bool hasoid; -+ bool hassecid; - ListCell *tlist_item = list_head(tlist); - - /* Check the tlist attributes */ -*************** tlist_matches_tupdesc(PlanState *ps, Lis -*** 240,251 **** - return false; /* tlist too long */ - - /* -! * If the plan context requires a particular hasoid setting, then that has -! * to match, too. - */ - if (ExecContextForcesOids(ps, &hasoid) && - hasoid != tupdesc->tdhasoid) - return false; - - return true; - } ---- 252,267 ---- - return false; /* tlist too long */ - - /* -! * If the plan context requires a particular hasoid or hassecid setting, -! * then that has to match, too. - */ - if (ExecContextForcesOids(ps, &hasoid) && - hasoid != tupdesc->tdhasoid) - return false; - -+ if (ExecContextForcesSecids(ps, &hassecid) && -+ hassecid != tupdesc->tdhassecid) -+ return false; -+ - return true; - } -diff -Nrpc base/src/backend/executor/execTuples.c sepgsql/src/backend/executor/execTuples.c -*** base/src/backend/executor/execTuples.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/executor/execTuples.c Wed Sep 9 13:14:37 2009 -*************** -*** 100,106 **** - - - static TupleDesc ExecTypeFromTLInternal(List *targetList, -! bool hasoid, bool skipjunk); - - - /* ---------------------------------------------------------------- ---- 100,106 ---- - - - static TupleDesc ExecTypeFromTLInternal(List *targetList, -! bool hasoid, bool hasseclabel, bool skipjunk); - - - /* ---------------------------------------------------------------- -*************** ExecInitNullTupleSlot(EState *estate, Tu -*** 968,976 **** - * ---------------------------------------------------------------- - */ - TupleDesc -! ExecTypeFromTL(List *targetList, bool hasoid) - { -! return ExecTypeFromTLInternal(targetList, hasoid, false); - } - - /* ---------------------------------------------------------------- ---- 968,976 ---- - * ---------------------------------------------------------------- - */ - TupleDesc -! ExecTypeFromTL(List *targetList, bool hasoid, bool hassecid) - { -! return ExecTypeFromTLInternal(targetList, hasoid, hassecid, false); - } - - /* ---------------------------------------------------------------- -*************** ExecTypeFromTL(List *targetList, bool ha -*** 980,992 **** - * ---------------------------------------------------------------- - */ - TupleDesc -! ExecCleanTypeFromTL(List *targetList, bool hasoid) - { -! return ExecTypeFromTLInternal(targetList, hasoid, true); - } - - static TupleDesc -! ExecTypeFromTLInternal(List *targetList, bool hasoid, bool skipjunk) - { - TupleDesc typeInfo; - ListCell *l; ---- 980,993 ---- - * ---------------------------------------------------------------- - */ - TupleDesc -! ExecCleanTypeFromTL(List *targetList, bool hasoid, bool hassecid) - { -! return ExecTypeFromTLInternal(targetList, hasoid, hassecid, true); - } - - static TupleDesc -! ExecTypeFromTLInternal(List *targetList, bool hasoid, -! bool hassecid, bool skipjunk) - { - TupleDesc typeInfo; - ListCell *l; -*************** ExecTypeFromTLInternal(List *targetList, -*** 998,1003 **** ---- 999,1005 ---- - else - len = ExecTargetListLength(targetList); - typeInfo = CreateTemplateTupleDesc(len, hasoid); -+ typeInfo->tdhassecid = hassecid; - - foreach(l, targetList) - { -diff -Nrpc base/src/backend/executor/execUtils.c sepgsql/src/backend/executor/execUtils.c -*** base/src/backend/executor/execUtils.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/executor/execUtils.c Wed Sep 9 13:14:37 2009 -*************** void -*** 512,517 **** ---- 512,518 ---- - ExecAssignResultTypeFromTL(PlanState *planstate) - { - bool hasoid; -+ bool hassecid; - TupleDesc tupDesc; - - if (ExecContextForcesOids(planstate, &hasoid)) -*************** ExecAssignResultTypeFromTL(PlanState *pl -*** 524,535 **** - hasoid = false; - } - - /* - * ExecTypeFromTL needs the parse-time representation of the tlist, not a - * list of ExprStates. This is good because some plan nodes don't bother - * to set up planstate->targetlist ... - */ -! tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid); - ExecAssignResultType(planstate, tupDesc); - } - ---- 525,539 ---- - hasoid = false; - } - -+ if (!ExecContextForcesSecids(planstate, &hassecid)) -+ hassecid = false; -+ - /* - * ExecTypeFromTL needs the parse-time representation of the tlist, not a - * list of ExprStates. This is good because some plan nodes don't bother - * to set up planstate->targetlist ... - */ -! tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid, hassecid); - ExecAssignResultType(planstate, tupDesc); - } - -diff -Nrpc base/src/backend/executor/functions.c sepgsql/src/backend/executor/functions.c -*** base/src/backend/executor/functions.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/executor/functions.c Wed Jul 15 19:30:50 2009 -*************** check_sql_fn_retval(Oid func_id, Oid ret -*** 1135,1141 **** - - /* Set up junk filter if needed */ - if (junkFilter) -! *junkFilter = ExecInitJunkFilter(tlist, false, NULL); - } - else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID) - { ---- 1135,1141 ---- - - /* Set up junk filter if needed */ - if (junkFilter) -! *junkFilter = ExecInitJunkFilter(tlist, false, false, NULL); - } - else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID) - { -*************** check_sql_fn_retval(Oid func_id, Oid ret -*** 1167,1173 **** - COERCE_DONTCARE); - /* Set up junk filter if needed */ - if (junkFilter) -! *junkFilter = ExecInitJunkFilter(tlist, false, NULL); - return false; /* NOT returning whole tuple */ - } - } ---- 1167,1173 ---- - COERCE_DONTCARE); - /* Set up junk filter if needed */ - if (junkFilter) -! *junkFilter = ExecInitJunkFilter(tlist, false, false, NULL); - return false; /* NOT returning whole tuple */ - } - } -*************** check_sql_fn_retval(Oid func_id, Oid ret -*** 1180,1186 **** - * what the caller expects will happen at runtime. - */ - if (junkFilter) -! *junkFilter = ExecInitJunkFilter(tlist, false, NULL); - return true; - } - Assert(tupdesc); ---- 1180,1186 ---- - * what the caller expects will happen at runtime. - */ - if (junkFilter) -! *junkFilter = ExecInitJunkFilter(tlist, false, false, NULL); - return true; - } - Assert(tupdesc); -diff -Nrpc base/src/backend/executor/nodeAgg.c sepgsql/src/backend/executor/nodeAgg.c -*** base/src/backend/executor/nodeAgg.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/executor/nodeAgg.c Mon Sep 7 00:55:45 2009 -*************** -*** 81,86 **** ---- 81,87 ---- - #include "parser/parse_agg.h" - #include "parser/parse_coerce.h" - #include "parser/parse_oper.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/lsyscache.h" -*************** ExecInitAgg(Agg *node, EState *estate, i -*** 1431,1436 **** ---- 1432,1438 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(aggref->aggfnoid)); -+ sepgsqlCheckProcedureExecute(aggref->aggfnoid); - - peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn; - peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn; -*************** ExecInitAgg(Agg *node, EState *estate, i -*** 1454,1459 **** ---- 1456,1462 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(transfn_oid)); -+ sepgsqlCheckProcedureExecute(transfn_oid); - if (OidIsValid(finalfn_oid)) - { - aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner, -*************** ExecInitAgg(Agg *node, EState *estate, i -*** 1461,1466 **** ---- 1464,1470 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(finalfn_oid)); -+ sepgsqlCheckProcedureExecute(finalfn_oid); - } - } - -diff -Nrpc base/src/backend/executor/nodeMergejoin.c sepgsql/src/backend/executor/nodeMergejoin.c -*** base/src/backend/executor/nodeMergejoin.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/executor/nodeMergejoin.c Mon Sep 7 00:55:45 2009 -*************** -*** 98,103 **** ---- 98,104 ---- - #include "executor/execdefs.h" - #include "executor/nodeMergejoin.h" - #include "miscadmin.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/lsyscache.h" - #include "utils/memutils.h" -*************** MJExamineQuals(List *mergeclauses, -*** 215,220 **** ---- 216,222 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(cmpproc)); -+ sepgsqlCheckProcedureExecute(cmpproc); - - /* Set up the fmgr lookup information */ - fmgr_info(cmpproc, &(clause->cmpfinfo)); -diff -Nrpc base/src/backend/executor/nodeSubplan.c sepgsql/src/backend/executor/nodeSubplan.c -*** base/src/backend/executor/nodeSubplan.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/executor/nodeSubplan.c Wed Jul 15 19:30:50 2009 -*************** ExecInitSubPlan(SubPlan *subplan, PlanSt -*** 869,875 **** - * (hack alert!). The righthand expressions will be evaluated in our - * own innerecontext. - */ -! tupDesc = ExecTypeFromTL(leftptlist, false); - slot = ExecAllocTableSlot(tupTable); - ExecSetSlotDescriptor(slot, tupDesc); - sstate->projLeft = ExecBuildProjectionInfo(lefttlist, ---- 869,875 ---- - * (hack alert!). The righthand expressions will be evaluated in our - * own innerecontext. - */ -! tupDesc = ExecTypeFromTL(leftptlist, false, false); - slot = ExecAllocTableSlot(tupTable); - ExecSetSlotDescriptor(slot, tupDesc); - sstate->projLeft = ExecBuildProjectionInfo(lefttlist, -*************** ExecInitSubPlan(SubPlan *subplan, PlanSt -*** 877,883 **** - slot, - NULL); - -! tupDesc = ExecTypeFromTL(rightptlist, false); - slot = ExecAllocTableSlot(tupTable); - ExecSetSlotDescriptor(slot, tupDesc); - sstate->projRight = ExecBuildProjectionInfo(righttlist, ---- 877,883 ---- - slot, - NULL); - -! tupDesc = ExecTypeFromTL(rightptlist, false, false); - slot = ExecAllocTableSlot(tupTable); - ExecSetSlotDescriptor(slot, tupDesc); - sstate->projRight = ExecBuildProjectionInfo(righttlist, -diff -Nrpc base/src/backend/executor/nodeWindowAgg.c sepgsql/src/backend/executor/nodeWindowAgg.c -*** base/src/backend/executor/nodeWindowAgg.c Tue Jun 23 11:09:47 2009 ---- sepgsql/src/backend/executor/nodeWindowAgg.c Mon Sep 7 00:55:45 2009 -*************** -*** 43,48 **** ---- 43,49 ---- - #include "optimizer/clauses.h" - #include "parser/parse_agg.h" - #include "parser/parse_coerce.h" -+ #include "security/sepgsql.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/datum.h" -*************** ExecInitWindowAgg(WindowAgg *node, EStat -*** 1224,1229 **** ---- 1225,1231 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(wfunc->winfnoid)); -+ sepgsqlCheckProcedureExecute(wfunc->winfnoid); - - /* Fill in the perfuncstate data */ - perfuncstate->wfuncstate = wfuncstate; -*************** initialize_peragg(WindowAggState *winsta -*** 1418,1423 **** ---- 1420,1426 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(transfn_oid)); -+ sepgsqlCheckProcedureExecute(transfn_oid); - if (OidIsValid(finalfn_oid)) - { - aclresult = pg_proc_aclcheck(finalfn_oid, aggOwner, -*************** initialize_peragg(WindowAggState *winsta -*** 1425,1430 **** ---- 1428,1434 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(finalfn_oid)); -+ sepgsqlCheckProcedureExecute(finalfn_oid); - } - } - -diff -Nrpc base/src/backend/executor/spi.c sepgsql/src/backend/executor/spi.c -*** base/src/backend/executor/spi.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/executor/spi.c Tue Sep 8 23:55:48 2009 -*************** SPI_modifytuple(Relation rel, HeapTuple -*** 705,710 **** ---- 705,712 ---- - mtuple->t_tableOid = tuple->t_tableOid; - if (rel->rd_att->tdhasoid) - HeapTupleSetOid(mtuple, HeapTupleGetOid(tuple)); -+ if (HeapTupleHasSecid(mtuple)) -+ HeapTupleSetSecid(mtuple, HeapTupleGetSecid(tuple)); - } - else - { -diff -Nrpc base/src/backend/libpq/be-fsstubs.c sepgsql/src/backend/libpq/be-fsstubs.c -*** base/src/backend/libpq/be-fsstubs.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/libpq/be-fsstubs.c Wed Jul 15 19:48:58 2009 -*************** -*** 42,50 **** ---- 42,53 ---- - #include - #include - -+ #include "catalog/pg_largeobject.h" -+ #include "catalog/pg_security.h" - #include "libpq/be-fsstubs.h" - #include "libpq/libpq-fs.h" - #include "miscadmin.h" -+ #include "security/sepgsql.h" - #include "storage/fd.h" - #include "storage/large_object.h" - #include "utils/builtins.h" -*************** lo_read(int fd, char *buf, int len) -*** 156,161 **** ---- 159,167 ---- - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("invalid large-object descriptor: %d", fd))); - -+ /* SELinux checks db_blob:{read} */ -+ sepgsqlCheckBlobRead(cookies[fd]); -+ - status = inv_read(cookies[fd], buf, len); - - return status; -*************** lo_write(int fd, const char *buf, int le -*** 177,182 **** ---- 183,191 ---- - errmsg("large object descriptor %d was not opened for writing", - fd))); - -+ /* SELinux checks db_blob:{write} */ -+ sepgsqlCheckBlobWrite(cookies[fd]); -+ - status = inv_write(cookies[fd], buf, len); - - return status; -*************** lo_import_internal(text *filename, Oid l -*** 381,386 **** ---- 390,398 ---- - */ - lobj = inv_open(oid, INV_WRITE, fscxt); - -+ /* SELinux checks db_blob:{write import} and file:{read} */ -+ sepgsqlCheckBlobImport(lobj, FileRawDescriptor(fd), fnamebuf); -+ - while ((nbytes = FileRead(fd, buf, BUFSIZE)) > 0) - { - tmp = inv_write(lobj, buf, nbytes); -*************** lo_export(PG_FUNCTION_ARGS) -*** 448,453 **** ---- 460,468 ---- - errmsg("could not create server file \"%s\": %m", - fnamebuf))); - -+ /* SELinux checks db_blob:{read export} and file:{write} */ -+ sepgsqlCheckBlobExport(lobj, FileRawDescriptor(fd), fnamebuf); -+ - /* - * read in from the inversion file and write to the filesystem - */ -*************** lo_truncate(PG_FUNCTION_ARGS) -*** 482,493 **** ---- 497,560 ---- - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("invalid large-object descriptor: %d", fd))); - -+ /* SELinux checks db_blob:{write} */ -+ sepgsqlCheckBlobWrite(cookies[fd]); -+ - inv_truncate(cookies[fd], len); - - PG_RETURN_INT32(0); - } - - /* -+ * lo_get_seclabel -+ * get a security label of large object -+ */ -+ Datum -+ lo_get_security(PG_FUNCTION_ARGS) -+ { -+ Oid loid = PG_GETARG_OID(0); -+ Oid secid; -+ char *seclabel; -+ -+ secid = inv_get_security(loid); -+ seclabel = securityTransSecLabelOut(LargeObjectRelationId, secid); -+ -+ return CStringGetTextDatum(seclabel); -+ } -+ -+ /* -+ * lo_set_seclabel -+ * set a security label of large object -+ */ -+ Datum -+ lo_set_security(PG_FUNCTION_ARGS) -+ { -+ Oid loid = PG_GETARG_OID(0); -+ char *seclabel = TextDatumGetCString(PG_GETARG_DATUM(1)); -+ Oid secid; -+ -+ secid = securityTransSecLabelIn(LargeObjectRelationId, seclabel); -+ -+ inv_set_security(loid, secid); -+ -+ /* -+ * Also on memory caches to be updated -+ */ -+ if (fscxt != NULL) -+ { -+ int i; -+ -+ for (i = 0; i < cookies_size; i++) -+ { -+ if (cookies[i] != NULL && cookies[i]->id == loid) -+ cookies[i]->secid = secid; -+ } -+ } -+ -+ PG_RETURN_BOOL(true); -+ } -+ -+ /* - * AtEOXact_LargeObject - - * prepares large objects for transaction commit - */ -diff -Nrpc base/src/backend/nodes/copyfuncs.c sepgsql/src/backend/nodes/copyfuncs.c -*** base/src/backend/nodes/copyfuncs.c Fri Jun 19 13:40:37 2009 ---- sepgsql/src/backend/nodes/copyfuncs.c Wed Jul 15 19:39:56 2009 -*************** CopyScanFields(Scan *from, Scan *newnode -*** 259,264 **** ---- 259,265 ---- - CopyPlanFields((Plan *) from, (Plan *) newnode); - - COPY_SCALAR_FIELD(scanrelid); -+ COPY_SCALAR_FIELD(rowlvPerms); - } - - /* -*************** _copyColumnDef(ColumnDef *from) -*** 2075,2080 **** ---- 2076,2082 ---- - COPY_NODE_FIELD(raw_default); - COPY_STRING_FIELD(cooked_default); - COPY_NODE_FIELD(constraints); -+ COPY_NODE_FIELD(secLabel); - - return newnode; - } -*************** _copyCreateStmt(CreateStmt *from) -*** 2414,2419 **** ---- 2416,2422 ---- - COPY_NODE_FIELD(options); - COPY_SCALAR_FIELD(oncommit); - COPY_STRING_FIELD(tablespacename); -+ COPY_NODE_FIELD(secLabel); - - return newnode; - } -*************** _copyAlterOwnerStmt(AlterOwnerStmt *from -*** 2638,2643 **** ---- 2641,2661 ---- - return newnode; - } - -+ static AlterSecLabelStmt * -+ _copyAlterSecLabelStmt(AlterSecLabelStmt *from) -+ { -+ AlterSecLabelStmt *newnode = makeNode(AlterSecLabelStmt); -+ -+ COPY_SCALAR_FIELD(objectType); -+ COPY_NODE_FIELD(relation); -+ COPY_NODE_FIELD(object); -+ COPY_NODE_FIELD(objarg); -+ COPY_STRING_FIELD(subname); -+ COPY_NODE_FIELD(secLabel); -+ -+ return newnode; -+ } -+ - static RuleStmt * - _copyRuleStmt(RuleStmt *from) - { -*************** _copyCreateSeqStmt(CreateSeqStmt *from) -*** 2887,2892 **** ---- 2905,2911 ---- - - COPY_NODE_FIELD(sequence); - COPY_NODE_FIELD(options); -+ COPY_NODE_FIELD(secLabel); - - return newnode; - } -*************** copyObject(void *from) -*** 3819,3824 **** ---- 3838,3846 ---- - case T_AlterOwnerStmt: - retval = _copyAlterOwnerStmt(from); - break; -+ case T_AlterSecLabelStmt: -+ retval = _copyAlterSecLabelStmt(from); -+ break; - case T_RuleStmt: - retval = _copyRuleStmt(from); - break; -diff -Nrpc base/src/backend/nodes/equalfuncs.c sepgsql/src/backend/nodes/equalfuncs.c -*** base/src/backend/nodes/equalfuncs.c Fri Jun 19 13:40:37 2009 ---- sepgsql/src/backend/nodes/equalfuncs.c Wed Jul 15 19:37:35 2009 -*************** _equalCreateStmt(CreateStmt *a, CreateSt -*** 1078,1083 **** ---- 1078,1084 ---- - COMPARE_NODE_FIELD(options); - COMPARE_SCALAR_FIELD(oncommit); - COMPARE_STRING_FIELD(tablespacename); -+ COMPARE_NODE_FIELD(secLabel); - - return true; - } -*************** _equalAlterOwnerStmt(AlterOwnerStmt *a, -*** 1271,1276 **** ---- 1272,1290 ---- - } - - static bool -+ _equalAlterSecLabelStmt(AlterSecLabelStmt *a, AlterSecLabelStmt *b) -+ { -+ COMPARE_SCALAR_FIELD(objectType); -+ COMPARE_NODE_FIELD(relation); -+ COMPARE_NODE_FIELD(object); -+ COMPARE_NODE_FIELD(objarg); -+ COMPARE_STRING_FIELD(subname); -+ COMPARE_NODE_FIELD(secLabel); -+ -+ return true; -+ } -+ -+ static bool - _equalRuleStmt(RuleStmt *a, RuleStmt *b) - { - COMPARE_NODE_FIELD(relation); -*************** _equalCreateSeqStmt(CreateSeqStmt *a, Cr -*** 1477,1482 **** ---- 1491,1497 ---- - { - COMPARE_NODE_FIELD(sequence); - COMPARE_NODE_FIELD(options); -+ COMPARE_NODE_FIELD(secLabel); - - return true; - } -*************** _equalColumnDef(ColumnDef *a, ColumnDef -*** 2054,2059 **** ---- 2069,2075 ---- - COMPARE_NODE_FIELD(raw_default); - COMPARE_STRING_FIELD(cooked_default); - COMPARE_NODE_FIELD(constraints); -+ COMPARE_NODE_FIELD(secLabel); - - return true; - } -*************** equal(void *a, void *b) -*** 2596,2601 **** ---- 2612,2620 ---- - case T_AlterOwnerStmt: - retval = _equalAlterOwnerStmt(a, b); - break; -+ case T_AlterSecLabelStmt: -+ retval = _equalAlterSecLabelStmt(a, b); -+ break; - case T_RuleStmt: - retval = _equalRuleStmt(a, b); - break; -diff -Nrpc base/src/backend/nodes/outfuncs.c sepgsql/src/backend/nodes/outfuncs.c -*** base/src/backend/nodes/outfuncs.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/nodes/outfuncs.c Wed Jul 15 19:39:56 2009 -*************** _outScanInfo(StringInfo str, Scan *node) -*** 285,290 **** ---- 285,291 ---- - _outPlanInfo(str, (Plan *) node); - - WRITE_UINT_FIELD(scanrelid); -+ WRITE_UINT_FIELD(rowlvPerms); - } - - /* -*************** _outRelOptInfo(StringInfo str, RelOptInf -*** 1534,1539 **** ---- 1535,1541 ---- - WRITE_BOOL_FIELD(has_eclass_joins); - WRITE_BITMAPSET_FIELD(index_outer_relids); - WRITE_NODE_FIELD(index_inner_paths); -+ WRITE_UINT_FIELD(rowlvPerms); - } - - static void -*************** _outCreateStmt(StringInfo str, CreateStm -*** 1717,1722 **** ---- 1719,1725 ---- - WRITE_NODE_FIELD(options); - WRITE_ENUM_FIELD(oncommit, OnCommitAction); - WRITE_STRING_FIELD(tablespacename); -+ WRITE_NODE_FIELD(secLabel); - } - - static void -*************** _outColumnDef(StringInfo str, ColumnDef -*** 1839,1844 **** ---- 1842,1848 ---- - WRITE_NODE_FIELD(raw_default); - WRITE_STRING_FIELD(cooked_default); - WRITE_NODE_FIELD(constraints); -+ WRITE_NODE_FIELD(secLabel); - } - - static void -diff -Nrpc base/src/backend/optimizer/plan/createplan.c sepgsql/src/backend/optimizer/plan/createplan.c -*** base/src/backend/optimizer/plan/createplan.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/optimizer/plan/createplan.c Sun Sep 6 19:53:10 2009 -*************** create_scan_plan(PlannerInfo *root, Path -*** 305,310 **** ---- 305,313 ---- - break; - } - -+ /* Copy of row-level permissions to Scan node */ -+ ((Scan *)plan)->rowlvPerms = rel->rowlvPerms; -+ - /* - * If there are any pseudoconstant clauses attached to this node, insert a - * gating Result node that evaluates the pseudoconstants as one-time -diff -Nrpc base/src/backend/optimizer/util/clauses.c sepgsql/src/backend/optimizer/util/clauses.c -*** base/src/backend/optimizer/util/clauses.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/optimizer/util/clauses.c Mon Sep 7 00:55:45 2009 -*************** -*** 38,43 **** ---- 38,44 ---- - #include "parser/parse_coerce.h" - #include "parser/parse_func.h" - #include "rewrite/rewriteManip.h" -+ #include "security/sepgsql.h" - #include "tcop/tcopprot.h" - #include "utils/acl.h" - #include "utils/builtins.h" -*************** inline_function(Oid funcid, Oid result_t -*** 3502,3507 **** ---- 3503,3509 ---- - funcform->prosecdef || - funcform->proretset || - !heap_attisnull(func_tuple, Anum_pg_proc_proconfig) || -+ !sepgsqlHintProcedureInlined(func_tuple) || - funcform->pronargs != list_length(args)) - return NULL; - -*************** inline_set_returning_function(PlannerInf -*** 3970,3975 **** ---- 3972,3978 ---- - funcform->prosecdef || - !funcform->proretset || - !heap_attisnull(func_tuple, Anum_pg_proc_proconfig) || -+ !sepgsqlHintProcedureInlined(func_tuple) || - funcform->pronargs != list_length(fexpr->args)) - { - ReleaseSysCache(func_tuple); -diff -Nrpc base/src/backend/optimizer/util/relnode.c sepgsql/src/backend/optimizer/util/relnode.c -*** base/src/backend/optimizer/util/relnode.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/optimizer/util/relnode.c Wed Jul 15 19:39:56 2009 -*************** -*** 21,26 **** ---- 21,27 ---- - #include "optimizer/plancat.h" - #include "optimizer/restrictinfo.h" - #include "parser/parsetree.h" -+ #include "security/rowlevel.h" - #include "utils/hsearch.h" - - -*************** build_simple_rel(PlannerInfo *root, int -*** 91,96 **** ---- 92,98 ---- - rel->has_eclass_joins = false; - rel->index_outer_relids = NULL; - rel->index_inner_paths = NIL; -+ rel->rowlvPerms = rowlvSetupPermissions(rte); - - /* Check type of rtable entry */ - switch (rte->rtekind) -diff -Nrpc base/src/backend/parser/analyze.c sepgsql/src/backend/parser/analyze.c -*** base/src/backend/parser/analyze.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/parser/analyze.c Sun Sep 6 19:53:10 2009 -*************** -*** 25,30 **** ---- 25,31 ---- - #include "postgres.h" - - #include "access/sysattr.h" -+ #include "catalog/heap.h" - #include "catalog/pg_type.h" - #include "nodes/makefuncs.h" - #include "nodes/nodeFuncs.h" -*************** transformInsertStmt(ParseState *pstate, -*** 653,659 **** - tle = makeTargetEntry(expr, - attr_num, - col->name, -! false); - qry->targetList = lappend(qry->targetList, tle); - - rte->modifiedCols = bms_add_member(rte->modifiedCols, ---- 654,660 ---- - tle = makeTargetEntry(expr, - attr_num, - col->name, -! attr_num < 0 ? true : false); - qry->targetList = lappend(qry->targetList, tle); - - rte->modifiedCols = bms_add_member(rte->modifiedCols, -*************** transformInsertRow(ParseState *pstate, L -*** 768,773 **** ---- 769,816 ---- - return result; - } - -+ static void -+ transformSelectIntoSystemColumn(ParseState *pstate, Query *qry) -+ { -+ ListCell *l; -+ uint32 system_attrs = 0; -+ bool relhasoids -+ = interpretOidsOption(qry->intoClause->options); -+ -+ foreach (l, qry->targetList) -+ { -+ Form_pg_attribute attr; -+ TargetEntry *tle = lfirst(l); -+ -+ if (tle->resjunk) -+ continue; -+ -+ attr = SystemAttributeByName(tle->resname, relhasoids); -+ if (attr && SystemAttributeIsWritable(attr->attnum)) -+ { -+ uint32 mask = (1<<(-attr->attnum)); -+ -+ /* duplication checks */ -+ if (system_attrs & mask) -+ continue; -+ system_attrs |= mask; -+ -+ if (exprType((Node *) tle->expr) != attr->atttypid) -+ { -+ tle->expr = -+ (Expr *) coerce_to_target_type(pstate, -+ (Node *) tle->expr, -+ exprType((Node *) tle->expr), -+ attr->atttypid, -+ attr->atttypmod, -+ COERCION_IMPLICIT, -+ COERCE_IMPLICIT_CAST, -+ -1); -+ } -+ tle->resjunk = true; -+ } -+ } -+ } - - /* - * transformSelectStmt - -*************** transformSelectStmt(ParseState *pstate, -*** 872,877 **** ---- 915,921 ---- - if (stmt->intoClause) - { - qry->intoClause = stmt->intoClause; -+ transformSelectIntoSystemColumn(pstate, qry); - if (stmt->intoClause->colNames) - applyColumnNames(qry->targetList, stmt->intoClause->colNames); - } -diff -Nrpc base/src/backend/parser/gram.y sepgsql/src/backend/parser/gram.y -*** base/src/backend/parser/gram.y Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/parser/gram.y Tue Sep 8 17:13:41 2009 -*************** -*** 58,63 **** ---- 58,64 ---- - #include "nodes/makefuncs.h" - #include "nodes/nodeFuncs.h" - #include "parser/gramparse.h" -+ #include "security/sepgsql.h" - #include "storage/lmgr.h" - #include "utils/date.h" - #include "utils/datetime.h" -*************** static TypeName *TableFuncTypeName(List -*** 184,190 **** - %type stmt schema_stmt - AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt - AlterForeignServerStmt AlterGroupStmt -! AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt - AlterUserStmt AlterUserMappingStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt - AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt - ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt ---- 185,191 ---- - %type stmt schema_stmt - AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt - AlterForeignServerStmt AlterGroupStmt -! AlterObjectSchemaStmt AlterOwnerStmt AlterSecLabelStmt AlterSeqStmt AlterTableStmt - AlterUserStmt AlterUserMappingStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt - AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt - ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt -*************** static TypeName *TableFuncTypeName(List -*** 401,406 **** ---- 402,409 ---- - %type OptTableSpace OptConsTableSpace OptTableSpaceOwner - %type opt_check_option - -+ %type OptSecCxt SecCxtItem -+ - %type xml_attribute_el - %type xml_attribute_list xml_attributes - %type xml_root_version opt_xml_root_standalone -*************** stmt : -*** 607,612 **** ---- 610,616 ---- - | AlterGroupStmt - | AlterObjectSchemaStmt - | AlterOwnerStmt -+ | AlterSecLabelStmt - | AlterSeqStmt - | AlterTableStmt - | AlterRoleSetStmt -*************** DropGroupStmt: -*** 1041,1047 **** - *****************************************************************************/ - - CreateSchemaStmt: -! CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSchemaEltList - { - CreateSchemaStmt *n = makeNode(CreateSchemaStmt); - /* One can omit the schema name or the authorization id. */ ---- 1045,1051 ---- - *****************************************************************************/ - - CreateSchemaStmt: -! CREATE SCHEMA OptSchemaName AUTHORIZATION RoleId OptSecCxt OptSchemaEltList - { - CreateSchemaStmt *n = makeNode(CreateSchemaStmt); - /* One can omit the schema name or the authorization id. */ -*************** CreateSchemaStmt: -*** 1050,1065 **** - else - n->schemaname = $5; - n->authid = $5; -! n->schemaElts = $6; - $$ = (Node *)n; - } -! | CREATE SCHEMA ColId OptSchemaEltList - { - CreateSchemaStmt *n = makeNode(CreateSchemaStmt); - /* ...but not both */ - n->schemaname = $3; - n->authid = NULL; -! n->schemaElts = $4; - $$ = (Node *)n; - } - ; ---- 1054,1071 ---- - else - n->schemaname = $5; - n->authid = $5; -! n->secLabel = (Node *)$6; -! n->schemaElts = $7; - $$ = (Node *)n; - } -! | CREATE SCHEMA ColId OptSecCxt OptSchemaEltList - { - CreateSchemaStmt *n = makeNode(CreateSchemaStmt); - /* ...but not both */ - n->schemaname = $3; - n->authid = NULL; -! n->secLabel = (Node *)$4; -! n->schemaElts = $5; - $$ = (Node *)n; - } - ; -*************** opt_using: -*** 2036,2042 **** - *****************************************************************************/ - - CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' -! OptInherit OptWith OnCommitOption OptTableSpace - { - CreateStmt *n = makeNode(CreateStmt); - $4->istemp = $2; ---- 2042,2048 ---- - *****************************************************************************/ - - CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' -! OptInherit OptWith OnCommitOption OptTableSpace OptSecCxt - { - CreateStmt *n = makeNode(CreateStmt); - $4->istemp = $2; -*************** CreateStmt: CREATE OptTemp TABLE qualifi -*** 2047,2056 **** - n->options = $9; - n->oncommit = $10; - n->tablespacename = $11; - $$ = (Node *)n; - } - | CREATE OptTemp TABLE qualified_name OF qualified_name -! '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace - { - /* SQL99 CREATE TABLE OF (cols) seems to be satisfied - * by our inheritance capabilities. Let's try it... ---- 2053,2063 ---- - n->options = $9; - n->oncommit = $10; - n->tablespacename = $11; -+ n->secLabel = (Node *) $12; - $$ = (Node *)n; - } - | CREATE OptTemp TABLE qualified_name OF qualified_name -! '(' OptTableElementList ')' OptWith OnCommitOption OptTableSpace OptSecCxt - { - /* SQL99 CREATE TABLE OF (cols) seems to be satisfied - * by our inheritance capabilities. Let's try it... -*************** CreateStmt: CREATE OptTemp TABLE qualifi -*** 2064,2069 **** ---- 2071,2077 ---- - n->options = $10; - n->oncommit = $11; - n->tablespacename = $12; -+ n->secLabel = (Node *) $13; - $$ = (Node *)n; - } - ; -*************** TableElement: -*** 2106,2118 **** - | TableConstraint { $$ = $1; } - ; - -! columnDef: ColId Typename ColQualList - { - ColumnDef *n = makeNode(ColumnDef); - n->colname = $1; - n->typename = $2; - n->constraints = $3; - n->is_local = true; - $$ = (Node *)n; - } - ; ---- 2114,2127 ---- - | TableConstraint { $$ = $1; } - ; - -! columnDef: ColId Typename ColQualList OptSecCxt - { - ColumnDef *n = makeNode(ColumnDef); - n->colname = $1; - n->typename = $2; - n->constraints = $3; - n->is_local = true; -+ n->secLabel = (Node *) $4; - $$ = (Node *)n; - } - ; -*************** opt_with_data: -*** 2584,2595 **** - *****************************************************************************/ - - CreateSeqStmt: -! CREATE OptTemp SEQUENCE qualified_name OptSeqOptList - { - CreateSeqStmt *n = makeNode(CreateSeqStmt); - $4->istemp = $2; - n->sequence = $4; - n->options = $5; - $$ = (Node *)n; - } - ; ---- 2593,2605 ---- - *****************************************************************************/ - - CreateSeqStmt: -! CREATE OptTemp SEQUENCE qualified_name OptSeqOptList OptSecCxt - { - CreateSeqStmt *n = makeNode(CreateSeqStmt); - $4->istemp = $2; - n->sequence = $4; - n->options = $5; -+ n->secLabel = (Node *)$6; - $$ = (Node *)n; - } - ; -*************** createfunc_opt_item: -*** 4885,4890 **** ---- 4895,4904 ---- - { - $$ = makeDefElem("window", (Node *)makeInteger(TRUE)); - } -+ | SecCxtItem -+ { -+ $$ = $1; -+ } - | common_func_opt_item - { - $$ = $1; -*************** AlterOwnerStmt: ALTER AGGREGATE func_nam -*** 5591,5596 **** ---- 5605,5680 ---- - } - ; - -+ /***************************************************************************** -+ * -+ * ALTER THING name SECURITY_CONTEXT [=] -+ * -+ *****************************************************************************/ -+ -+ AlterSecLabelStmt: ALTER DATABASE database_name SecCxtItem -+ { -+ AlterSecLabelStmt *n = makeNode(AlterSecLabelStmt); -+ n->objectType = OBJECT_DATABASE; -+ n->object = list_make1(makeString($3)); -+ n->secLabel = (Node *)$4; -+ $$ = (Node *) n; -+ } -+ | ALTER SCHEMA name SecCxtItem -+ { -+ AlterSecLabelStmt *n = makeNode(AlterSecLabelStmt); -+ n->objectType = OBJECT_SCHEMA; -+ n->object = list_make1(makeString($3)); -+ n->secLabel = (Node *)$4; -+ $$ = (Node *) n; -+ } -+ | ALTER TABLE relation_expr SecCxtItem -+ { -+ AlterSecLabelStmt *n = makeNode(AlterSecLabelStmt); -+ n->objectType = OBJECT_TABLE; -+ n->relation = $3; -+ n->secLabel = (Node *)$4; -+ $$ = (Node *) n; -+ } -+ | ALTER TABLE relation_expr ALTER opt_column ColId SecCxtItem -+ { -+ AlterSecLabelStmt *n = makeNode(AlterSecLabelStmt); -+ n->objectType = OBJECT_COLUMN; -+ n->relation = $3; -+ n->subname = $6; -+ n->secLabel = (Node *)$7; -+ $$ = (Node *) n; -+ } -+ | ALTER SEQUENCE relation_expr SecCxtItem -+ { -+ AlterSecLabelStmt *n = makeNode(AlterSecLabelStmt); -+ n->objectType = OBJECT_SEQUENCE; -+ n->relation = $3; -+ n->secLabel = (Node *)$4; -+ $$ = (Node *) n; -+ } -+ | ALTER FUNCTION function_with_argtypes SecCxtItem -+ { -+ AlterSecLabelStmt *n = makeNode(AlterSecLabelStmt); -+ n->objectType = OBJECT_FUNCTION; -+ n->object = $3->funcname; -+ n->objarg = $3->funcargs; -+ n->secLabel = (Node *)$4; -+ $$ = (Node *) n; -+ } -+ ; -+ -+ OptSecCxt: SecCxtItem { $$ = $1; } -+ | /* EMPTY */ { $$ = NULL; } -+ ; -+ -+ SecCxtItem: IDENT opt_equal Sconst -+ { -+ if (strcmp("security_context", $1) != 0) -+ yyerror("syntax error"); -+ $$ = makeDefElem($1, (Node *) makeString($3)); -+ } -+ ; -+ - - /***************************************************************************** - * -*************** createdb_opt_item: -*** 6033,6038 **** ---- 6117,6126 ---- - { - $$ = makeDefElem("owner", NULL); - } -+ | SecCxtItem -+ { -+ $$ = $1; -+ } - ; - - /* -diff -Nrpc base/src/backend/parser/parse_target.c sepgsql/src/backend/parser/parse_target.c -*** base/src/backend/parser/parse_target.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/parser/parse_target.c Wed Jul 15 19:38:52 2009 -*************** -*** 14,19 **** ---- 14,20 ---- - */ - #include "postgres.h" - -+ #include "catalog/heap.h" - #include "catalog/pg_type.h" - #include "commands/dbcommands.h" - #include "funcapi.h" -*************** transformAssignedExpr(ParseState *pstate -*** 361,376 **** - Oid attrtype; /* type of target column */ - int32 attrtypmod; - Relation rd = pstate->p_target_relation; - - Assert(rd != NULL); -! if (attrno <= 0) -! ereport(ERROR, -! (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -! errmsg("cannot assign to system column \"%s\"", -! colname), -! parser_errposition(pstate, location))); -! attrtype = attnumTypeId(rd, attrno); -! attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod; - - /* - * If the expression is a DEFAULT placeholder, insert the attribute's ---- 362,394 ---- - Oid attrtype; /* type of target column */ - int32 attrtypmod; - Relation rd = pstate->p_target_relation; -+ bool relhasoids = RelationGetForm(rd)->relhasoids; - - Assert(rd != NULL); -! if (attrno > 0) -! { -! attrtype = attnumTypeId(rd, attrno); -! attrtypmod = rd->rd_att->attrs[attrno - 1]->atttypmod; -! } -! else -! { -! Form_pg_attribute attForm -! = SystemAttributeDefinition(attrno, relhasoids); -! if (attForm && SystemAttributeIsWritable(attrno)) -! { -! attrtype = attForm->atttypid; -! attrtypmod = attForm->atttypmod; -! } -! else -! { -! ereport(ERROR, -! (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -! errmsg("cannot assign to system column \"%s\"", -! colname), -! parser_errposition(pstate, location))); -! return NULL; /* compiler kindness */ -! } -! } - - /* - * If the expression is a DEFAULT placeholder, insert the attribute's -*************** updateTargetListEntry(ParseState *pstate -*** 515,520 **** ---- 533,541 ---- - */ - tle->resno = (AttrNumber) attrno; - tle->resname = colname; -+ -+ if (SystemAttributeIsWritable(attrno)) -+ tle->resjunk = true; - } - - -*************** checkInsertTargets(ParseState *pstate, L -*** 789,794 **** ---- 810,816 ---- - Bitmapset *wholecols = NULL; - Bitmapset *partialcols = NULL; - ListCell *tl; -+ uint32 system_attrs = 0UL; - - foreach(tl, cols) - { -*************** checkInsertTargets(ParseState *pstate, L -*** 797,810 **** - int attrno; - - /* Lookup column name, ereport on failure */ -! attrno = attnameAttNum(pstate->p_target_relation, name, false); - if (attrno == InvalidAttrNumber) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column \"%s\" of relation \"%s\" does not exist", - name, - RelationGetRelationName(pstate->p_target_relation)), - parser_errposition(pstate, col->location))); - - /* - * Check for duplicates, but only of whole columns --- we allow ---- 819,855 ---- - int attrno; - - /* Lookup column name, ereport on failure */ -! attrno = attnameAttNum(pstate->p_target_relation, name, true); - if (attrno == InvalidAttrNumber) -+ { - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_COLUMN), - errmsg("column \"%s\" of relation \"%s\" does not exist", - name, - RelationGetRelationName(pstate->p_target_relation)), - parser_errposition(pstate, col->location))); -+ } -+ else if (attrno < 0) -+ { -+ if (SystemAttributeIsWritable(attrno)) -+ { -+ uint32 mask = (1<<(-attrno)); -+ -+ if ((system_attrs & mask) != 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_DUPLICATE_COLUMN), -+ errmsg("column \"%s\" specified more than once", name), -+ parser_errposition(pstate, col->location))); -+ system_attrs |= mask; -+ *attrnos = lappend_int(*attrnos, attrno); -+ continue; -+ } -+ ereport(ERROR, -+ (errcode(ERRCODE_INVALID_COLUMN_REFERENCE), -+ errmsg("column \"%s\" of relation \"%s\" is system column", -+ name, RelationGetRelationName(pstate->p_target_relation)), -+ parser_errposition(pstate, col->location))); -+ } - - /* - * Check for duplicates, but only of whole columns --- we allow -diff -Nrpc base/src/backend/postmaster/autovacuum.c sepgsql/src/backend/postmaster/autovacuum.c -*** base/src/backend/postmaster/autovacuum.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/postmaster/autovacuum.c Sun Sep 6 19:53:10 2009 -*************** do_autovacuum(void) -*** 2004,2010 **** - object.classId = RelationRelationId; - object.objectId = relid; - object.objectSubId = 0; -! performDeletion(&object, DROP_CASCADE); - } - else - { ---- 2004,2010 ---- - object.classId = RelationRelationId; - object.objectId = relid; - object.objectSubId = 0; -! performDeletionNoPerms(&object, DROP_CASCADE); - } - else - { -diff -Nrpc base/src/backend/postmaster/postmaster.c sepgsql/src/backend/postmaster/postmaster.c -*** base/src/backend/postmaster/postmaster.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/postmaster/postmaster.c Sun Sep 6 19:53:10 2009 -*************** -*** 108,113 **** ---- 108,114 ---- - #include "postmaster/pgarch.h" - #include "postmaster/postmaster.h" - #include "postmaster/syslogger.h" -+ #include "security/sepgsql.h" - #include "storage/fd.h" - #include "storage/ipc.h" - #include "storage/pg_shmem.h" -*************** static pid_t StartupPID = 0, -*** 209,215 **** - AutoVacPID = 0, - PgArchPID = 0, - PgStatPID = 0, -! SysLoggerPID = 0; - - /* Startup/shutdown state */ - #define NoShutdown 0 ---- 210,217 ---- - AutoVacPID = 0, - PgArchPID = 0, - PgStatPID = 0, -! SysLoggerPID = 0, -! sepgsqlWorkerPID = 0; - - /* Startup/shutdown state */ - #define NoShutdown 0 -*************** ServerLoop(void) -*** 1436,1441 **** ---- 1438,1447 ---- - if (PgStatPID == 0 && pmState == PM_RUN) - PgStatPID = pgstat_start(); - -+ /* If we have lost the sepgsql worker (if needed), try to start a new one */ -+ if (sepgsqlWorkerPID == 0 && pmState == PM_RUN) -+ sepgsqlWorkerPID = sepgsqlStartupWorkerProcess(); -+ - /* If we need to signal the autovacuum launcher, do so now */ - if (avlauncher_needs_signal) - { -*************** SIGHUP_handler(SIGNAL_ARGS) -*** 2053,2058 **** ---- 2059,2066 ---- - signal_child(SysLoggerPID, SIGHUP); - if (PgStatPID != 0) - signal_child(PgStatPID, SIGHUP); -+ if (sepgsqlWorkerPID != 0) -+ signal_child(sepgsqlWorkerPID, SIGHUP); - - /* Reload authentication config files too */ - if (!load_hba()) -*************** pmdie(SIGNAL_ARGS) -*** 2113,2118 **** ---- 2121,2129 ---- - /* and the walwriter too */ - if (WalWriterPID != 0) - signal_child(WalWriterPID, SIGTERM); -+ /* and the sepgsql worker too */ -+ if (sepgsqlWorkerPID != 0) -+ signal_child(sepgsqlWorkerPID, SIGTERM); - pmState = PM_WAIT_BACKUP; - } - -*************** pmdie(SIGNAL_ARGS) -*** 2160,2165 **** ---- 2171,2179 ---- - /* and the walwriter too */ - if (WalWriterPID != 0) - signal_child(WalWriterPID, SIGTERM); -+ /* and the sepgsqlWorker too */ -+ if (sepgsqlWorkerPID != 0) -+ signal_child(sepgsqlWorkerPID, SIGTERM); - pmState = PM_WAIT_BACKENDS; - } - -*************** pmdie(SIGNAL_ARGS) -*** 2193,2198 **** ---- 2207,2214 ---- - signal_child(PgArchPID, SIGQUIT); - if (PgStatPID != 0) - signal_child(PgStatPID, SIGQUIT); -+ if (sepgsqlWorkerPID != 0) -+ signal_child(sepgsqlWorkerPID, SIGQUIT); - ExitPostmaster(0); - break; - } -*************** reaper(SIGNAL_ARGS) -*** 2455,2460 **** ---- 2471,2486 ---- - continue; - } - -+ /* Was it the sepgsql worker process? */ -+ if (pid == sepgsqlWorkerPID) -+ { -+ sepgsqlWorkerPID = 0; -+ if (!EXIT_STATUS_0(exitstatus)) -+ LogChildExit(LOG, _("SE-PostgreSQL worker process"), -+ pid, exitstatus); -+ continue; -+ } -+ - /* - * Else do standard backend child cleanup. - */ -*************** HandleChildCrash(int pid, int exitstatus -*** 2646,2651 **** ---- 2672,2689 ---- - signal_child(AutoVacPID, (SendStop ? SIGSTOP : SIGQUIT)); - } - -+ /* Take care of the sepgsql worker too */ -+ if (pid == sepgsqlWorkerPID) -+ sepgsqlWorkerPID = 0; -+ else if (sepgsqlWorkerPID != 0 && !FatalError) -+ { -+ ereport(DEBUG2, -+ (errmsg_internal("sending %s to process %d", -+ (SendStop ? "SIGSTOP" : "SIGQUIT"), -+ (int) sepgsqlWorkerPID))); -+ signal_child(sepgsqlWorkerPID, (SendStop ? SIGSTOP : SIGQUIT)); -+ } -+ - /* - * Force a power-cycle of the pgarch process too. (This isn't absolutely - * necessary, but it seems like a good idea for robustness, and it -*************** PostmasterStateMachine(void) -*** 2778,2784 **** - StartupPID == 0 && - (BgWriterPID == 0 || !FatalError) && - WalWriterPID == 0 && -! AutoVacPID == 0) - { - if (FatalError) - { ---- 2816,2823 ---- - StartupPID == 0 && - (BgWriterPID == 0 || !FatalError) && - WalWriterPID == 0 && -! AutoVacPID == 0 && -! sepgsqlWorkerPID == 0) - { - if (FatalError) - { -diff -Nrpc base/src/backend/security/Makefile sepgsql/src/backend/security/Makefile -*** base/src/backend/security/Makefile Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/Makefile Wed Jul 15 19:39:56 2009 -*************** -*** 0 **** ---- 1,13 ---- -+ # -+ # Makefile for the enhanced security subsystem -+ # -+ -+ subdir = src/backend/security -+ top_builddir = ../../.. -+ include $(top_builddir)/src/Makefile.global -+ -+ SUBDIRS = sepgsql -+ -+ OBJS = rowlevel.o -+ -+ include $(top_srcdir)/src/backend/common.mk -diff -Nrpc base/src/backend/security/rowlevel.c sepgsql/src/backend/security/rowlevel.c -*** base/src/backend/security/rowlevel.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/rowlevel.c Thu Jul 16 17:22:29 2009 -*************** -*** 0 **** ---- 1,121 ---- -+ /* -+ * src/backend/security/common.c -+ * common facilities for row-level access controls both of DAC and MAC -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "catalog/pg_security.h" -+ #include "security/rowlevel.h" -+ #include "security/sepgsql.h" -+ #include "storage/bufmgr.h" -+ #include "storage/bufpage.h" -+ #include "utils/rel.h" -+ #include "utils/tqual.h" -+ -+ /* -+ * rowlvGetPerformingMode -+ * rowlvSetPerformingMode -+ * enables to control the behavior of row-level features -+ * when violated tuples are detected. -+ * The default is ROWLV_FILTER_MODE which filters out -+ * violated tuples from result set, ROWLV_ABORT_MODE -+ * raises an error and ROWLV_BYPASS_MODE do nothing. -+ */ -+ static int rowlv_mode = ROWLV_FILTER_MODE; -+ -+ int rowlvGetPerformingMode(void) -+ { -+ return rowlv_mode; -+ } -+ -+ int rowlvSetPerformingMode(int new_mode) -+ { -+ int old_mode = new_mode; -+ -+ rowlv_mode = new_mode; -+ -+ return old_mode; -+ } -+ -+ /* -+ * rowlvSetupPermissions -+ * setups permissions for row-level access controls. -+ */ -+ uint32 -+ rowlvSetupPermissions(RangeTblEntry *rte) -+ { -+ return sepgsqlSetupTuplePerms(rte); -+ } -+ -+ /* -+ * rowlvExecScan -+ * a hook to filter out invisible/untouchable tuples. -+ */ -+ static bool -+ rowlvExecScan(Scan *scan, Relation rel, TupleTableSlot *slot, bool abort) -+ { -+ HeapTuple tuple; -+ uint32 perms = scan->rowlvPerms; -+ -+ if (!perms) -+ return true; -+ -+ tuple = ExecMaterializeSlot(slot); -+ -+ return sepgsqlExecScan(rel, tuple, perms, abort); -+ } -+ -+ bool -+ rowlvExecScanFilter(Scan *scan, Relation rel, TupleTableSlot *slot) -+ { -+ if (!rel || !scan->rowlvPerms || rowlv_mode != ROWLV_FILTER_MODE) -+ return true; -+ -+ return rowlvExecScan(scan, rel, slot, false); -+ } -+ -+ void -+ rowlvExecScanAbort(Scan *scan, Relation rel, TupleTableSlot *slot) -+ { -+ if (!rel || !scan->rowlvPerms || rowlv_mode != ROWLV_ABORT_MODE) -+ return; -+ -+ rowlvExecScan(scan, rel, slot, true); -+ } -+ -+ /* -+ * rowlvCopyToTuple -+ * checks permission on fetched tuple -+ */ -+ bool -+ rowlvCopyToTuple(Relation rel, HeapTuple tuple) -+ { -+ if (!sepgsqlExecScan(rel, tuple, SEPG_DB_TUPLE__SELECT, false)) -+ return false; -+ -+ return true; -+ } -+ -+ /* -+ * rowlvHeapTupleInsert -+ * assign default security attribute, and check permission -+ * if necessary. -+ */ -+ void -+ rowlvHeapTupleInsert(Relation rel, HeapTuple newtup, bool internal) -+ { -+ sepgsqlHeapTupleInsert(rel, newtup, internal); -+ } -+ -+ /* -+ * rowlvHeapTupleUpdate -+ * check permission to change security attribute, if necesary -+ */ -+ void -+ rowlvHeapTupleUpdate(Relation rel, ItemPointer otid, HeapTuple newtup) -+ { -+ sepgsqlHeapTupleUpdate(rel, otid, newtup); -+ } -diff -Nrpc base/src/backend/security/sepgsql/Makefile sepgsql/src/backend/security/sepgsql/Makefile -*** base/src/backend/security/sepgsql/Makefile Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/Makefile Thu Jul 16 17:22:29 2009 -*************** -*** 0 **** ---- 1,16 ---- -+ # -+ # Makefile -+ # Makefile for utils/sepgsql : SE-PostgreSQL -+ # -+ -+ subdir = src/backend/security/sepgsql -+ top_builddir = ../../../.. -+ include $(top_builddir)/src/Makefile.global -+ -+ ifeq ($(enable_selinux), yes) -+ OBJS = avc.o checker.o hooks.o label.o misc.o perms.o -+ else -+ OBJS = dummy.o -+ endif -+ -+ include $(top_srcdir)/src/backend/common.mk -diff -Nrpc base/src/backend/security/sepgsql/avc.c sepgsql/src/backend/security/sepgsql/avc.c -*** base/src/backend/security/sepgsql/avc.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/avc.c Wed Sep 9 17:45:12 2009 -*************** -*** 0 **** ---- 1,894 ---- -+ /* -+ * src/backend/security/sepgsql/avc.c -+ * SE-PostgreSQL userspace access vector cache -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "access/hash.h" -+ #include "catalog/pg_security.h" -+ #include "libpq/pqsignal.h" -+ #include "miscadmin.h" -+ #include "postmaster/postmaster.h" -+ #include "security/sepgsql.h" -+ #include "storage/ipc.h" -+ #include "storage/lwlock.h" -+ #include "utils/memutils.h" -+ #include -+ #include -+ #include -+ -+ /* -+ * AVC: userspace access vector cache -+ * -+ * SE-PostgreSQL asks in-kernel SELinux to make its decision whether -+ * the required accesses should be allowed, or not, based on the unified -+ * security policy. It needs a system call invocation to communicate -+ * a kernel feature, such as SELinux, but it is a heavy task in most cases -+ * due to the context switching. -+ * -+ * The userspace avc enables to minimize the number of system call -+ * invocations, using a chache mechanim for the certain pair of security -+ * contexts and object classes (it means the kind of actions). -+ * It enables to hold recently fetched results from the in-kernel SELinux, -+ * and make a decision without context switching, if the cache hit. -+ * -+ * When the state of security policy is changed, the cached results -+ * shall to be invalidated. The state monitoring process launched by -+ * postmaster can receives the notification messages from the kernel -+ * space, and invalidate the current version of avc. -+ */ -+ static MemoryContext AvcMemCtx; -+ -+ #define AVC_HASH_NUM_SLOTS 256 -+ #define AVC_HASH_NUM_NODES 180 -+ -+ #define AVC_DATUM_NSID_SLOTS 19 -+ typedef struct -+ { -+ uint32 hash_key; -+ -+ security_class_t tclass; -+ sepgsql_sid_t tsid; -+ sepgsql_sid_t nsid[AVC_DATUM_NSID_SLOTS]; -+ -+ access_vector_t allowed; -+ access_vector_t decided; -+ access_vector_t auditallow; -+ access_vector_t auditdeny; -+ -+ bool hot_cache; -+ bool permissive; -+ -+ char ncontext[1]; -+ } avc_datum; -+ -+ typedef struct avc_page -+ { -+ struct avc_page *next; -+ -+ security_context_t scontext; -+ -+ List *slot[AVC_HASH_NUM_SLOTS]; -+ -+ uint32 avc_count; -+ uint32 lru_hint; -+ } avc_page; -+ -+ static avc_page *current_page = NULL; -+ -+ static int avc_version; -+ -+ /* -+ * selinux_state -+ * -+ * It is deployed on the shared memory region, to show the system -+ * state of SELinux and its security policy. -+ * -+ * The selinux_state->version should be checked prior to avc accesses. -+ * If it does not match with the local avc_version, it means that -+ * system security policy was reloaded or system state (enforcing -+ * or permissive) was changed. -+ * -+ * The state monitoring worker process receives messages from the -+ * kernel using libselinux, and it updates the selinux_state. -+ */ -+ struct -+ { -+ int version; -+ -+ bool enforcing; -+ -+ } *selinux_state = NULL; -+ -+ Size -+ sepgsqlShmemSize(void) -+ { -+ if (!sepgsqlIsEnabled()) -+ return 0; -+ -+ return sizeof(*selinux_state); -+ } -+ -+ /* -+ * sepgsql_shmem_init -+ * attaches shared memory segment. -+ */ -+ static void -+ sepgsqlShmemInit(void) -+ { -+ bool found; -+ -+ selinux_state = ShmemInitStruct("SELinux policy state", -+ sepgsqlShmemSize(), &found); -+ if (!found) -+ { -+ LWLockAcquire(SepgsqlAvcLock, LW_EXCLUSIVE); -+ -+ selinux_state->version = 0; -+ selinux_state->enforcing = (security_getenforce() > 0); -+ -+ LWLockRelease(SepgsqlAvcLock); -+ } -+ } -+ -+ /* -+ * sepgsqlAvcReset -+ * -+ * It invalidate access vector cache. It has to be called on errors, -+ * because avc entries for newly created context is uncertain whether -+ * it is still valid, or not. -+ */ -+ void -+ sepgsqlAvcReset(void) -+ { -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ MemoryContextReset(AvcMemCtx); -+ -+ current_page = NULL; -+ -+ sepgsqlAvcSwitchClient(sepgsqlGetClientLabel()); -+ } -+ -+ /* -+ * sepgsqlAvcCheckValid -+ * -+ * It checks whether the current AVC pages are valid, or not. -+ * If state monitoring process already received an invalidation -+ * message from the kernel, it clears current AVC pages and -+ * returns false. -+ */ -+ static bool -+ sepgsqlAvcCheckValid(void) -+ { -+ bool result = true; -+ -+ LWLockAcquire(SepgsqlAvcLock, LW_SHARED); -+ if (avc_version != selinux_state->version) -+ { -+ /* reset invalid avc pages, and makes an empty one */ -+ MemoryContextReset(AvcMemCtx); -+ -+ current_page = NULL; -+ -+ sepgsqlAvcSwitchClient(sepgsqlGetClientLabel()); -+ -+ /* copy current version to local */ -+ avc_version = selinux_state->version; -+ -+ result = false; -+ } -+ LWLockRelease(SepgsqlAvcLock); -+ -+ return result; -+ } -+ -+ /* -+ * sepgsqlAvcInitialize -+ * -+ * It allocates a memory context for userspace AVC, -+ * map shared memory segment, and initialize avc_page -+ * for the current client's privilege. -+ * -+ * If the current backend is not associated with a certain -+ * client process, it switches to permissive mode to avoid -+ * to prevent any internal processes. -+ */ -+ void -+ sepgsqlAvcInitialize(void) -+ { -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* -+ * local memory context -+ */ -+ AvcMemCtx = AllocSetContextCreate(TopMemoryContext, -+ "SE-PostgreSQL userspace avc", -+ ALLOCSET_DEFAULT_MINSIZE, -+ ALLOCSET_DEFAULT_INITSIZE, -+ ALLOCSET_DEFAULT_MAXSIZE); -+ sepgsqlShmemInit(); -+ -+ /* -+ * Switch to local permissive mode -+ */ -+ if (!MyProcPort) -+ sepgsqlSetEnforce(0); -+ -+ /* -+ * selinux_state->version is never negative value, -+ * so this call always reset local avc. -+ */ -+ avc_version = -1; -+ sepgsqlAvcCheckValid(); -+ } -+ -+ /* -+ * sepgsqlGetEnforce -+ * sepgsqlSetEnforce -+ * -+ * SELinux has two working mode called Enforcing/Permissive. -+ * In enforcing mode, it checks security policy and actually -+ * applies its access controls. In permissive mode, it also -+ * checks security policy, but does not apply any access -+ * controls. It is used to collect access denied logs to -+ * debug security policy. -+ * -+ * sepgsqlGetEnforce() returns the current working mode, and -+ * sepgsqlSetEnforce() switches the current working mode -+ * temporary. When we switches the mode, any errors have to -+ * be acquired, and it should be restored correctly. -+ */ -+ static int local_enforce = -1; /* undefined */ -+ -+ bool -+ sepgsqlGetEnforce(void) -+ { -+ bool rc; -+ -+ if (local_enforce < 0) -+ { -+ LWLockAcquire(SepgsqlAvcLock, LW_SHARED); -+ rc = selinux_state->enforcing; -+ LWLockRelease(SepgsqlAvcLock); -+ -+ return rc; -+ } -+ -+ return (local_enforce > 0 ? true : false); -+ } -+ -+ int -+ sepgsqlSetEnforce(int new_mode) -+ { -+ int old_mode = local_enforce; -+ -+ local_enforce = new_mode; -+ -+ return old_mode; -+ } -+ -+ /* -+ * sepgsqlAvcAudit -+ * -+ * It write out audit message, when auditdeny or auditallow -+ * matches the required permission bits. -+ * If external module support sepgsqlAvcAuditHook, it allows -+ * to write audit logs to external log manager, such as system -+ * auditd. -+ */ -+ -+ PGDLLIMPORT sepgsqlAvcAuditHook_t sepgsqlAvcAuditHook = NULL; -+ -+ static void -+ sepgsqlAvcAudit(bool denied, char *scontext, char *tcontext, -+ uint16 tclass, uint32 audited, const char *audit_name) -+ { -+ StringInfoData buf; -+ uint32 mask; -+ const char *tclass_name; -+ -+ /* translate to human readable form */ -+ scontext = sepgsqlTransSecLabelOut(scontext); -+ tcontext = sepgsqlTransSecLabelOut(tcontext); -+ -+ /* permissions in text representation */ -+ initStringInfo(&buf); -+ appendStringInfo(&buf, "{"); -+ for (mask = 1; audited != 0; mask <<= 1) -+ { -+ if (audited & mask) -+ appendStringInfo(&buf, " %s", sepgsqlGetPermString(tclass, mask)); -+ -+ audited &= ~mask; -+ } -+ appendStringInfo(&buf, " }"); -+ -+ tclass_name = sepgsqlGetClassString(tclass); -+ -+ /* call external audit module, if loaded */ -+ if (sepgsqlAvcAuditHook) -+ (*sepgsqlAvcAuditHook) (denied, scontext, tcontext, -+ tclass_name, buf.data, audit_name); -+ else -+ { -+ appendStringInfo(&buf, " scontext=%s tcontext=%s tclass=%s", -+ scontext, tcontext, tclass_name); -+ if (audit_name) -+ appendStringInfo(&buf, " name=%s", audit_name); -+ -+ ereport(LOG, -+ (errcode(ERRCODE_SELINUX_AUDIT), -+ errmsg("SELinux: %s %s", -+ denied ? "denied" : "granted", buf.data))); -+ } -+ } -+ -+ /* -+ * sepgsqlAvcReclaim -+ * -+ * It wipes recently unused AVC entries, when the number of entries -+ * reaches AVC_HASH_NUM_NODES.. -+ */ -+ static void -+ sepgsqlAvcReclaim(avc_page *page) -+ { -+ ListCell *l; -+ avc_datum *cache; -+ -+ while (page->avc_count > AVC_HASH_NUM_NODES) -+ { -+ foreach (l, page->slot[page->lru_hint]) -+ { -+ cache = lfirst(l); -+ -+ if (cache->hot_cache) -+ cache->hot_cache = false; -+ else -+ { -+ list_delete_ptr(page->slot[page->lru_hint], cache); -+ pfree(cache); -+ page->avc_count--; -+ } -+ } -+ page->lru_hint = (page->lru_hint + 1) % AVC_HASH_NUM_SLOTS; -+ } -+ } -+ -+ /* -+ * sepgsqlAvcMakeEntry -+ * -+ * It makes a new AVC entry and insert it on the avc_page. -+ * If is hold more than AVC_HASH_NUM_NODES entries, recently unused -+ * avc_datum shall be reclaimed. -+ */ -+ #define avc_hash_key(trelid,tsecid,tclass) \ -+ (hash_uint32((trelid) ^ (tsecid) ^ ((tclass) << 3))) -+ -+ static avc_datum * -+ sepgsqlAvcMakeEntry(avc_page *page, sepgsql_sid_t tsid, uint16 tclass) -+ { -+ security_context_t scontext, tcontext, ncontext; -+ security_class_t tclass_ex; -+ MemoryContext oldctx; -+ struct av_decision avd; -+ avc_datum *cache; -+ uint32 hash_key, index; -+ -+ hash_key = avc_hash_key(tsid.relid, tsid.secid, tclass); -+ index = hash_key % AVC_HASH_NUM_SLOTS; -+ -+ scontext = page->scontext; -+ tcontext = securityRawSecLabelOut(tsid.relid, tsid.secid); -+ -+ /* -+ * Compute SELinux permission -+ */ -+ tclass_ex = sepgsqlTransToExternalClass(tclass); -+ if (tclass_ex > 0) -+ { -+ if (security_compute_av_flags_raw(scontext, tcontext, -+ tclass_ex, 0, &avd) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: unable to compute av_decision: " -+ "scontext=%s tcontext=%s tclass=%s", -+ scontext, tcontext, -+ sepgsqlGetClassString(tclass)))); -+ sepgsqlTransToInternalPerms(tclass, &avd); -+ } -+ else -+ { -+ /* fill it up as undefined class */ -+ avd.allowed = (security_deny_unknown() ? 0 : ~0UL); -+ avd.decided = ~0UL; -+ avd.auditallow = 0UL; -+ avd.auditdeny = ~0UL; -+ avd.flags = 0; -+ } -+ -+ /* -+ * Compute New security context -+ */ -+ if (security_compute_create_raw(scontext, tcontext, -+ tclass_ex, &ncontext) < 0) -+ { -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: unable to compute new context: " -+ "scontext=%s tcontext=%s tclass=%s", -+ scontext, tcontext, sepgsqlGetClassString(tclass)))); -+ } -+ -+ /* -+ * Copy them to avc_datum -+ */ -+ oldctx = MemoryContextSwitchTo(AvcMemCtx); -+ PG_TRY(); -+ { -+ cache = palloc0(sizeof(avc_datum) + strlen(ncontext)); -+ } -+ PG_CATCH(); -+ { -+ freecon(ncontext); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ -+ cache->hash_key = hash_key; -+ cache->tclass = tclass; -+ cache->tsid.relid = tsid.relid; -+ cache->tsid.secid = tsid.secid; -+ /* cache->nsid shall be set later */ -+ -+ cache->allowed = avd.allowed; -+ cache->decided = avd.decided; -+ cache->auditallow = avd.auditallow; -+ cache->auditdeny = avd.auditdeny; -+ -+ cache->hot_cache = true; -+ if (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE) -+ cache->permissive = true; -+ strcpy(cache->ncontext, ncontext); -+ freecon(ncontext); -+ -+ sepgsqlAvcReclaim(page); -+ -+ page->slot[index] = lcons(cache, page->slot[index]); -+ page->avc_count++; -+ -+ MemoryContextSwitchTo(oldctx); -+ -+ return cache; -+ } -+ -+ /* -+ * sepgsqlAvcLookup -+ * -+ * It lookups required AVC entry. -+ */ -+ static avc_datum * -+ sepgsqlAvcLookup(avc_page *page, sepgsql_sid_t tsid, uint16 tclass) -+ { -+ avc_datum *cache = NULL; -+ uint32 hash_key, index; -+ ListCell *l; -+ -+ hash_key = avc_hash_key(tsid.relid, tsid.secid, tclass); -+ index = hash_key % AVC_HASH_NUM_SLOTS; -+ -+ foreach (l, page->slot[index]) -+ { -+ cache = lfirst(l); -+ if (cache->hash_key == hash_key -+ && cache->tclass == tclass -+ && cache->tsid.relid == tsid.relid -+ && cache->tsid.secid == tsid.secid) -+ { -+ cache->hot_cache = true; -+ return cache; -+ } -+ } -+ return NULL; -+ } -+ -+ /* -+ * sepgsqlAvcSwitchClientLabel() -+ * -+ * It switches the current avc_page. -+ * An avc_page is a set of cached access control decisions associated -+ * with a certain privilege of the client. This structure enables to -+ * lookup required avc_datum without any comparison to the subject -+ * label. -+ */ -+ void -+ sepgsqlAvcSwitchClient(const char *scontext) -+ { -+ MemoryContext oldctx; -+ avc_page *new_page; -+ int i; -+ -+ if (current_page) -+ { -+ new_page = current_page; -+ do { -+ if (strcmp(new_page->scontext, scontext) == 0) -+ { -+ current_page = new_page; -+ return; -+ } -+ new_page = new_page->next; -+ } while (new_page != current_page); -+ } -+ -+ /* Not found, create a new avc_page */ -+ oldctx = MemoryContextSwitchTo(AvcMemCtx); -+ new_page = palloc0(sizeof(avc_page)); -+ new_page->scontext = pstrdup(scontext); -+ MemoryContextSwitchTo(oldctx); -+ -+ for (i=0; i < AVC_HASH_NUM_SLOTS; i++) -+ new_page->slot[i] = NIL; -+ -+ if (!current_page) -+ new_page->next = new_page; -+ else -+ { -+ new_page->next = current_page->next; -+ current_page->next = new_page; -+ } -+ -+ current_page = new_page; -+ } -+ -+ /* -+ * sepgsqlClientHasPerms -+ * -+ * It checks client's privileges on the given object using avc. -+ */ -+ bool -+ sepgsqlClientHasPerms(sepgsql_sid_t tsid, -+ uint16 tclass, uint32 required, -+ const char *audit_name, bool abort) -+ { -+ avc_datum *cache; -+ uint32 denied, audited; -+ bool result = true; -+ -+ Assert(required != 0); -+ -+ do { -+ cache = sepgsqlAvcLookup(current_page, tsid, tclass); -+ if (!cache) -+ cache = sepgsqlAvcMakeEntry(current_page, tsid, tclass); -+ } while (!sepgsqlAvcCheckValid()); -+ -+ denied = required & ~cache->allowed; -+ audited = denied ? (denied & cache->auditdeny) -+ : (required & cache->auditallow); -+ if (audited) -+ { -+ sepgsqlAvcAudit(!!denied, -+ current_page->scontext, -+ securityRawSecLabelOut(tsid.relid, tsid.secid), -+ cache->tclass, audited, audit_name); -+ } -+ -+ if (denied) -+ { -+ if (!sepgsqlGetEnforce() || cache->permissive) -+ cache->allowed |= required; /* prevent flood of audit log */ -+ else -+ { -+ if (abort) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: security policy violation"))); -+ result = false; -+ } -+ } -+ -+ return result; -+ } -+ -+ /* -+ * sepgsqlClientCreateSecid -+ * sepgsqlClientCreateLabel -+ */ -+ sepgsql_sid_t -+ sepgsqlClientCreateSecid(sepgsql_sid_t tsid, uint16 tclass, Oid nrelid) -+ { -+ sepgsql_sid_t nsid; -+ avc_datum *cache; -+ int index; -+ -+ do { -+ cache = sepgsqlAvcLookup(current_page, tsid, tclass); -+ if (!cache) -+ cache = sepgsqlAvcMakeEntry(current_page, tsid, tclass); -+ -+ index = (nrelid % AVC_DATUM_NSID_SLOTS); -+ if (cache->nsid[index].relid != nrelid) -+ { -+ cache->nsid[index].secid -+ = securityRawSecLabelIn(nrelid, cache->ncontext); -+ cache->nsid[index].relid = nrelid; -+ } -+ nsid = cache->nsid[index]; -+ } while (!sepgsqlAvcCheckValid()); -+ -+ return nsid; -+ } -+ -+ security_context_t -+ sepgsqlClientCreateLabel(sepgsql_sid_t tsid, uint16 tclass) -+ { -+ avc_datum *cache; -+ -+ do { -+ cache = sepgsqlAvcLookup(current_page, tsid, tclass); -+ if (!cache) -+ cache = sepgsqlAvcMakeEntry(current_page, tsid, tclass); -+ } while (!sepgsqlAvcCheckValid()); -+ -+ return cache->ncontext; -+ } -+ -+ /* -+ * sepgsqlComputePerms -+ * sepgsqlComputeCreate -+ * -+ * The following two functions make a query to in-kernel SELinux -+ * without userspace caches, due to some reasons. -+ * The AVC can cover most of cases, but some of corner cases are -+ * not suitable for AVC structure, so we need uncached interfaces. -+ * For example, AVC is unavailable when we tries to load a shared -+ * library module, because security context of the library does not -+ * have its security identifier, so we cannot put it on AVC. -+ */ -+ bool -+ sepgsqlComputePerms(char *scontext, char *tcontext, -+ uint16 tclass_in, uint32 required, -+ const char *audit_name, bool abort) -+ { -+ access_vector_t denied, audited; -+ security_class_t tclass_ex; -+ struct av_decision avd; -+ -+ Assert(required != 0); -+ -+ tclass_ex = sepgsqlTransToExternalClass(tclass_in); -+ if (tclass_ex > 0) -+ { -+ /* -+ * security_compute_av_flags_raw() is a SELinux's API that -+ * returns its access control decision based on the security -+ * policy, to the given combination of user's privilege -+ * (scontext; security label of the client process), -+ * target's attribute (tcontext; security label of the -+ * object) and type of actions (tclass; object classes). -+ * -+ * The returned avd.allowed is a bitmap of allowed actions. -+ */ -+ if (security_compute_av_flags_raw(scontext, tcontext, -+ tclass_ex, 0, &avd) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not compute av_decision: " -+ "scontext=%s tcontext=%s tclass=%s", -+ scontext, tcontext, -+ sepgsqlGetClassString(tclass_in)))); -+ sepgsqlTransToInternalPerms(tclass_in, &avd); -+ } -+ else -+ { -+ /* -+ * If security policy does not support database related -+ * permissions, it fulls up permission bits by dummy -+ * data. -+ * If security_deny_unknown() returns positive value, -+ * undefined permissions should not be allowed. -+ * Otherwise, it shall be allowed. -+ */ -+ avd.allowed = (security_deny_unknown() > 0 ? 0 : ~0UL); -+ avd.decided = ~0UL; -+ avd.auditallow = 0UL; -+ avd.auditdeny = ~0UL; -+ avd.flags = 0; -+ } -+ -+ denied = required & ~avd.allowed; -+ audited = denied ? (denied & avd.auditdeny) -+ : (required & avd.auditallow); -+ if (audited) -+ { -+ /* -+ * If security policy requires to generate an audit log -+ * record for the given request, it should be logged. -+ */ -+ sepgsqlAvcAudit(!!denied, scontext, tcontext, -+ tclass_in, audited, audit_name); -+ } -+ -+ /* -+ * If any required permissions are not allowed, and -+ * SE-PgSQL performs in enforcing mode, and the given -+ * combination of subject, object and action does not -+ * have special flag to be handled as permission, -+ * SE-PgSQL returns false or raises an error. -+ * Otherwise, it returns true that means required -+ * actions are allowed. -+ */ -+ if (!denied || /* no policy violation */ -+ !sepgsqlGetEnforce() || /* permissive mode */ -+ (avd.flags & SELINUX_AVD_FLAGS_PERMISSIVE) != 0) /* permissive domain */ -+ return true; -+ -+ if (abort) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: security policy violation"))); -+ -+ return false; -+ } -+ -+ char * -+ sepgsqlComputeCreate(char *scontext, char *tcontext, uint16 tclass_in) -+ { -+ security_context_t ncontext, result; -+ security_class_t tclass_ex; -+ -+ tclass_ex = sepgsqlTransToExternalClass(tclass_in); -+ /* -+ * security_compute_create_raw() is a SELinux's API that -+ * returns a default security context to be assigned on -+ * a new object (categorized by object class) when a client -+ * labeled as scontext tries to create a new one under the -+ * parent object labeled as tcontext. -+ */ -+ if (security_compute_create_raw(scontext, tcontext, -+ tclass_ex, &ncontext) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not compute a new context " -+ "scontext=%s tcontext=%s tclass=%s", -+ scontext, tcontext, sepgsqlGetClassString(tclass_in)))); -+ PG_TRY(); -+ { -+ result = pstrdup(ncontext); -+ } -+ PG_CATCH(); -+ { -+ freecon(ncontext); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ freecon(ncontext); -+ -+ return result; -+ } -+ -+ /* -+ * SELinux state monitoring process -+ * -+ * This process is forked from postmaster to monitor the state of SELinux. -+ * SELinux can make a notifier message to userspace object manager via -+ * netlink socket. When it receives the message, it updates selinux_state -+ * structure assigned on shared memory region to make any instance reset -+ * its AVC soon. -+ */ -+ static int -+ sepgsql_cb_log(int type, const char *fmt, ...) -+ { -+ char *c, buffer[1024]; -+ va_list ap; -+ -+ va_start(ap, fmt); -+ vsnprintf(buffer, sizeof(buffer), fmt, ap); -+ va_end(ap); -+ -+ c = strrchr(buffer, '\n'); -+ if (c) -+ *c = '\0'; -+ -+ ereport(LOG, -+ (errcode(ERRCODE_SELINUX_INFO), -+ errmsg("%s", buffer))); -+ -+ return 0; -+ } -+ -+ static int -+ sepgsql_cb_setenforce(int enforce) -+ { -+ /* switch enforcing/permissive */ -+ LWLockAcquire(SepgsqlAvcLock, LW_EXCLUSIVE); -+ selinux_state->version = selinux_state->version + 1; -+ selinux_state->enforcing = (enforce ? true : false); -+ LWLockRelease(SepgsqlAvcLock); -+ -+ return 0; -+ } -+ -+ static int -+ sepgsql_cb_policyload(int seqno) -+ { -+ /* invalidate local avc */ -+ LWLockAcquire(SepgsqlAvcLock, LW_EXCLUSIVE); -+ selinux_state->version = selinux_state->version + 1; -+ LWLockRelease(SepgsqlAvcLock); -+ -+ return 0; -+ } -+ -+ static int -+ sepgsqlWorkerMain(void) -+ { -+ union selinux_callback cb; -+ -+ ClosePostmasterPorts(false); -+ -+ on_exit_reset(); -+ -+ /* -+ * map shared memory segment -+ */ -+ sepgsqlShmemInit(); -+ -+ /* -+ * setup the signal handler -+ */ -+ pqinitmask(); -+ pqsignal(SIGHUP, SIG_IGN); -+ pqsignal(SIGINT, SIG_IGN); -+ pqsignal(SIGTERM, exit); -+ pqsignal(SIGQUIT, exit); -+ pqsignal(SIGUSR1, SIG_IGN); -+ pqsignal(SIGUSR2, SIG_IGN); -+ pqsignal(SIGCHLD, SIG_DFL); -+ PG_SETMASK(&UnBlockSig); -+ -+ ereport(LOG, -+ (errcode(ERRCODE_SELINUX_INFO), -+ errmsg("SELinux: security policy monitor (pid=%u)", getpid()))); -+ /* -+ * setup callback functions from avc_netlink_loop() -+ */ -+ cb.func_log = sepgsql_cb_log; -+ selinux_set_callback(SELINUX_CB_LOG, cb); -+ cb.func_setenforce = sepgsql_cb_setenforce; -+ selinux_set_callback(SELINUX_CB_SETENFORCE, cb); -+ cb.func_policyload = sepgsql_cb_policyload; -+ selinux_set_callback(SELINUX_CB_POLICYLOAD, cb); -+ -+ /* -+ * open netlink socket and wait for messages -+ */ -+ avc_netlink_open(1); -+ -+ avc_netlink_loop(); -+ -+ return 0; -+ } -+ -+ pid_t -+ sepgsqlStartupWorkerProcess(void) -+ { -+ pid_t chld; -+ -+ if (!sepgsqlIsEnabled()) -+ return (pid_t) 0; -+ -+ chld = fork(); -+ if (chld == 0) -+ exit(sepgsqlWorkerMain()); -+ else if (chld > 0) -+ return chld; -+ -+ return (pid_t) 0; -+ } -diff -Nrpc base/src/backend/security/sepgsql/checker.c sepgsql/src/backend/security/sepgsql/checker.c -*** base/src/backend/security/sepgsql/checker.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/checker.c Thu Sep 10 00:06:47 2009 -*************** -*** 0 **** ---- 1,443 ---- -+ /* -+ * src/backend/security/sepgsql/checker.c -+ * walks on given Query tree and applies checks -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "access/sysattr.h" -+ #include "catalog/catalog.h" -+ #include "catalog/pg_security.h" -+ #include "miscadmin.h" -+ #include "security/sepgsql.h" -+ #include "storage/bufmgr.h" -+ #include "utils/lsyscache.h" -+ #include "utils/syscache.h" -+ #include "utils/tqual.h" -+ -+ /* -+ * fixupWholeRowReference -+ */ -+ static Bitmapset * -+ fixupWholeRowReference(Oid relid, int nattrs, Bitmapset *columns) -+ { -+ Bitmapset *result; -+ AttrNumber attno; -+ -+ attno = InvalidAttrNumber - FirstLowInvalidHeapAttributeNumber; -+ -+ if (!bms_is_member(attno, columns)) -+ return columns; /* no need to fixup */ -+ -+ result = bms_copy(columns); -+ result = bms_del_member(result, attno); -+ -+ for (attno=1; attno <= nattrs; attno++) -+ { -+ Form_pg_attribute attform; -+ HeapTuple atttup; -+ -+ atttup = SearchSysCache(ATTNUM, -+ ObjectIdGetDatum(relid), -+ Int16GetDatum(attno), -+ 0, 0); -+ if (!HeapTupleIsValid(atttup)) -+ continue; -+ -+ attform = (Form_pg_attribute) GETSTRUCT(atttup); -+ if (!attform->attisdropped) -+ { -+ int cindex = attno - FirstLowInvalidHeapAttributeNumber; -+ result = bms_add_member(result, cindex); -+ } -+ ReleaseSysCache(atttup); -+ } -+ -+ return result; -+ } -+ -+ /* -+ * checkTabelColumnPerms -+ * This functions applies table/column level permissions for -+ * all the appeared ones in user's query, and raises an error -+ * if violated. -+ * It also applies a few hardwired policy which prevent to -+ * modified some of system catalogs. -+ */ -+ static void -+ checkTabelColumnPerms(Oid relid, Bitmapset *selected, Bitmapset *modified, -+ access_vector_t required) -+ { -+ Bitmapset *columns; -+ Bitmapset *selected_ex; -+ Bitmapset *modified_ex; -+ Form_pg_class relForm; -+ HeapTuple reltup; -+ sepgsql_sid_t relsid; -+ sepgsql_sid_t attsid; -+ AttrNumber attno; -+ uint16 tclass; -+ -+ /* -+ * Hardwired Policy: -+ * SE-PostgreSQL enforces that clients cannot modify system -+ * catalogs and access toast values using DML statements, -+ * except initial setting up phase. -+ */ -+ if (sepgsqlGetEnforce()) -+ { -+ if (IsSystemNamespace(get_rel_namespace(relid)) && -+ (required & (SEPG_DB_TABLE__UPDATE | -+ SEPG_DB_TABLE__INSERT | -+ SEPG_DB_TABLE__DELETE)) != 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SE-PostgreSQL prevents to modidy \"%s\"", -+ get_rel_name(relid)))); -+ if (get_rel_relkind(relid) == RELKIND_TOASTVALUE) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SE-PostgreSQL prevents to access \"%s\"", -+ get_rel_name(relid)))); -+ } -+ -+ /* -+ * Check db_table:{...} or db_sequence permissions -+ */ -+ reltup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(relid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(reltup)) -+ elog(ERROR, "SELinux: cache lookup failed for relation %u", relid); -+ -+ relForm = (Form_pg_class) GETSTRUCT(reltup); -+ -+ relsid = sepgsqlGetTupleContext(RelationRelationId, reltup, &tclass); -+ -+ if (tclass != SEPG_CLASS_DB_TABLE) -+ { -+ /* check db_sequence:{xxx} permission */ -+ if (tclass == SEPG_CLASS_DB_SEQUENCE) -+ { -+ if (required & SEPG_DB_TABLE__SELECT) -+ { -+ sepgsqlClientHasPerms(relsid, tclass, -+ SEPG_DB_SEQUENCE__GET_VALUE, -+ NameStr(relForm->relname), true); -+ } -+ } -+ ReleaseSysCache(reltup); -+ return; -+ } -+ sepgsqlClientHasPerms(relsid, tclass, required, -+ NameStr(relForm->relname), true); -+ -+ /* -+ * Check db_column:{...} permissions -+ */ -+ selected_ex = fixupWholeRowReference(relid, relForm->relnatts, selected); -+ modified_ex = fixupWholeRowReference(relid, relForm->relnatts, modified); -+ columns = bms_union(selected_ex, modified_ex); -+ -+ while ((attno = bms_first_member(columns)) >= 0) -+ { -+ Form_pg_attribute attForm; -+ HeapTuple atttup; -+ uint32 attperms = 0; -+ char auname[2 * NAMEDATALEN + 3]; -+ -+ if (bms_is_member(attno, selected_ex)) -+ attperms |= SEPG_DB_COLUMN__SELECT; -+ if (bms_is_member(attno, modified_ex)) -+ { -+ if (required & SEPG_DB_TABLE__UPDATE) -+ attperms |= SEPG_DB_COLUMN__UPDATE; -+ if (required & SEPG_DB_TABLE__INSERT) -+ attperms |= SEPG_DB_COLUMN__INSERT; -+ } -+ if (attperms == 0) -+ continue; -+ -+ /* remove the attribute number offset */ -+ attno += FirstLowInvalidHeapAttributeNumber; -+ atttup = SearchSysCache(ATTNUM, -+ ObjectIdGetDatum(relid), -+ Int16GetDatum(attno), -+ 0, 0); -+ if (!HeapTupleIsValid(atttup)) -+ elog(ERROR, "cache lookup failed for attribute %d of relation %u", -+ attno, relid); -+ -+ attForm = (Form_pg_attribute) GETSTRUCT(atttup); -+ if (attForm->attisdropped) -+ elog(ERROR, "attribute %d of relation %u does not exist", -+ attno, relid); -+ -+ snprintf(auname, sizeof(auname), "%s.%s", -+ NameStr(relForm->relname), -+ NameStr(attForm->attname)); -+ attsid = sepgsqlGetTupleContext(AttributeRelationId, -+ atttup, &tclass); -+ sepgsqlClientHasPerms(attsid, tclass, attperms, auname, true); -+ -+ ReleaseSysCache(atttup); -+ } -+ -+ ReleaseSysCache(reltup); -+ -+ if (selected_ex != selected) -+ bms_free(selected_ex); -+ -+ if (modified_ex != modified) -+ bms_free(modified_ex); -+ -+ bms_free(columns); -+ } -+ -+ /* -+ * sepgsqlCheckQueryPerms -+ * It checks permission for all the required tables/columns on -+ * generic user queries. -+ */ -+ void -+ sepgsqlCheckRTEPerms(RangeTblEntry *rte) -+ { -+ access_vector_t required = 0; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ if (rte->rtekind != RTE_RELATION) -+ return; -+ -+ if (rte->requiredPerms & ACL_SELECT) -+ required |= SEPG_DB_TABLE__SELECT; -+ if (rte->requiredPerms & ACL_INSERT) -+ required |= SEPG_DB_TABLE__INSERT; -+ if (rte->requiredPerms & ACL_UPDATE) -+ { -+ /* -+ * ACL_SELECT_FOR_UPDATE is defined as an aliase of ACL_UPDATE, -+ * so we cannot determine whether the given relation is accessed -+ * with UPDATE statement or SELECT FOR SHARE/UPDATE immediately. -+ * UPDATE statements set a bit on rte->modifiedCols at least, -+ * so we use it as a watermark. -+ */ -+ if (!bms_is_empty(rte->modifiedCols)) -+ required |= SEPG_DB_TABLE__UPDATE; -+ else -+ required |= SEPG_DB_TABLE__LOCK; -+ } -+ if (rte->requiredPerms & ACL_DELETE) -+ required |= SEPG_DB_TABLE__DELETE; -+ -+ if (required == 0) -+ return; -+ -+ checkTabelColumnPerms(rte->relid, -+ rte->selectedCols, -+ rte->modifiedCols, -+ required); -+ } -+ -+ /* -+ * sepgsqlCheckCopyTable -+ * It checks permissions on COPY TO/FROM. -+ */ -+ void -+ sepgsqlCheckCopyTable(Relation rel, List *attnumlist, bool is_from) -+ { -+ Bitmapset *selected = NULL; -+ Bitmapset *modified = NULL; -+ ListCell *l; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* all checkes are done in sepgsqlCheckRTEPerms */ -+ if (!rel) -+ return; -+ -+ foreach (l, attnumlist) -+ { -+ AttrNumber attno = lfirst_int(l); -+ -+ attno -= FirstLowInvalidHeapAttributeNumber; -+ if (is_from) -+ modified = bms_add_member(modified, attno); -+ else -+ selected = bms_add_member(selected, attno); -+ } -+ -+ checkTabelColumnPerms(RelationGetRelid(rel), -+ selected, modified, -+ is_from ? SEPG_DB_TABLE__INSERT -+ : SEPG_DB_TABLE__SELECT); -+ } -+ -+ /* -+ * sepgsqlCheckSelectInto -+ * It checks db_table/db_column:{insert} on the table newly created -+ */ -+ void -+ sepgsqlCheckSelectInto(Oid relationId) -+ { -+ Bitmapset *modified = NULL; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ modified = bms_add_member(modified, InvalidAttrNumber -+ - FirstLowInvalidHeapAttributeNumber); -+ -+ checkTabelColumnPerms(relationId, NULL, modified, -+ SEPG_DB_TABLE__INSERT); -+ } -+ -+ /* -+ * sepgsqlExecScan -+ * makes a decision on the given tuple. -+ */ -+ bool -+ sepgsqlExecScan(Relation rel, HeapTuple tuple, uint32 required, bool abort) -+ { -+ sepgsql_sid_t sid; -+ uint16 tclass; -+ -+ if (!sepgsqlIsEnabled() || -+ !required || -+ RelationGetForm(rel)->relkind != RELKIND_RELATION || -+ RelationGetRelid(rel) == SecurityRelationId) -+ return true; -+ -+ sid = sepgsqlGetTupleContext(RelationGetRelid(rel), tuple, &tclass); -+ /* -+ * Insert/Delete to an external attribute is equivalent to -+ * the set-attribute on the master -+ */ -+ if (sid.relid != RelationGetRelid(rel) && -+ (required & (SEPG_DB_TUPLE__INSERT | SEPG_DB_TUPLE__DELETE))) -+ { -+ required &= ~(SEPG_DB_TUPLE__INSERT | SEPG_DB_TUPLE__DELETE); -+ required |= SEPG_DB_TUPLE__UPDATE; -+ } -+ -+ return sepgsqlClientHasPerms(sid, tclass, required, NULL, abort); -+ } -+ -+ uint32 -+ sepgsqlSetupTuplePerms(RangeTblEntry *rte) -+ { -+ AclMode perms = 0; -+ -+ if (!sepgsqlIsEnabled()) -+ return 0; -+ -+ if (rte->rtekind != RTE_RELATION) -+ return 0; -+ -+ if (rte->requiredPerms & ACL_SELECT) -+ perms |= SEPG_DB_TUPLE__SELECT; -+ if (rte->requiredPerms & ACL_UPDATE && !bms_is_empty(rte->modifiedCols)) -+ perms |= SEPG_DB_TUPLE__UPDATE; -+ if (rte->requiredPerms & ACL_DELETE) -+ perms |= SEPG_DB_TUPLE__DELETE; -+ -+ return perms; -+ } -+ -+ /* -+ * sepgsqlHeapTupleInsert -+ * It assigns a default security label, if no explicit security labels -+ * were given. In addition, it also checks db_tuple:{insert} for the -+ * tuple newly inserted, when it invoked from user's query. -+ */ -+ void -+ sepgsqlHeapTupleInsert(Relation rel, HeapTuple newtup, bool internal) -+ { -+ sepgsql_sid_t sid; -+ uint16 tclass; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* -+ * assigns a default security label, if not explicit one -+ */ -+ if (!OidIsValid(HeapTupleGetSecid(newtup))) -+ { -+ if (HeapTupleHasSecid(newtup)) -+ sepgsqlSetDefaultSecid(rel, newtup); -+ } -+ -+ /* -+ * It does not check permission for the new tuples -+ * inserted by system internal stuff using -+ * simple_heap_insert(); -+ */ -+ if (internal) -+ return; -+ -+ sid = sepgsqlGetTupleContext(RelationGetRelid(rel), -+ newtup, &tclass); -+ sepgsqlClientHasPerms(sid, tclass, SEPG_DB_TUPLE__INSERT, NULL, true); -+ } -+ -+ /* -+ * sepgsqlHeapTupleUpdate -+ * It checks db_tuple:{relabelfrom relabelto} permission on -+ * the user queries. (Please note that it does not check -+ * system internal stuff via simple_heap_update) -+ */ -+ void -+ sepgsqlHeapTupleUpdate(Relation rel, ItemPointer otid, HeapTuple newtup) -+ { -+ Oid secid; -+ HeapTupleData oldtup; -+ Buffer oldbuf; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* -+ * heap_update() preserves the original security label -+ * of the given tuple, if no explicit security label -+ * is assigned on the newer version. -+ * In this case, db_tuple:{update} is already checked -+ * at the sepgsqlExecScan() hook, so we don't need to -+ * check anything more. -+ */ -+ secid = HeapTupleGetSecid(newtup); -+ if (!OidIsValid(secid)) -+ return; -+ -+ /* -+ * User gave an explicit security label -+ */ -+ ItemPointerCopy(otid, &oldtup.t_self); -+ if (!heap_fetch(rel, SnapshotAny, &oldtup, &oldbuf, false, NULL)) -+ elog(ERROR, "failed to fetch old version of the tuple"); -+ -+ if (secid != HeapTupleGetSecid(&oldtup)) -+ { -+ sepgsql_sid_t sid; -+ uint16 tclass; -+ -+ /* db_tuple:{relabelfrom} for older security context */ -+ sid = sepgsqlGetTupleContext(RelationGetRelid(rel), -+ &oldtup, &tclass); -+ sepgsqlClientHasPerms(sid, tclass, -+ SEPG_DB_TUPLE__RELABELFROM, -+ NULL, true); -+ -+ /* db_tuple:{relabelto} for newer security label */ -+ sid = sepgsqlGetTupleContext(RelationGetRelid(rel), -+ newtup, &tclass); -+ sepgsqlClientHasPerms(sid, tclass, -+ SEPG_DB_TUPLE__RELABELTO, -+ NULL, true); -+ } -+ ReleaseBuffer(oldbuf); -+ } -diff -Nrpc base/src/backend/security/sepgsql/dummy.c sepgsql/src/backend/security/sepgsql/dummy.c -*** base/src/backend/security/sepgsql/dummy.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/dummy.c Wed Jul 15 19:39:56 2009 -*************** -*** 0 **** ---- 1,79 ---- -+ /* -+ * src/backend/utils/sepgsql/dummy.c -+ * A set of stubs when SE-PostgreSQL is not activated -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "security/sepgsql.h" -+ -+ static Datum -+ unavailable_function(const char *fn_name) -+ { -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("function \"%s\" is not available", fn_name))); -+ PG_RETURN_VOID(); -+ } -+ -+ Datum -+ sepgsql_getcon(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_server_getcon(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_get_user(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_get_role(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_get_type(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_get_range(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_set_user(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_set_role(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_set_type(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -+ -+ Datum -+ sepgsql_set_range(PG_FUNCTION_ARGS) -+ { -+ return unavailable_function(__FUNCTION__); -+ } -diff -Nrpc base/src/backend/security/sepgsql/hooks.c sepgsql/src/backend/security/sepgsql/hooks.c -*** base/src/backend/security/sepgsql/hooks.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/hooks.c Thu Sep 10 00:06:47 2009 -*************** -*** 0 **** ---- 1,1273 ---- -+ /* -+ * src/backend/security/sepgsql/hooks.c -+ * SE-PostgreSQL security hooks -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "catalog/indexing.h" -+ #include "catalog/namespace.h" -+ #include "catalog/pg_database.h" -+ #include "catalog/pg_foreign_data_wrapper.h" -+ #include "catalog/pg_language.h" -+ #include "catalog/pg_largeobject.h" -+ #include "catalog/pg_namespace.h" -+ #include "catalog/pg_opclass.h" -+ #include "catalog/pg_operator.h" -+ #include "catalog/pg_opfamily.h" -+ #include "catalog/pg_proc.h" -+ #include "catalog/pg_security.h" -+ #include "catalog/pg_trigger.h" -+ #include "catalog/pg_ts_dict.h" -+ #include "catalog/pg_ts_parser.h" -+ #include "catalog/pg_ts_template.h" -+ #include "catalog/pg_type.h" -+ #include "catalog/pg_security.h" -+ #include "commands/dbcommands.h" -+ #include "miscadmin.h" -+ #include "security/sepgsql.h" -+ #include "utils/builtins.h" -+ #include "utils/fmgroids.h" -+ #include "utils/lsyscache.h" -+ #include "utils/syscache.h" -+ #include "utils/tqual.h" -+ -+ /* -+ * ------------------------------------------------------------ -+ * Hooks corresponding to db_database object class -+ * ------------------------------------------------------------ -+ * -+ * sepgsqlCheckDatabaseInstallModule -+ * checks db_database:{install_module} permission when the client -+ * tries to install a dynamic link library on the current databse. -+ * -+ * sepgsqlCheckDatabaseLoadModule -+ * checks capability of the database when it loads a certain DLL -+ * into its process address space. -+ */ -+ Oid -+ sepgsqlCheckDatabaseCreate(const char *datname, DefElem *newLabel) -+ { -+ sepgsql_sid_t datSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return InvalidOid; -+ -+ if (!newLabel) -+ datSid = sepgsqlGetDefaultDatabaseSecid(); -+ else -+ { -+ datSid.relid = DatabaseRelationId; -+ datSid.secid = securityTransSecLabelIn(datSid.relid, -+ strVal(newLabel->arg)); -+ } -+ -+ sepgsqlClientHasPerms(datSid, -+ SEPG_CLASS_DB_DATABASE, -+ SEPG_DB_DATABASE__CREATE, -+ datname, true); -+ return datSid.secid; -+ } -+ -+ static bool -+ checkDatabaseCommon(Oid datOid, uint32 required, bool abort) -+ { -+ HeapTuple tuple; -+ sepgsql_sid_t datSid; -+ uint16 tclass; -+ const char *auname; -+ bool rc; -+ -+ if (!sepgsqlIsEnabled()) -+ return true; -+ -+ tuple = SearchSysCache(DATABASEOID, -+ ObjectIdGetDatum(datOid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for database: %u", datOid); -+ -+ auname = NameStr(((Form_pg_database) GETSTRUCT(tuple))->datname); -+ datSid = sepgsqlGetTupleContext(DatabaseRelationId, -+ tuple, &tclass); -+ rc = sepgsqlClientHasPerms(datSid, -+ tclass, required, -+ auname, abort); -+ -+ ReleaseSysCache(tuple); -+ -+ return rc; -+ } -+ -+ void -+ sepgsqlCheckDatabaseDrop(Oid datOid) -+ { -+ checkDatabaseCommon(datOid, SEPG_DB_DATABASE__DROP, true); -+ } -+ -+ void -+ sepgsqlCheckDatabaseSetattr(Oid datOid) -+ { -+ checkDatabaseCommon(datOid, SEPG_DB_DATABASE__SETATTR, true); -+ } -+ -+ Oid -+ sepgsqlCheckDatabaseRelabel(Oid datOid, DefElem *newLabel) -+ { -+ sepgsql_sid_t datSid; -+ -+ if (!sepgsqlIsEnabled()) -+ { -+ if (newLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux is disabled now"))); -+ return InvalidOid; -+ } -+ datSid.relid = DatabaseRelationId; -+ datSid.secid = securityTransSecLabelIn(datSid.relid, -+ strVal(newLabel->arg)); -+ /* db_database:{setattr relabelfrom} for older seclabel */ -+ checkDatabaseCommon(datOid, -+ SEPG_DB_DATABASE__SETATTR | -+ SEPG_DB_DATABASE__RELABELFROM, true); -+ /* db_database:{relabelto} for newer seclabel */ -+ sepgsqlClientHasPerms(datSid, -+ SEPG_CLASS_DB_DATABASE, -+ SEPG_DB_DATABASE__RELABELTO, -+ get_database_name(datOid), true); -+ return datSid.secid; -+ } -+ -+ void -+ sepgsqlCheckDatabaseAccess(Oid datOid) -+ { -+ if (!checkDatabaseCommon(datOid, SEPG_DB_DATABASE__ACCESS, false)) -+ ereport(FATAL, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: security policy violation"))); -+ } -+ -+ bool -+ sepgsqlCheckDatabaseSuperuser(void) -+ { -+ return checkDatabaseCommon(MyDatabaseId, -+ SEPG_DB_DATABASE__SUPERUSER, false); -+ } -+ -+ void -+ sepgsqlCheckDatabaseLoadModule(const char *filename) -+ { -+ HeapTuple tuple; -+ security_context_t filecon; -+ security_context_t dbcon; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ /* -+ * It assumes preloaded libraries are secure, -+ * because it can be set up using guc variable -+ * not any SQL statements. -+ */ -+ if (GetProcessingMode() == InitProcessing) -+ return; -+ -+ /* Get database context */ -+ tuple = SearchSysCache(DATABASEOID, -+ ObjectIdGetDatum(MyDatabaseId), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for database: %u", MyDatabaseId); -+ -+ dbcon = securityRawSecLabelOut(DatabaseRelationId, -+ HeapTupleGetSecid(tuple)); -+ ReleaseSysCache(tuple); -+ -+ /* Get library context */ -+ if (getfilecon_raw(filename, &filecon) < 0) -+ ereport(ERROR, -+ (errcode_for_file_access(), -+ errmsg("could not access file \"%s\": %m", filename))); -+ PG_TRY(); -+ { -+ sepgsqlComputePerms(dbcon, -+ filecon, -+ SEPG_CLASS_DB_DATABASE, -+ SEPG_DB_DATABASE__LOAD_MODULE, -+ filename, true); -+ } -+ PG_CATCH(); -+ { -+ freecon(filecon); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ freecon(filecon); -+ } -+ -+ /* -+ * ------------------------------------------------------------ -+ * Hooks corresponding to db_schema object class -+ * ------------------------------------------------------------ -+ */ -+ -+ Oid -+ sepgsqlCheckSchemaCreate(const char *nspName, DefElem *newLabel, bool isTemp) -+ { -+ sepgsql_sid_t nspSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return InvalidOid; -+ -+ if (!newLabel) -+ { -+ nspSid = (!isTemp -+ ? sepgsqlGetDefaultSchemaSecid(MyDatabaseId) -+ : sepgsqlGetDefaultSchemaTempSecid(MyDatabaseId)); -+ } -+ else -+ { -+ nspSid.relid = NamespaceRelationId; -+ nspSid.secid = securityTransSecLabelIn(nspSid.relid, -+ strVal(newLabel->arg)); -+ } -+ sepgsqlClientHasPerms(nspSid, -+ (!isTemp -+ ? SEPG_CLASS_DB_SCHEMA -+ : SEPG_CLASS_DB_SCHEMA_TEMP), -+ SEPG_DB_SCHEMA__CREATE, -+ nspName, true); -+ return nspSid.secid; -+ } -+ -+ static bool -+ checkSchemaCommon(Oid nspOid, uint32 required, bool abort) -+ { -+ HeapTuple tuple; -+ sepgsql_sid_t nspSid; -+ uint16 tclass; -+ const char *auname; -+ bool rc; -+ -+ if (!sepgsqlIsEnabled()) -+ return true; -+ -+ tuple = SearchSysCache(NAMESPACEOID, -+ ObjectIdGetDatum(nspOid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for namespace: %u", nspOid); -+ -+ nspSid = sepgsqlGetTupleContext(NamespaceRelationId, -+ tuple, &tclass); -+ -+ auname = NameStr(((Form_pg_namespace) GETSTRUCT(tuple))->nspname); -+ rc = sepgsqlClientHasPerms(nspSid, tclass, required, -+ auname, abort); -+ -+ ReleaseSysCache(tuple); -+ -+ return rc; -+ } -+ -+ void -+ sepgsqlCheckSchemaDrop(Oid nspOid) -+ { -+ checkSchemaCommon(nspOid, SEPG_DB_SCHEMA__DROP, true); -+ } -+ -+ void -+ sepgsqlCheckSchemaSetattr(Oid nspOid) -+ { -+ checkSchemaCommon(nspOid, SEPG_DB_SCHEMA__SETATTR, true); -+ } -+ -+ Oid -+ sepgsqlCheckSchemaRelabel(Oid nspOid, DefElem *newLabel) -+ { -+ sepgsql_sid_t nspSid; -+ -+ if (!sepgsqlIsEnabled()) -+ { -+ if (newLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux is disabled now"))); -+ return InvalidOid; -+ } -+ nspSid.relid = NamespaceRelationId; -+ nspSid.secid = securityTransSecLabelIn(nspSid.relid, -+ strVal(newLabel->arg)); -+ -+ /* db_schema:{setattr relabelfrom} for older seclabel */ -+ checkSchemaCommon(nspOid, -+ SEPG_DB_SCHEMA__SETATTR | -+ SEPG_DB_SCHEMA__RELABELFROM, true); -+ /* db_schema:{relabelto} for newer seclabel */ -+ sepgsqlClientHasPerms(nspSid, -+ !isAnyTempNamespace(nspOid) -+ ? SEPG_CLASS_DB_SCHEMA -+ : SEPG_CLASS_DB_SCHEMA_TEMP, -+ SEPG_DB_SCHEMA__RELABELTO, -+ get_namespace_name(nspOid), true); -+ return nspSid.secid; -+ } -+ -+ void -+ sepgsqlCheckSchemaAddName(Oid nspOid) -+ { -+ checkSchemaCommon(nspOid, SEPG_DB_SCHEMA__ADD_NAME, true); -+ } -+ -+ void -+ sepgsqlCheckSchemaRemoveName(Oid nspOid) -+ { -+ checkSchemaCommon(nspOid, SEPG_DB_SCHEMA__REMOVE_NAME, true); -+ } -+ -+ bool -+ sepgsqlCheckSchemaSearch(Oid nspOid, bool abort) -+ { -+ return checkSchemaCommon(nspOid, SEPG_DB_SCHEMA__SEARCH, abort); -+ } -+ -+ /* ------------------------------------------------------------ * -+ * Hooks corresponding to db_column object class -+ * ------------------------------------------------------------ */ -+ -+ /* -+ * NOTE: db_column:{create} is checked on sepgsqlCreateTableColumns() -+ * which is invoked on CREATE TABLE statement. -+ * The sepgsqlCheckColumnCreate() is called on the ALTER TABLE -+ * ... ADD COLUMN path. -+ */ -+ Oid -+ sepgsqlCheckColumnCreate(Oid table_oid, const char *attname, DefElem *newLabel) -+ { -+ sepgsql_sid_t attSid; -+ char relkind; -+ char auname[NAMEDATALEN * 2 + 3]; -+ -+ if (!sepgsqlIsEnabled()) -+ { -+ if (newLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux is disabled now"))); -+ return InvalidOid; -+ } -+ -+ relkind = get_rel_relkind(table_oid); -+ if (relkind != RELKIND_RELATION) -+ { -+ if (newLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("Unable to assign security label"))); -+ return InvalidOid; -+ } -+ -+ if (!newLabel) -+ attSid = sepgsqlGetDefaultColumnSecid(table_oid); -+ else -+ { -+ attSid.relid = AttributeRelationId; -+ attSid.secid = securityTransSecLabelIn(attSid.relid, -+ strVal(newLabel->arg)); -+ } -+ -+ sprintf(auname, "%s.%s", get_rel_name(table_oid), attname); -+ sepgsqlClientHasPerms(attSid, -+ SEPG_CLASS_DB_COLUMN, -+ SEPG_DB_COLUMN__CREATE, -+ auname, true); -+ return attSid.secid; -+ } -+ -+ static void -+ checkColumnCommon(Oid relOid, AttrNumber attno, uint32 required) -+ { -+ Form_pg_attribute attr; -+ sepgsql_sid_t attSid; -+ HeapTuple tuple; -+ uint16 tclass; -+ char auname[2 * NAMEDATALEN + 3]; -+ char relkind; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ relkind = get_rel_relkind(relOid); -+ if (relkind != RELKIND_RELATION) -+ return; -+ -+ tuple = SearchSysCache(ATTNUM, -+ ObjectIdGetDatum(relOid), -+ Int16GetDatum(attno), -+ 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for attribute %d of relation %u", -+ attno, relOid); -+ -+ attr = (Form_pg_attribute) GETSTRUCT(tuple); -+ if (!attr->attisdropped) -+ { -+ sprintf(auname, "%s.%s", -+ get_rel_name(relOid), -+ NameStr(attr->attname)); -+ attSid = sepgsqlGetTupleContext(AttributeRelationId, -+ tuple, &tclass); -+ sepgsqlClientHasPerms(attSid, tclass, required, -+ auname, true); -+ } -+ -+ ReleaseSysCache(tuple); -+ } -+ -+ void -+ sepgsqlCheckColumnDrop(Oid relOid, AttrNumber attno) -+ { -+ checkColumnCommon(relOid, attno, SEPG_DB_COLUMN__DROP); -+ } -+ -+ void -+ sepgsqlCheckColumnSetattr(Oid relOid, AttrNumber attno) -+ { -+ checkColumnCommon(relOid, attno, SEPG_DB_COLUMN__SETATTR); -+ } -+ -+ Oid -+ sepgsqlCheckColumnRelabel(Oid relOid, AttrNumber attno, DefElem *newLabel) -+ { -+ sepgsql_sid_t attSid; -+ char relkind; -+ -+ if (!sepgsqlIsEnabled()) -+ { -+ if (newLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux is disabled now"))); -+ return InvalidOid; -+ } -+ -+ relkind = get_rel_relkind(relOid); -+ if (relkind != RELKIND_RELATION) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s.%s\"", -+ get_rel_name(relOid), -+ get_attname(relOid, attno)))); -+ -+ attSid.relid = AttributeRelationId; -+ attSid.secid = securityTransSecLabelIn(attSid.relid, -+ strVal(newLabel->arg)); -+ -+ /* db_column:{setattr relabelfrom} for older seclabel */ -+ checkColumnCommon(relOid, attno, -+ SEPG_DB_COLUMN__SETATTR | -+ SEPG_DB_COLUMN__RELABELFROM); -+ -+ /* db_column:{relabelto} for newer seclabel */ -+ sepgsqlClientHasPerms(attSid, -+ SEPG_CLASS_DB_COLUMN, -+ SEPG_DB_COLUMN__RELABELTO, -+ get_attname(relOid, attno), true); -+ return attSid.secid; -+ } -+ -+ /* ------------------------------------------------------------ * -+ * Hooks corresponding to db_table object class -+ * ------------------------------------------------------------ */ -+ -+ /* -+ * NOTE: db_table/db_sequence:{create} permission is checked -+ * at sepgsqlCreateTableColumns() due to the reason -+ * for implementation. -+ * -+ * sepgsqlCheckTableReference -+ * checks db_table:{reference} and db_column:{reference} permission -+ * when the client tries to set up a foreign key constraint on the -+ * certain tables and columns. -+ */ -+ -+ static void -+ checkTableCommon(Oid table_oid, access_vector_t required) -+ { -+ HeapTuple tuple; -+ sepgsql_sid_t relSid; -+ uint16 tclass; -+ const char *auname; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ tuple = SearchSysCache(RELOID, -+ ObjectIdGetDatum(table_oid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for relation %u", table_oid); -+ -+ auname = NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname); -+ relSid = sepgsqlGetTupleContext(RelationRelationId, -+ tuple, &tclass); -+ sepgsqlClientHasPerms(relSid, tclass, required, -+ auname, true); -+ ReleaseSysCache(tuple); -+ } -+ -+ void -+ sepgsqlCheckTableDrop(Oid table_oid) -+ { -+ checkTableCommon(table_oid, SEPG_DB_TABLE__DROP); -+ } -+ -+ void -+ sepgsqlCheckTableSetattr(Oid table_oid) -+ { -+ checkTableCommon(table_oid, SEPG_DB_TABLE__SETATTR); -+ } -+ -+ Oid -+ sepgsqlCheckTableRelabel(Oid table_oid, DefElem *newLabel) -+ { -+ sepgsql_sid_t relSid; -+ char relkind; -+ -+ if (!sepgsqlIsEnabled()) -+ { -+ if (newLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux is disabled now"))); -+ return InvalidOid; -+ } -+ -+ relkind = get_rel_relkind(table_oid); -+ if (relkind != RELKIND_RELATION && relkind != RELKIND_SEQUENCE) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s\"", -+ get_rel_name(table_oid)))); -+ -+ relSid.relid = RelationRelationId; -+ relSid.secid = securityTransSecLabelIn(relSid.relid, -+ strVal(newLabel->arg)); -+ -+ /* db_table/db_sequence:{setattr relabelfrom} for older seclabel */ -+ checkTableCommon(table_oid, -+ SEPG_DB_TABLE__SETATTR | -+ SEPG_DB_TABLE__RELABELFROM); -+ -+ /* db_table/db_sequence:{relabelto} for newer seclabel */ -+ sepgsqlClientHasPerms(relSid, -+ (relkind == RELKIND_RELATION -+ ? SEPG_CLASS_DB_TABLE -+ : SEPG_CLASS_DB_SEQUENCE), -+ SEPG_DB_TABLE__RELABELTO, -+ get_rel_name(table_oid), true); -+ return relSid.secid; -+ } -+ -+ void -+ sepgsqlCheckTableLock(Oid table_oid) -+ { -+ checkTableCommon(table_oid, SEPG_DB_TABLE__LOCK); -+ } -+ -+ void -+ sepgsqlCheckTableTruncate(Relation rel) -+ { -+ HeapScanDesc scan; -+ HeapTuple tuple; -+ sepgsql_sid_t tupSid; -+ uint16 tclass; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* check db_table:{delete} permission */ -+ checkTableCommon(RelationGetRelid(rel), SEPG_DB_TABLE__DELETE); -+ -+ /* row-level access control is enabled? */ -+ if (!sepostgresql_row_level) -+ return; -+ -+ /* check db_tuple:{delete} permission */ -+ scan = heap_beginscan(rel, SnapshotNow, 0, NULL); -+ -+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL) -+ { -+ tupSid = sepgsqlGetTupleContext(RelationGetRelid(rel), -+ tuple, &tclass); -+ sepgsqlClientHasPerms(tupSid, -+ tclass, SEPG_DB_TUPLE__DELETE, -+ NULL, true); -+ } -+ heap_endscan(scan); -+ } -+ -+ void -+ sepgsqlCheckTableReference(Relation rel, int16 *attnums, int natts) -+ { -+ int i; -+ -+ checkTableCommon(RelationGetRelid(rel), SEPG_DB_TABLE__REFERENCE); -+ -+ for (i=0; i < natts; i++) -+ { -+ checkColumnCommon(RelationGetRelid(rel), -+ attnums[i], SEPG_DB_COLUMN__REFERENCE); -+ } -+ } -+ -+ /* ------------------------------------------------------------ * -+ * Hooks corresponding to db_sequence object class -+ * ------------------------------------------------------------ */ -+ void sepgsqlCheckSequenceGetValue(Oid seqOid) -+ { -+ checkTableCommon(seqOid, SEPG_DB_SEQUENCE__GET_VALUE); -+ } -+ -+ void sepgsqlCheckSequenceNextValue(Oid seqOid) -+ { -+ checkTableCommon(seqOid, SEPG_DB_SEQUENCE__NEXT_VALUE); -+ } -+ -+ void sepgsqlCheckSequenceSetValue(Oid seqOid) -+ { -+ checkTableCommon(seqOid, SEPG_DB_SEQUENCE__SET_VALUE); -+ } -+ -+ /* ------------------------------------------------------------ * -+ * Hooks corresponding to db_procedure object class -+ * ------------------------------------------------------------ */ -+ static bool -+ checkProcedureCommon(Oid procOid, uint32 required, bool abort) -+ { -+ sepgsql_sid_t proSid; -+ HeapTuple tuple; -+ uint16 tclass; -+ const char *auname; -+ bool rc; -+ -+ if (!sepgsqlIsEnabled()) -+ return true; -+ -+ tuple = SearchSysCache(PROCOID, -+ ObjectIdGetDatum(procOid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for procedure: %u", procOid); -+ -+ auname = NameStr(((Form_pg_proc) GETSTRUCT(tuple))->proname); -+ proSid = sepgsqlGetTupleContext(ProcedureRelationId, -+ tuple, &tclass); -+ rc = sepgsqlClientHasPerms(proSid, tclass, required, -+ auname, abort); -+ -+ ReleaseSysCache(tuple); -+ -+ return rc; -+ } -+ -+ Oid -+ sepgsqlCheckProcedureCreate(const char *procName, Oid procOid, -+ Oid procNsp, Oid procLang, DefElem *newLabel) -+ { -+ sepgsql_sid_t proSid; -+ HeapTuple tuple; -+ uint32 required; -+ -+ if (!sepgsqlIsEnabled()) -+ return InvalidOid; -+ -+ if (!OidIsValid(procOid)) -+ { -+ /* create a new function */ -+ required = SEPG_DB_PROCEDURE__CREATE; -+ if (!newLabel) -+ proSid = sepgsqlGetDefaultProcedureSecid(procNsp); -+ else -+ { -+ proSid.relid = ProcedureRelationId; -+ proSid.secid = securityTransSecLabelIn(proSid.relid, -+ strVal(newLabel->arg)); -+ } -+ } -+ else if (!newLabel) -+ { -+ /* replace an existing function, without any label */ -+ required = SEPG_DB_PROCEDURE__SETATTR; -+ tuple = SearchSysCache(PROCOID, -+ ObjectIdGetDatum(procOid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for procedure: %u", procOid); -+ -+ proSid = sepgsqlGetTupleContext(ProcedureRelationId, -+ tuple, NULL); -+ ReleaseSysCache(tuple); -+ } -+ else -+ { -+ /* replace an existing function, with relabeling */ -+ checkProcedureCommon(procOid, -+ SEPG_DB_PROCEDURE__SETATTR | -+ SEPG_DB_PROCEDURE__RELABELFROM, true); -+ -+ required = SEPG_DB_PROCEDURE__RELABELTO; -+ proSid.relid = ProcedureRelationId; -+ proSid.secid = securityTransSecLabelIn(proSid.relid, -+ strVal(newLabel->arg)); -+ } -+ -+ /* Procedural language is trusted? */ -+ tuple = SearchSysCache(LANGOID, -+ ObjectIdGetDatum(procLang), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for procedural langugage: %u", procLang); -+ -+ if (!((Form_pg_language) GETSTRUCT(tuple))->lanpltrusted) -+ required |= SEPG_DB_PROCEDURE__UNTRUSTED; -+ -+ ReleaseSysCache(tuple); -+ -+ /* check it */ -+ sepgsqlClientHasPerms(proSid, -+ SEPG_CLASS_DB_PROCEDURE, required, -+ procName, true); -+ -+ return proSid.secid; -+ } -+ -+ void -+ sepgsqlCheckProcedureDrop(Oid procOid) -+ { -+ checkProcedureCommon(procOid, SEPG_DB_PROCEDURE__DROP, true); -+ } -+ -+ void -+ sepgsqlCheckProcedureSetattr(Oid procOid) -+ { -+ checkProcedureCommon(procOid, SEPG_DB_PROCEDURE__SETATTR, true); -+ } -+ -+ Oid -+ sepgsqlCheckProcedureRelabel(Oid procOid, DefElem *newLabel) -+ { -+ sepgsql_sid_t proSid; -+ -+ if (!sepgsqlIsEnabled()) -+ { -+ if (newLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux is disabled now"))); -+ return InvalidOid; -+ } -+ -+ proSid.relid = ProcedureRelationId; -+ proSid.secid = securityTransSecLabelIn(proSid.relid, -+ strVal(newLabel->arg)); -+ -+ /* db_procedure:{setattr relabelfrom} for older seclabel */ -+ checkProcedureCommon(procOid, -+ SEPG_DB_PROCEDURE__SETATTR | -+ SEPG_DB_PROCEDURE__RELABELFROM, true); -+ /* db_procedure:{relabelto} for newer seclabel */ -+ sepgsqlClientHasPerms(proSid, -+ SEPG_CLASS_DB_PROCEDURE, -+ SEPG_DB_PROCEDURE__RELABELTO, -+ get_func_name(procOid), true); -+ return proSid.secid; -+ } -+ -+ void -+ sepgsqlCheckProcedureExecute(Oid procOid) -+ { -+ checkProcedureCommon(procOid, SEPG_DB_PROCEDURE__EXECUTE, true); -+ } -+ -+ /* -+ * sepgsqlCheckProcedureInstall -+ * -+ * It should be checked when a procedure is installed as a part of system -+ * internal stuff. -+ */ -+ void -+ sepgsqlCheckProcedureInstall(Oid procOid) -+ { -+ if (OidIsValid(procOid)) -+ checkProcedureCommon(procOid, SEPG_DB_PROCEDURE__INSTALL, true); -+ } -+ -+ /* -+ * sepgsqlHintProcedureInlined -+ * -+ * It provides a hint whether the given sql procedure can be inlined, or not. -+ */ -+ bool -+ sepgsqlHintProcedureInlined(HeapTuple protup) -+ { -+ security_context_t newcon; -+ sepgsql_sid_t proSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return true; -+ -+ if (!checkProcedureCommon(HeapTupleGetOid(protup), -+ SEPG_DB_PROCEDURE__EXECUTE, false)) -+ return false; -+ /* -+ * If the security context of client is unchange -+ * before or after invocation of the functions, -+ * it is not a trusted procedure, so it can be -+ * inlined due to performance purpose. -+ */ -+ proSid = sepgsqlGetTupleContext(ProcedureRelationId, -+ protup, NULL); -+ -+ newcon = sepgsqlClientCreateLabel(proSid, SEPG_CLASS_PROCESS); -+ -+ if (strcmp(sepgsqlGetClientLabel(), newcon) == 0) -+ return true; -+ -+ return false; -+ } -+ -+ /* -+ * sepgsqlCheckProcedureEntrypoint -+ * checks whether the given function call causes domain transition, -+ * or not. If it needs a domain transition, it injects a wrapper -+ * function to invoke it under new domain. -+ */ -+ struct TrustedProcedureCache -+ { -+ FmgrInfo flinfo; -+ char newcon[1]; -+ }; -+ -+ static Datum -+ sepgsqlTrustedProcedure(PG_FUNCTION_ARGS) -+ { -+ struct TrustedProcedureCache *tcache; -+ security_context_t save_context; -+ FmgrInfo *save_flinfo; -+ Datum result; -+ -+ tcache = fcinfo->flinfo->fn_extra; -+ Assert(tcache != NULL); -+ -+ save_context = sepgsqlSwitchClient(tcache->newcon); -+ save_flinfo = fcinfo->flinfo; -+ fcinfo->flinfo = &tcache->flinfo; -+ -+ PG_TRY(); -+ { -+ result = FunctionCallInvoke(fcinfo); -+ } -+ PG_CATCH(); -+ { -+ sepgsqlSwitchClient(save_context); -+ fcinfo->flinfo = save_flinfo; -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ sepgsqlSwitchClient(save_context); -+ fcinfo->flinfo = save_flinfo; -+ -+ return result; -+ } -+ -+ void -+ sepgsqlCheckProcedureEntrypoint(FmgrInfo *flinfo, HeapTuple protup) -+ { -+ struct TrustedProcedureCache *tcache; -+ security_context_t newcon; -+ sepgsql_sid_t proSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ proSid = sepgsqlGetTupleContext(ProcedureRelationId, -+ protup, NULL); -+ -+ newcon = sepgsqlClientCreateLabel(proSid, SEPG_CLASS_PROCESS); -+ -+ /* Do nothing, if it is not a trusted procedure */ -+ if (strcmp(newcon, sepgsqlGetClientLabel()) == 0) -+ return; -+ -+ /* check db_procedure:{entrypoint} */ -+ sepgsqlClientHasPerms(proSid, -+ SEPG_CLASS_DB_PROCEDURE, -+ SEPG_DB_PROCEDURE__ENTRYPOINT, -+ NULL, true); -+ -+ /* check process:{transition} */ -+ sepgsqlComputePerms(sepgsqlGetClientLabel(), -+ newcon, -+ SEPG_CLASS_PROCESS, -+ SEPG_PROCESS__TRANSITION, -+ NULL, true); -+ -+ /* setup trusted procedure */ -+ tcache = MemoryContextAllocZero(flinfo->fn_mcxt, -+ sizeof(*tcache) + strlen(newcon)); -+ memcpy(&tcache->flinfo, flinfo, sizeof(*flinfo)); -+ strcpy(tcache->newcon, newcon); -+ flinfo->fn_addr = sepgsqlTrustedProcedure; -+ flinfo->fn_extra = tcache; -+ } -+ -+ /* -+ * sepgsqlCheckBlobCreate -+ * assigns a default security label and checks db_blob:{create} -+ */ -+ void -+ sepgsqlCheckBlobCreate(Relation rel, HeapTuple lotup) -+ { -+ sepgsql_sid_t loSid; -+ Oid relid = RelationGetRelid(rel); -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* set a default security context */ -+ sepgsqlSetDefaultSecid(rel, lotup); -+ -+ loSid = sepgsqlGetTupleContext(relid, lotup, NULL); -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__CREATE, -+ NULL, true); -+ } -+ -+ /* -+ * sepgsqlCheckBlobDrop -+ * checks db_blob:{drop} permission -+ */ -+ void -+ sepgsqlCheckBlobDrop(Relation rel, HeapTuple lotup) -+ { -+ sepgsql_sid_t loSid; -+ Oid relid = RelationGetRelid(rel); -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ loSid = sepgsqlGetTupleContext(relid, lotup, NULL); -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__DROP, -+ NULL, true); -+ } -+ -+ /* -+ * sepgsqlCheckBlobRead -+ * checks db_blob:{read} permission -+ */ -+ void -+ sepgsqlCheckBlobRead(LargeObjectDesc *lobj) -+ { -+ sepgsql_sid_t loSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ loSid.relid = LargeObjectRelationId; -+ loSid.secid = lobj->secid; -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__READ, -+ NULL, true); -+ } -+ -+ /* -+ * sepgsqlCheckBlobWrite -+ * check db_blob:{write} permission -+ */ -+ void -+ sepgsqlCheckBlobWrite(LargeObjectDesc *lobj) -+ { -+ sepgsql_sid_t loSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ loSid.relid = LargeObjectRelationId; -+ loSid.secid = lobj->secid; -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__WRITE, -+ NULL, true); -+ } -+ -+ /* -+ * sepgsqlCheckBlobGetattr -+ * check db_blob:{getattr} permission -+ */ -+ void -+ sepgsqlCheckBlobGetattr(HeapTuple tuple) -+ { -+ sepgsql_sid_t loSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ loSid.relid = LargeObjectRelationId; -+ loSid.secid = HeapTupleGetSecid(tuple); -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__GETATTR, -+ NULL, true); -+ } -+ -+ /* -+ * sepgsqlCheckBlobSetattr -+ * check db_blob:{setattr} permission -+ */ -+ void -+ sepgsqlCheckBlobSetattr(HeapTuple tuple) -+ { -+ sepgsql_sid_t loSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ loSid.relid = LargeObjectRelationId; -+ loSid.secid = HeapTupleGetSecid(tuple); -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__SETATTR, -+ NULL, true); -+ } -+ -+ /* -+ * sepgsqlCheckBlobExport -+ * check db_blob:{read export} and file:{write} permission -+ */ -+ void -+ sepgsqlCheckBlobExport(LargeObjectDesc *lobj, -+ int fdesc, const char *filename) -+ { -+ sepgsql_sid_t loSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* db_blob:{read export} */ -+ loSid.relid = LargeObjectRelationId; -+ loSid.secid = lobj->secid; -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__READ | SEPG_DB_BLOB__EXPORT, -+ NULL, true); -+ /* file:{write} */ -+ sepgsqlCheckFileWrite(fdesc, filename); -+ } -+ -+ /* -+ * sepgsqlCheckBlobImport -+ * check db_blob:{write import} and file:{read} permission -+ */ -+ void -+ sepgsqlCheckBlobImport(LargeObjectDesc *lobj, -+ int fdesc, const char *filename) -+ { -+ sepgsql_sid_t loSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ /* db_blob:{write import} */ -+ loSid.relid = LargeObjectRelationId; -+ loSid.secid = lobj->secid; -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__WRITE | SEPG_DB_BLOB__IMPORT, -+ NULL, true); -+ /* file:{read} */ -+ sepgsqlCheckFileRead(fdesc, filename); -+ } -+ -+ /* -+ * sepgsqlCheckBlobRelabel -+ * check db_blob:{setattr relabelfrom relabelto} -+ */ -+ void -+ sepgsqlCheckBlobRelabel(HeapTuple oldtup, HeapTuple newtup) -+ { -+ sepgsql_sid_t loSid; -+ access_vector_t required = SEPG_DB_BLOB__SETATTR; -+ -+ if (HeapTupleGetSecid(oldtup) != HeapTupleGetSecid(newtup)) -+ required |= SEPG_DB_BLOB__RELABELFROM; -+ -+ /* db_blob:{setattr relabelfrom} */ -+ loSid = sepgsqlGetTupleContext(LargeObjectRelationId, oldtup, NULL); -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ required, -+ NULL, true); -+ -+ if ((required & SEPG_DB_BLOB__RELABELFROM) == 0) -+ return; -+ -+ /* db_blob:{relabelto} */ -+ loSid = sepgsqlGetTupleContext(LargeObjectRelationId, newtup, NULL); -+ sepgsqlClientHasPerms(loSid, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_DB_BLOB__RELABELTO, -+ NULL, true); -+ } -+ -+ /* -+ * sepgsqlCheckSysobjCreate -+ * -+ * It checks db_tuple:{insert} for system catalog -+ */ -+ Oid -+ sepgsqlCheckSysobjCreate(Oid relid, const char *auditName) -+ { -+ sepgsql_sid_t sysSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return InvalidOid; -+ -+ sysSid = sepgsqlGetDefaultTupleSecid(relid); -+ -+ sepgsqlClientHasPerms(sysSid, -+ SEPG_CLASS_DB_TUPLE, -+ SEPG_DB_TUPLE__INSERT, -+ auditName, true); -+ -+ return sysSid.secid; -+ } -+ -+ /* -+ * sepgsqlCheckSysobjGetattr -+ * -+ * It checks db_tuple:{select} for system catalog -+ */ -+ void -+ sepgsqlCheckSysobjGetattr(Oid relid, Oid secid, const char *auditName) -+ { -+ sepgsql_sid_t sysSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ sysSid.relid = relid; -+ sysSid.secid = secid; -+ sepgsqlClientHasPerms(sysSid, -+ SEPG_CLASS_DB_TUPLE, -+ SEPG_DB_TUPLE__SELECT, -+ auditName, true); -+ } -+ -+ /* -+ * sepgsqlCheckSysobjSetattr -+ * -+ * It checks db_tuple:{update} for system catalog -+ */ -+ void -+ sepgsqlCheckSysobjSetattr(Oid relid, Oid secid, const char *auditName) -+ { -+ sepgsql_sid_t sysSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ sysSid.relid = relid; -+ sysSid.secid = secid; -+ sepgsqlClientHasPerms(sysSid, -+ SEPG_CLASS_DB_TUPLE, -+ SEPG_DB_TUPLE__UPDATE, -+ auditName, true); -+ } -+ -+ /* -+ * sepgsqlCheckSysobjDrop -+ * It checks db_xxx:{drop} permission on the given opaque -+ * object, invoked from deleteOneObject() -+ */ -+ void -+ sepgsqlCheckSysobjDrop(const ObjectAddress *object) -+ { -+ switch (object->classId) -+ { -+ case NamespaceRelationId: -+ sepgsqlCheckSchemaDrop(object->objectId); -+ break; -+ -+ case RelationRelationId: -+ if (!object->objectSubId) -+ sepgsqlCheckTableDrop(object->objectId); -+ else -+ sepgsqlCheckColumnDrop(object->objectId, object->objectSubId); -+ break; -+ -+ case ProcedureRelationId: -+ sepgsqlCheckProcedureDrop(object->objectId); -+ break; -+ -+ default: -+ /* do nothing in this version */ -+ break; -+ } -+ } -+ -+ /* -+ * sepgsqlCheckFileRead -+ * sepgsqlCheckFileWrite -+ * check file:{read} or file:{write} permission on the given file, -+ * and raises an error if violated. -+ */ -+ static void -+ checkFileCommon(int fdesc, const char *filename, access_vector_t perms) -+ { -+ security_context_t context; -+ security_class_t tclass; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ tclass = sepgsqlFileObjectClass(fdesc); -+ -+ if (fgetfilecon_raw(fdesc, &context) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not get context of %s", filename))); -+ PG_TRY(); -+ { -+ sepgsqlComputePerms(sepgsqlGetClientLabel(), -+ context, -+ tclass, -+ perms, -+ filename, true); -+ } -+ PG_CATCH(); -+ { -+ freecon(context); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ freecon(context); -+ } -+ -+ void -+ sepgsqlCheckFileRead(int fdesc, const char *filename) -+ { -+ checkFileCommon(fdesc, filename, SEPG_FILE__READ); -+ } -+ -+ void -+ sepgsqlCheckFileWrite(int fdesc, const char *filename) -+ { -+ checkFileCommon(fdesc, filename, SEPG_FILE__WRITE); -+ } -diff -Nrpc base/src/backend/security/sepgsql/label.c sepgsql/src/backend/security/sepgsql/label.c -*** base/src/backend/security/sepgsql/label.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/label.c Thu Sep 10 15:18:03 2009 -*************** -*** 0 **** ---- 1,1151 ---- -+ /* -+ * src/backend/security/sepgsql/label.c -+ * SE-PostgreSQL security label management -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "access/sysattr.h" -+ #include "access/xact.h" -+ #include "catalog/catalog.h" -+ #include "catalog/pg_constraint.h" -+ #include "catalog/heap.h" -+ #include "catalog/indexing.h" -+ #include "catalog/namespace.h" -+ #include "catalog/pg_aggregate.h" -+ #include "catalog/pg_amop.h" -+ #include "catalog/pg_amproc.h" -+ #include "catalog/pg_attrdef.h" -+ #include "catalog/pg_attribute.h" -+ #include "catalog/pg_auth_members.h" -+ #include "catalog/pg_authid.h" -+ #include "catalog/pg_cast.h" -+ #include "catalog/pg_class.h" -+ #include "catalog/pg_conversion.h" -+ #include "catalog/pg_database.h" -+ #include "catalog/pg_description.h" -+ #include "catalog/pg_enum.h" -+ #include "catalog/pg_foreign_data_wrapper.h" -+ #include "catalog/pg_foreign_server.h" -+ #include "catalog/pg_inherits.h" -+ #include "catalog/pg_language.h" -+ #include "catalog/pg_largeobject.h" -+ #include "catalog/pg_namespace.h" -+ #include "catalog/pg_opclass.h" -+ #include "catalog/pg_operator.h" -+ #include "catalog/pg_opfamily.h" -+ #include "catalog/pg_proc.h" -+ #include "catalog/pg_rewrite.h" -+ #include "catalog/pg_security.h" -+ #include "catalog/pg_shdescription.h" -+ #include "catalog/pg_statistic.h" -+ #include "catalog/pg_tablespace.h" -+ #include "catalog/pg_trigger.h" -+ #include "catalog/pg_ts_config.h" -+ #include "catalog/pg_ts_dict.h" -+ #include "catalog/pg_ts_parser.h" -+ #include "catalog/pg_ts_template.h" -+ #include "catalog/pg_type.h" -+ #include "catalog/pg_user_mapping.h" -+ #include "miscadmin.h" -+ #include "nodes/makefuncs.h" -+ #include "security/sepgsql.h" -+ #include "storage/fd.h" -+ #include "utils/fmgroids.h" -+ #include "utils/lsyscache.h" -+ #include "utils/syscache.h" -+ #include "utils/tqual.h" -+ -+ /* GUC: to turn on/off row level controls in SE-PostgreSQL */ -+ bool sepostgresql_row_level; -+ -+ /* GUC parameter to turn on/off mcstrans */ -+ bool sepostgresql_use_mcstrans; -+ -+ /* -+ * sepgsqlTupleDescHasSecid -+ * -+ * returns a hint whether we should allocate a field to store -+ * security label on the given relation, or not. -+ */ -+ bool -+ sepgsqlTupleDescHasSecid(Oid relid, char relkind) -+ { -+ if (!sepgsqlIsEnabled()) -+ return false; -+ -+ if (!OidIsValid(relid)) -+ return sepostgresql_row_level; /* Target of SELECT INTO */ -+ -+ /* These system catalogs always have its secid */ -+ if (relid == DatabaseRelationId || -+ relid == NamespaceRelationId || -+ relid == RelationRelationId || -+ relid == AttributeRelationId || -+ relid == ProcedureRelationId) -+ return true; -+ -+ /* These system catalogs are an external attributes */ -+ if (relid == AggregateRelationId || -+ relid == AccessMethodOperatorRelationId || -+ relid == AccessMethodProcedureRelationId || -+ relid == AttrDefaultRelationId || -+ relid == AuthMemRelationId || -+ relid == ConstraintRelationId || -+ relid == DescriptionRelationId || -+ relid == EnumRelationId || -+ relid == IndexRelationId || -+ relid == InheritsRelationId || -+ relid == RewriteRelationId || -+ relid == SecurityRelationId || -+ relid == SharedDescriptionRelationId || -+ relid == StatisticRelationId || -+ relid == TriggerRelationId) -+ return false; -+ -+ return sepostgresql_row_level; -+ } -+ -+ /* -+ * sepgsqlGetDefaultDatabaseSecid -+ * It returns the default security label of a database object. -+ */ -+ sepgsql_sid_t -+ sepgsqlGetDefaultDatabaseSecid(void) -+ { -+ security_context_t seclabel; -+ sepgsql_sid_t sid; -+ char filename[MAXPGPATH]; -+ char buffer[1024], *policy_type, *tmp; -+ FILE *filp; -+ -+ /* -+ * NOTE: when the security policy provide a configuration to -+ * specify the default security context of database object, -+ * we apply is as a default one. -+ * If the configuration is unavailable, we compute the -+ * default security context without any parent object. -+ */ -+ if (selinux_getpolicytype(&policy_type) < 0) -+ goto fallback; -+ -+ snprintf(filename, sizeof(filename), -+ "%s%s/contexts/sepgsql_context", selinux_path(), policy_type); -+ filp = AllocateFile(filename, PG_BINARY_R); -+ if (!filp) -+ goto fallback; -+ -+ while (fgets(buffer, sizeof(buffer), filp) != NULL) -+ { -+ tmp = strchr(buffer, '#'); -+ if (tmp) -+ *tmp = '\0'; -+ -+ seclabel = strtok(buffer, " \t\n\r"); -+ if (!seclabel) -+ continue; -+ -+ /* An entry found */ -+ FreeFile(filp); -+ -+ sid.relid = DatabaseRelationId; -+ sid.secid = securityTransSecLabelIn(sid.relid, seclabel); -+ -+ return sid; -+ } -+ FreeFile(filp); -+ -+ fallback: -+ seclabel = sepgsqlComputeCreate(sepgsqlGetClientLabel(), -+ sepgsqlGetClientLabel(), -+ SEPG_CLASS_DB_DATABASE); -+ sid.relid = DatabaseRelationId; -+ sid.secid = securityTransSecLabelIn(sid.relid, seclabel); -+ -+ return sid; -+ } -+ -+ static sepgsql_sid_t -+ defaultSecidWithDatabase(Oid relid, Oid datoid, uint16 tclass) -+ { -+ HeapTuple tuple; -+ sepgsql_sid_t datsid; -+ -+ if (IsBootstrapProcessingMode()) -+ { -+ static sepgsql_sid_t cached = { InvalidOid, InvalidOid }; -+ -+ if (!SidIsValid(cached)) -+ cached = sepgsqlGetDefaultDatabaseSecid(); -+ datsid = cached; -+ } -+ else -+ { -+ tuple = SearchSysCache(DATABASEOID, -+ ObjectIdGetDatum(datoid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for database: %u", datoid); -+ datsid.relid = DatabaseRelationId; -+ datsid.secid = HeapTupleGetSecid(tuple); -+ ReleaseSysCache(tuple); -+ } -+ -+ return sepgsqlClientCreateSecid(datsid, tclass, relid); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultSchemaSecid(Oid database_oid) -+ { -+ return defaultSecidWithDatabase(NamespaceRelationId, -+ database_oid, -+ SEPG_CLASS_DB_SCHEMA); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultSchemaTempSecid(Oid database_oid) -+ { -+ return defaultSecidWithDatabase(NamespaceRelationId, -+ database_oid, -+ SEPG_CLASS_DB_SCHEMA_TEMP); -+ } -+ -+ static sepgsql_sid_t -+ defaultSecidWithSchema(Oid relid, Oid nspoid, uint16 tclass) -+ { -+ HeapTuple tuple; -+ sepgsql_sid_t nspsid; -+ -+ if (IsBootstrapProcessingMode()) -+ { -+ static sepgsql_sid_t cached = { InvalidOid, InvalidOid }; -+ -+ if (!SidIsValid(cached)) -+ cached = sepgsqlGetDefaultSchemaSecid(MyDatabaseId); -+ -+ nspsid = sepgsqlGetDefaultSchemaSecid(MyDatabaseId); -+ } -+ else -+ { -+ tuple = SearchSysCache(NAMESPACEOID, -+ ObjectIdGetDatum(nspoid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for namespace: %u", nspoid); -+ nspsid.relid = NamespaceRelationId; -+ nspsid.secid = HeapTupleGetSecid(tuple); -+ ReleaseSysCache(tuple); -+ } -+ -+ return sepgsqlClientCreateSecid(nspsid, tclass, relid); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultTableSecid(Oid namespace_oid) -+ { -+ return defaultSecidWithSchema(RelationRelationId, -+ namespace_oid, -+ SEPG_CLASS_DB_TABLE); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultSequenceSecid(Oid namespace_oid) -+ { -+ return defaultSecidWithSchema(RelationRelationId, -+ namespace_oid, -+ SEPG_CLASS_DB_SEQUENCE); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultProcedureSecid(Oid namespace_oid) -+ { -+ return defaultSecidWithSchema(ProcedureRelationId, -+ namespace_oid, -+ SEPG_CLASS_DB_PROCEDURE); -+ } -+ -+ static sepgsql_sid_t -+ defaultSecidWithTable(Oid relid, Oid tbloid, security_class_t tclass) -+ { -+ HeapTuple tuple; -+ sepgsql_sid_t relsid; -+ -+ if (IsBootstrapProcessingMode() -+ && (tbloid == TypeRelationId || -+ tbloid == ProcedureRelationId || -+ tbloid == AttributeRelationId || -+ tbloid == RelationRelationId)) -+ { -+ static sepgsql_sid_t cached = { InvalidOid, InvalidOid }; -+ -+ if (!SidIsValid(cached)) -+ cached = sepgsqlGetDefaultTableSecid(PG_CATALOG_NAMESPACE); -+ -+ relsid = cached; -+ } -+ else -+ { -+ tuple = SearchSysCache(RELOID, -+ ObjectIdGetDatum(tbloid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for relation: %u", tbloid); -+ relsid.relid = RelationRelationId; -+ relsid.secid = HeapTupleGetSecid(tuple); -+ ReleaseSysCache(tuple); -+ } -+ -+ return sepgsqlClientCreateSecid(relsid, tclass, relid); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultColumnSecid(Oid table_oid) -+ { -+ return defaultSecidWithTable(AttributeRelationId, -+ table_oid, -+ SEPG_CLASS_DB_COLUMN); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultTupleSecid(Oid table_oid) -+ { -+ return defaultSecidWithTable(table_oid, -+ table_oid, -+ SEPG_CLASS_DB_TUPLE); -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetDefaultBlobSecid(Oid database_oid) -+ { -+ return defaultSecidWithDatabase(LargeObjectRelationId, -+ MyDatabaseId, -+ SEPG_CLASS_DB_BLOB); -+ } -+ -+ void -+ sepgsqlSetDefaultSecid(Relation rel, HeapTuple tuple) -+ { -+ Oid relOid = RelationGetRelid(rel); -+ Oid nspOid, tblOid; -+ sepgsql_sid_t newSid; -+ -+ if (!sepgsqlIsEnabled()) -+ return; -+ -+ if (!HeapTupleHasSecid(tuple)) -+ return; -+ -+ switch (sepgsqlTupleObjectClass(relOid, tuple)) -+ { -+ case SEPG_CLASS_DB_DATABASE: -+ newSid = sepgsqlGetDefaultDatabaseSecid(); -+ break; -+ case SEPG_CLASS_DB_SCHEMA: -+ newSid = sepgsqlGetDefaultSchemaSecid(MyDatabaseId); -+ break; -+ case SEPG_CLASS_DB_SCHEMA_TEMP: -+ newSid = sepgsqlGetDefaultSchemaTempSecid(MyDatabaseId); -+ break; -+ case SEPG_CLASS_DB_TABLE: -+ nspOid = ((Form_pg_class) GETSTRUCT(tuple))->relnamespace; -+ newSid = sepgsqlGetDefaultTableSecid(nspOid); -+ break; -+ case SEPG_CLASS_DB_SEQUENCE: -+ nspOid = ((Form_pg_class) GETSTRUCT(tuple))->relnamespace; -+ newSid = sepgsqlGetDefaultSequenceSecid(nspOid); -+ break; -+ case SEPG_CLASS_DB_PROCEDURE: -+ nspOid = ((Form_pg_proc) GETSTRUCT(tuple))->pronamespace; -+ newSid = sepgsqlGetDefaultProcedureSecid(nspOid); -+ break; -+ case SEPG_CLASS_DB_COLUMN: -+ tblOid = ((Form_pg_attribute) GETSTRUCT(tuple))->attrelid; -+ newSid = sepgsqlGetDefaultColumnSecid(tblOid); -+ break; -+ case SEPG_CLASS_DB_BLOB: -+ newSid = sepgsqlGetDefaultBlobSecid(MyDatabaseId); -+ break; -+ default: -+ newSid = sepgsqlGetDefaultTupleSecid(relOid); -+ break; -+ } -+ -+ Assert(newSid.relid == relOid); -+ HeapTupleSetSecid(tuple, newSid.secid); -+ } -+ -+ /* -+ * sepgsqlCreateTableColumn -+ * It returns an array of security identifier for the new table -+ * and columns to be assigned. The corresponding security labels -+ * are already checked for db_table/db_sequence/db_column:{create} -+ * permission. -+ * In the default labeling rule, a column inherits the security -+ * label of its table, but we cannot refer it using system caches, -+ * because the command counter is not incremented under the -+ * heap_create_with_catalog(). Thus, we need to compute and check -+ * them prior to the actual creation of table and columns. -+ */ -+ Oid * -+ sepgsqlCreateTableColumns(CreateStmt *stmt, -+ const char *relname, Oid namespace_oid, -+ TupleDesc tupdesc, char relkind) -+ { -+ sepgsql_sid_t relsid; -+ Oid *secLabels = NULL; -+ int index; -+ -+ if (!sepgsqlIsEnabled()) -+ return NULL; -+ -+ /* -+ * In the current version, we don't assign any certain security -+ * labels on relations except for tables/sequences. -+ */ -+ if (relkind != RELKIND_RELATION && relkind != RELKIND_SEQUENCE) -+ return NULL; -+ -+ /* -+ * The secLabels array stores security identifiers to be assigned -+ * on the new table and columns. -+ * -+ * secLabels[0] is security identifier of the table. -+ * secLabels[attnum - FirstLowInvalidHeapAttributeNumber] -+ * is security identifier of columns. -+ */ -+ secLabels = palloc0(sizeof(Oid) * (tupdesc->natts -+ - FirstLowInvalidHeapAttributeNumber)); -+ -+ /* -+ * SELinux checks db_table/db_sequence:{create} -+ */ -+ switch (relkind) -+ { -+ case RELKIND_RELATION: -+ if (!stmt || !stmt->secLabel) -+ relsid = sepgsqlGetDefaultTableSecid(namespace_oid); -+ else -+ { -+ relsid.relid = RelationRelationId; -+ relsid.secid = securityTransSecLabelIn(relsid.relid, -+ strVal(((DefElem *)stmt->secLabel)->arg)); -+ } -+ sepgsqlClientHasPerms(relsid, -+ SEPG_CLASS_DB_TABLE, -+ SEPG_DB_TABLE__CREATE, -+ relname, true); -+ break; -+ -+ case RELKIND_SEQUENCE: -+ if (!stmt || !stmt->secLabel) -+ relsid = sepgsqlGetDefaultSequenceSecid(namespace_oid); -+ else -+ { -+ relsid.relid = RelationRelationId; -+ relsid.secid = securityTransSecLabelIn(relsid.relid, -+ strVal(((DefElem *)stmt->secLabel)->arg)); -+ } -+ sepgsqlClientHasPerms(relsid, -+ SEPG_CLASS_DB_SEQUENCE, -+ SEPG_DB_SEQUENCE__CREATE, -+ relname, true); -+ break; -+ -+ default: -+ if (stmt && stmt->secLabel) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s\"", relname))); -+ relsid = sepgsqlGetDefaultTupleSecid(RelationRelationId); -+ break; -+ } -+ /* table's security identifier to be assigned on */ -+ secLabels[0] = relsid.secid; -+ -+ /* -+ * SELinux checks db_column:{create} -+ */ -+ for (index = FirstLowInvalidHeapAttributeNumber + 1; -+ index < tupdesc->natts; -+ index++) -+ { -+ Form_pg_attribute attr; -+ sepgsql_sid_t attsid = { InvalidOid, InvalidOid }; -+ char attname[NAMEDATALEN * 2 + 3]; -+ -+ /* skip unnecessary attributes */ -+ if (index < 0 && (relkind == RELKIND_VIEW || -+ relkind == RELKIND_COMPOSITE_TYPE)) -+ continue; -+ if (index == ObjectIdAttributeNumber && !tupdesc->tdhasoid) -+ continue; -+ -+ if (index < 0) -+ attr = SystemAttributeDefinition(index, tupdesc->tdhasoid); -+ else -+ attr = tupdesc->attrs[index]; -+ -+ /* Is there any given security label? */ -+ if (stmt) -+ { -+ ListCell *l; -+ -+ foreach (l, stmt->tableElts) -+ { -+ ColumnDef *colDef = lfirst(l); -+ -+ if (colDef->secLabel && -+ strcmp(colDef->colname, NameStr(attr->attname)) == 0) -+ { -+ attsid.relid = AttributeRelationId; -+ attsid.secid = securityTransSecLabelIn(attsid.relid, -+ strVal(((DefElem *)colDef->secLabel)->arg)); -+ break; -+ } -+ } -+ } -+ -+ switch (relkind) -+ { -+ case RELKIND_RELATION: -+ /* compute default column's label if necessary */ -+ if (!SidIsValid(attsid)) -+ attsid = sepgsqlClientCreateSecid(relsid, -+ SEPG_CLASS_DB_COLUMN, -+ AttributeRelationId); -+ -+ sprintf(attname, "%s.%s", relname, NameStr(attr->attname)); -+ sepgsqlClientHasPerms(attsid, -+ SEPG_CLASS_DB_COLUMN, -+ SEPG_DB_COLUMN__CREATE, -+ attname, true); -+ break; -+ -+ default: -+ if (SidIsValid(attsid)) -+ ereport(ERROR, -+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), -+ errmsg("Unable to set security label on \"%s.%s\"", -+ relname, NameStr(attr->attname)))); -+ attsid = sepgsqlGetDefaultTupleSecid(AttributeRelationId); -+ break; -+ } -+ /* column's security identifier to be assigend on */ -+ secLabels[index - FirstLowInvalidHeapAttributeNumber] = attsid.secid; -+ } -+ return secLabels; -+ } -+ -+ /* -+ * sepgsqlCopyTableColumns -+ * It returns an array of security identifier of table and columns -+ * to be copied on make_new_heap(). It actually create a new temporary -+ * relation and insert all the tuples within original one into the -+ * temporary one, but swap_relation_files() swaps their file nodes. -+ * Thus, there are no changes from the viewpoint of users. -+ * SE-PostgreSQL also does not check and change anything. It simply -+ * copies security identifier of the source relation to the destination -+ * relation. -+ */ -+ Oid * -+ sepgsqlCopyTableColumns(Relation source) -+ { -+ HeapTuple tuple; -+ Oid *secLabels; -+ Oid relid = RelationGetRelid(source); -+ int index; -+ -+ if (!sepgsqlIsEnabled()) -+ return PointerGetDatum(NULL); -+ -+ /* see the comment at sepgsqlCreateTableColumn*/ -+ secLabels = palloc0(sizeof(Oid) * (RelationGetDescr(source)->natts -+ - FirstLowInvalidHeapAttributeNumber)); -+ -+ /* copy table's security identifier */ -+ tuple = SearchSysCache(RELOID, -+ ObjectIdGetDatum(relid), -+ 0, 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ elog(ERROR, "cache lookup failed for relation \"%s\"", -+ RelationGetRelationName(source)); -+ -+ secLabels[0] = HeapTupleGetSecid(tuple); -+ -+ ReleaseSysCache(tuple); -+ -+ /* copy column's security identifier */ -+ for (index = FirstLowInvalidHeapAttributeNumber + 1; -+ index < RelationGetDescr(source)->natts; -+ index++) -+ { -+ Form_pg_attribute attr; -+ -+ if (index < 0) -+ attr = SystemAttributeDefinition(index, true); -+ else -+ attr = RelationGetDescr(source)->attrs[index]; -+ -+ tuple = SearchSysCache(ATTNUM, -+ ObjectIdGetDatum(relid), -+ Int16GetDatum(attr->attnum), -+ 0, 0); -+ if (!HeapTupleIsValid(tuple)) -+ continue; -+ -+ secLabels[index - FirstLowInvalidHeapAttributeNumber] -+ = HeapTupleGetSecid(tuple); -+ -+ ReleaseSysCache(tuple); -+ } -+ -+ return secLabels; -+ } -+ -+ /* -+ * sepgsqlGetSysobjContext -+ * -+ * It returns a pair of relid/secid for the given OID. -+ */ -+ static sepgsql_sid_t -+ getSysobjContextDirect(Oid classOid, Oid indexOid, Oid objectId, uint16 *tclass) -+ { -+ sepgsql_sid_t sid = { InvalidOid, InvalidOid }; -+ Relation rel; -+ HeapTuple tup; -+ ScanKeyData skey; -+ SysScanDesc scan; -+ -+ rel = heap_open(CastRelationId, AccessShareLock); -+ -+ ScanKeyInit(&skey, -+ ObjectIdAttributeNumber, -+ BTEqualStrategyNumber, F_OIDEQ, -+ ObjectIdGetDatum(objectId)); -+ -+ scan = systable_beginscan(rel, CastOidIndexId, true, -+ SnapshotNow, 1, &skey); -+ tup = systable_getnext(scan); -+ -+ if (HeapTupleIsValid(tup)) -+ sid = sepgsqlGetTupleContext(classOid, tup, tclass); -+ -+ systable_endscan(scan); -+ -+ heap_close(rel, AccessShareLock); -+ -+ return sid; -+ } -+ -+ sepgsql_sid_t -+ sepgsqlGetSysobjContext(Oid classOid, Oid objectId, int32 objsubId, uint16 *tclass) -+ { -+ sepgsql_sid_t sid = { InvalidOid, InvalidOid }; -+ HeapTuple tup = NULL; -+ -+ switch (classOid) -+ { -+ case AccessMethodRelationId: -+ tup = SearchSysCache(AMOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case AccessMethodOperatorRelationId: -+ return getSysobjContextDirect(AccessMethodOperatorRelationId, -+ AccessMethodOperatorOidIndexId, -+ objectId, tclass); -+ -+ case AccessMethodProcedureRelationId: -+ return getSysobjContextDirect(AccessMethodProcedureRelationId, -+ AccessMethodProcedureOidIndexId, -+ objectId, tclass); -+ -+ case AuthIdRelationId: -+ tup = SearchSysCache(AUTHOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case CastRelationId: -+ return getSysobjContextDirect(CastRelationId, -+ CastOidIndexId, -+ objectId, tclass); -+ -+ case ConstraintRelationId: -+ tup = SearchSysCache(CONSTROID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case ConversionRelationId: -+ tup = SearchSysCache(CONVOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case DatabaseRelationId: -+ tup = SearchSysCache(DATABASEOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case ForeignDataWrapperRelationId: -+ tup = SearchSysCache(FOREIGNDATAWRAPPEROID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case ForeignServerRelationId: -+ tup = SearchSysCache(FOREIGNSERVEROID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case LanguageRelationId: -+ tup = SearchSysCache(LANGOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case LargeObjectRelationId: -+ /* to be replaced by LargeObjectMetaRelationId! */ -+ { -+ Relation rel; -+ ScanKeyData skey; -+ SysScanDesc scan; -+ -+ rel = heap_open(LargeObjectRelationId, AccessShareLock); -+ -+ ScanKeyInit(&skey, -+ Anum_pg_largeobject_loid, -+ BTEqualStrategyNumber, F_OIDEQ, -+ ObjectIdGetDatum(objectId)); -+ -+ scan = systable_beginscan(rel, LargeObjectLOidPNIndexId, -+ true, SnapshotNow, 1, &skey); -+ -+ tup = systable_getnext(scan); -+ -+ if (HeapTupleIsValid(tup)) -+ sid = sepgsqlGetTupleContext(classOid, tup, tclass); -+ -+ systable_endscan(scan); -+ -+ heap_close(rel, AccessShareLock); -+ } -+ return sid; -+ -+ case RelationRelationId: -+ if (objsubId != 0) -+ { -+ classOid = AttributeRelationId; -+ tup = SearchSysCache(ATTNUM, -+ ObjectIdGetDatum(objectId), -+ Int16GetDatum(objsubId), -+ 0, 0); -+ } -+ else -+ { -+ classOid = RelationRelationId; -+ tup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ } -+ break; -+ -+ case NamespaceRelationId: -+ tup = SearchSysCache(NAMESPACEOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case OperatorClassRelationId: -+ tup = SearchSysCache(CLAOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case OperatorFamilyRelationId: -+ tup = SearchSysCache(OPFAMILYOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case OperatorRelationId: -+ tup = SearchSysCache(OPEROID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case ProcedureRelationId: -+ tup = SearchSysCache(PROCOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case RewriteRelationId: -+ return getSysobjContextDirect(RewriteRelationId, -+ RewriteOidIndexId, -+ objectId, tclass); -+ -+ case TableSpaceRelationId: -+ return getSysobjContextDirect(TableSpaceRelationId, -+ TablespaceOidIndexId, -+ objectId, tclass); -+ -+ case TriggerRelationId: -+ return getSysobjContextDirect(TriggerRelationId, -+ TriggerOidIndexId, -+ objectId, tclass); -+ -+ case TSConfigRelationId: -+ tup = SearchSysCache(TSCONFIGOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case TSDictionaryRelationId: -+ tup = SearchSysCache(TSDICTOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case TSParserRelationId: -+ tup = SearchSysCache(TSPARSEROID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case TSTemplateRelationId: -+ tup = SearchSysCache(TSTEMPLATEOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case TypeRelationId: -+ tup = SearchSysCache(TYPEOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ case UserMappingRelationId: -+ tup = SearchSysCache(USERMAPPINGOID, -+ ObjectIdGetDatum(objectId), -+ 0, 0, 0); -+ break; -+ -+ default: -+ elog(ERROR, "unexpected class OID: %u", classOid); -+ break; -+ } -+ -+ if (HeapTupleIsValid(tup)) -+ { -+ sid = sepgsqlGetTupleContext(classOid, tup, tclass); -+ ReleaseSysCache(tup); -+ } -+ -+ return sid; -+ } -+ -+ /* -+ * sepgsqlGetTupleContext -+ * -+ * It returns a pair of relid/secid for the given HeapTuple. -+ * A few system catalogs is handled as an attribute of other -+ * system objects. -+ * E.g) pg_attrdef is an attribute of a certain pg_attribute -+ */ -+ sepgsql_sid_t -+ sepgsqlGetTupleContext(Oid tableOid, HeapTuple tuple, uint16 *tclass) -+ { -+ sepgsql_sid_t sid = { InvalidOid, InvalidOid }; -+ HeapTuple exttup; -+ Oid extid; -+ Oid extcls; -+ AttrNumber extsub; -+ -+ if (tclass) -+ *tclass = SEPG_CLASS_DB_TUPLE; -+ -+ switch (tableOid) -+ { -+ case AggregateRelationId: -+ sid.relid = ProcedureRelationId; -+ extid = ((Form_pg_aggregate) GETSTRUCT(tuple))->aggfnoid; -+ exttup = SearchSysCache(PROCOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case AccessMethodOperatorRelationId: -+ sid.relid = OperatorFamilyRelationId; -+ extid = ((Form_pg_amop) GETSTRUCT(tuple))->amopfamily; -+ exttup = SearchSysCache(OPFAMILYOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case AccessMethodProcedureRelationId: -+ sid.relid = OperatorFamilyRelationId; -+ extid = ((Form_pg_amproc) GETSTRUCT(tuple))->amprocfamily; -+ exttup = SearchSysCache(OPFAMILYOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case AttrDefaultRelationId: -+ sid.relid = AttributeRelationId; -+ extid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid; -+ extsub = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum; -+ exttup = SearchSysCache(ATTNUM, -+ ObjectIdGetDatum(extid), -+ Int16GetDatum(extsub), -+ 0, 0); -+ break; -+ -+ case AuthMemRelationId: -+ sid.relid = AuthIdRelationId; -+ extid = ((Form_pg_auth_members) GETSTRUCT(tuple))->roleid; -+ exttup = SearchSysCache(AUTHOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case ConstraintRelationId: -+ /* CHECK constraint is an attribute of the relation */ -+ extid = ((Form_pg_constraint) GETSTRUCT(tuple))->conrelid; -+ if (OidIsValid(extid)) -+ { -+ sid.relid = RelationRelationId; -+ exttup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ } -+ /* DOMAIN constraint is an attribute of the domain type */ -+ extid = ((Form_pg_constraint) GETSTRUCT(tuple))->contypid; -+ if (OidIsValid(extid)) -+ { -+ sid.relid = TypeRelationId; -+ exttup = SearchSysCache(TYPEOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ } -+ /* Database's context for global assertion */ -+ sid.relid = DatabaseRelationId; -+ exttup = SearchSysCache(DATABASEOID, -+ ObjectIdGetDatum(MyDatabaseId), -+ 0, 0, 0); -+ break; -+ -+ case DescriptionRelationId: -+ /* recursive call */ -+ extid = ((Form_pg_description) GETSTRUCT(tuple))->objoid; -+ extcls = ((Form_pg_description) GETSTRUCT(tuple))->classoid; -+ return sepgsqlGetSysobjContext(extcls, extid, 0, tclass); -+ -+ case EnumRelationId: -+ sid.relid = TypeRelationId; -+ extid = ((Form_pg_enum) GETSTRUCT(tuple))->enumtypid; -+ exttup = SearchSysCache(TYPEOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case IndexRelationId: -+ sid.relid = RelationRelationId; -+ extid = ((Form_pg_index) GETSTRUCT(tuple))->indexrelid; -+ exttup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case InheritsRelationId: -+ sid.relid = RelationRelationId; -+ extid = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid; -+ exttup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case RewriteRelationId: -+ sid.relid = RelationRelationId; -+ extid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class; -+ exttup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ case SharedDescriptionRelationId: -+ /* recursive invocation */ -+ extid = ((Form_pg_shdescription) GETSTRUCT(tuple))->objoid; -+ extcls = ((Form_pg_shdescription) GETSTRUCT(tuple))->classoid; -+ return sepgsqlGetSysobjContext(extcls, extid, 0, tclass); -+ -+ case StatisticRelationId: -+ sid.relid = AttributeRelationId; -+ extid = ((Form_pg_statistic) GETSTRUCT(tuple))->starelid; -+ extsub = ((Form_pg_statistic) GETSTRUCT(tuple))->staattnum; -+ exttup = SearchSysCache(ATTNUM, -+ ObjectIdGetDatum(extid), -+ Int16GetDatum(extsub), -+ 0, 0); -+ break; -+ -+ case TriggerRelationId: -+ sid.relid = RelationRelationId; -+ extid = ((Form_pg_trigger) GETSTRUCT(tuple))->tgrelid; -+ exttup = SearchSysCache(RELOID, -+ ObjectIdGetDatum(extid), -+ 0, 0, 0); -+ break; -+ -+ default: -+ exttup = tuple; -+ sid.relid = tableOid; -+ break; -+ } -+ -+ if (HeapTupleIsValid(exttup)) -+ { -+ sid.secid = HeapTupleGetSecid(exttup); -+ -+ if (tclass) -+ *tclass = sepgsqlTupleObjectClass(sid.relid, exttup); -+ -+ if (exttup != tuple) -+ ReleaseSysCache(exttup); -+ } -+ return sid; -+ } -+ -+ /* -+ * sepgsqlRawSecLabelIn -+ * correctness checks for the given security context -+ */ -+ char * -+ sepgsqlRawSecLabelIn(char *seclabel) -+ { -+ if (!sepgsqlIsEnabled()) -+ return seclabel; -+ -+ if (!seclabel || security_check_context_raw(seclabel) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("Invalid security context: \"%s\"", seclabel))); -+ -+ return seclabel; -+ } -+ -+ /* -+ * sepgsqlRawSecLabelOut -+ * correctness checks for the given security context, -+ * and replace it if invalid security context -+ */ -+ char * -+ sepgsqlRawSecLabelOut(char *seclabel) -+ { -+ if (!sepgsqlIsEnabled()) -+ return seclabel; -+ -+ if (!seclabel || security_check_context_raw(seclabel) < 0) -+ { -+ security_context_t unlabeledcon; -+ -+ if (security_get_initial_context_raw("unlabeled", -+ &unlabeledcon) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("Unabled to get unlabeled security context"))); -+ PG_TRY(); -+ { -+ seclabel = pstrdup(unlabeledcon); -+ } -+ PG_CATCH(); -+ { -+ freecon(unlabeledcon); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ freecon(unlabeledcon); -+ } -+ return seclabel; -+ } -+ -+ /* -+ * sepgsqlTransSecLabelIn -+ * sepgsqlTransSecLabelOut -+ * translation between human-readable and raw format -+ */ -+ char * -+ sepgsqlTransSecLabelIn(char *seclabel) -+ { -+ security_context_t rawlabel; -+ security_context_t result; -+ -+ if (!sepgsqlIsEnabled() || -+ !sepostgresql_use_mcstrans) -+ return seclabel; -+ -+ if (selinux_trans_to_raw_context(seclabel, &rawlabel) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: failed to translate \"%s\"", seclabel))); -+ PG_TRY(); -+ { -+ result = pstrdup(rawlabel); -+ } -+ PG_CATCH(); -+ { -+ freecon(rawlabel); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ freecon(rawlabel); -+ -+ return result; -+ } -+ -+ char * -+ sepgsqlTransSecLabelOut(char *seclabel) -+ { -+ security_context_t translabel; -+ security_context_t result; -+ -+ if (!sepgsqlIsEnabled() || -+ !sepostgresql_use_mcstrans) -+ return seclabel; -+ -+ if (selinux_raw_to_trans_context(seclabel, &translabel) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: failed to translate \"%s\"", seclabel))); -+ PG_TRY(); -+ { -+ result = pstrdup(translabel); -+ } -+ PG_CATCH(); -+ { -+ freecon(translabel); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ freecon(translabel); -+ -+ return result; -+ } -+ -+ char * -+ sepgsqlSysattSecLabelOut(Oid relid, HeapTuple tuple) -+ { -+ sepgsql_sid_t sid; -+ -+ sid = sepgsqlGetTupleContext(relid, tuple, NULL); -+ -+ return securityTransSecLabelOut(sid.relid, sid.secid); -+ } -diff -Nrpc base/src/backend/security/sepgsql/misc.c sepgsql/src/backend/security/sepgsql/misc.c -*** base/src/backend/security/sepgsql/misc.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/misc.c Sun Aug 23 23:05:48 2009 -*************** -*** 0 **** ---- 1,304 ---- -+ /* -+ * src/backend/security/sepgsql/misc.c -+ * Miscellaneous facilities in SE-PostgreSQL -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ #include "libpq/libpq-be.h" -+ #include "miscadmin.h" -+ #include "security/sepgsql.h" -+ #include "utils/builtins.h" -+ -+ static security_context_t clientLabel = NULL; -+ static security_context_t serverLabel = NULL; -+ -+ security_context_t -+ sepgsqlGetServerLabel(void) -+ { -+ if (!serverLabel) -+ { -+ if (getcon_raw(&serverLabel) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not get server label"))); -+ } -+ return serverLabel; -+ } -+ -+ security_context_t -+ sepgsqlGetClientLabel(void) -+ { -+ if (!clientLabel) -+ { -+ /* -+ * When the process is not invoked as a backend of client, -+ * it works as a server process and as a client process -+ * in same time. -+ */ -+ if (!MyProcPort) -+ return sepgsqlGetServerLabel(); -+ -+ /* -+ * SELinux provides getpeercon(3) which enables to obtain -+ * the security context of peer process. -+ * If MyProcPort->sock is unix domain socket, no special -+ * configuration is necessary. If it is tcp/ip socket, -+ * labeled IPsec or fallback context to be configured. -+ */ -+ if (getpeercon_raw(MyProcPort->sock, &clientLabel) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not obtain client label"))); -+ } -+ -+ return clientLabel; -+ } -+ -+ security_context_t -+ sepgsqlSwitchClient(security_context_t new_client) -+ { -+ char *old_client = sepgsqlGetClientLabel(); -+ -+ clientLabel = new_client; -+ -+ PG_TRY(); -+ { -+ sepgsqlAvcSwitchClient(clientLabel); -+ } -+ PG_CATCH(); -+ { -+ clientLabel = old_client; -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ -+ return old_client; -+ } -+ -+ /* -+ * sepgsqlIsEnabled() -+ * -+ * returns the state of SE-PostgreSQL whether enabled, or not. -+ * When functions under src/backend/utils/ are invoked, they have to -+ * be checked on the head. -+ * This status is decided with two factors. The one is GUC parameter -+ * of "sepostgresql=on/off", and the other is is_selinux_enabled(). -+ * Both of them have to be true, when SE-PostgreSQL is activated. -+ */ -+ bool sepostgresql_is_enabled; /* default is false */ -+ -+ bool -+ sepgsqlIsEnabled(void) -+ { -+ static int enabled = -1; /* unchecked */ -+ -+ if (!sepostgresql_is_enabled) -+ return false; -+ -+ if (enabled < 0) -+ enabled = is_selinux_enabled(); -+ -+ return enabled > 0 ? true : false; -+ } -+ -+ /* -+ * SE-PostgreSQL specific functions -+ */ -+ Datum -+ sepgsql_getcon(PG_FUNCTION_ARGS) -+ { -+ security_context_t context; -+ -+ if (!sepgsqlIsEnabled()) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: disabled now"))); -+ -+ context = sepgsqlGetClientLabel(); -+ context = sepgsqlTransSecLabelOut(context); -+ return CStringGetTextDatum(context); -+ } -+ -+ Datum -+ sepgsql_server_getcon(PG_FUNCTION_ARGS) -+ { -+ security_context_t context; -+ -+ if (!sepgsqlIsEnabled()) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: disabled now"))); -+ -+ context = sepgsqlGetServerLabel(); -+ context = sepgsqlTransSecLabelOut(context); -+ return CStringGetTextDatum(context); -+ } -+ -+ /* -+ * sepgsql_(get|set)_(user|role|type|range) -+ * get/set a component of security context. -+ */ -+ static void -+ parse_security_context(security_context_t context, -+ char **user, char **role, char **type, char **range) -+ { -+ security_context_t raw_context; -+ char *tok; -+ -+ if (!sepgsqlIsEnabled()) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: disabled now"))); -+ -+ if (selinux_trans_to_raw_context(context, &raw_context) < 0) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not translate mls label: %s", context))); -+ -+ PG_TRY(); -+ { -+ tok = strtok(raw_context, ":"); -+ if (user) -+ *user = (!tok ? NULL : pstrdup(tok)); -+ -+ tok = strtok(NULL, ":"); -+ if (role) -+ *role = (!tok ? NULL : pstrdup(tok)); -+ -+ tok = strtok(NULL, ":"); -+ if (type) -+ *type = (!tok ? NULL : pstrdup(tok)); -+ -+ tok = strtok(NULL, "\0"); -+ if (range) -+ *range = (!tok ? NULL : pstrdup(tok)); -+ } -+ PG_CATCH(); -+ { -+ freecon(raw_context); -+ PG_RE_THROW(); -+ } -+ PG_END_TRY(); -+ freecon(raw_context); -+ } -+ -+ Datum -+ sepgsql_get_user(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *user; -+ -+ parse_security_context(context, &user, NULL, NULL, NULL); -+ if (!user) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not extract user of \"%s\"", context))); -+ -+ PG_RETURN_TEXT_P(CStringGetTextDatum(user)); -+ } -+ -+ Datum -+ sepgsql_get_role(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *role; -+ -+ parse_security_context(context, NULL, &role, NULL, NULL); -+ if (!role) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not extract role of \"%s\"", context))); -+ -+ PG_RETURN_TEXT_P(CStringGetTextDatum(role)); -+ } -+ -+ Datum -+ sepgsql_get_type(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *type; -+ -+ parse_security_context(context, NULL, NULL, &type, NULL); -+ if (!type) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not extract type of \"%s\"", context))); -+ -+ PG_RETURN_TEXT_P(CStringGetTextDatum(type)); -+ } -+ -+ Datum -+ sepgsql_get_range(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *range; -+ -+ parse_security_context(context, NULL, NULL, NULL, &range); -+ if (!range) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: could not extract range of \"%s\"", context))); -+ -+ PG_RETURN_TEXT_P(CStringGetTextDatum(range)); -+ } -+ -+ static Datum -+ sepgsql_set_common(char *context, char *user, char *role, char *type, char *range) -+ { -+ StringInfoData newcon; -+ -+ parse_security_context(context, -+ !user ? &user : NULL, -+ !role ? &role : NULL, -+ !type ? &type : NULL, -+ !range ? &range : NULL); -+ if (!user || !role || !type) -+ ereport(ERROR, -+ (errcode(ERRCODE_SELINUX_ERROR), -+ errmsg("SELinux: invalid security context: \"%s\"", context))); -+ -+ initStringInfo(&newcon); -+ appendStringInfo(&newcon, "%s:%s:%s", user, role, type); -+ if (range) -+ appendStringInfo(&newcon, ":%s", range); -+ -+ return CStringGetTextDatum(sepgsqlTransSecLabelOut(newcon.data)); -+ } -+ -+ Datum -+ sepgsql_set_user(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *user = TextDatumGetCString(PG_GETARG_TEXT_P(1)); -+ -+ return sepgsql_set_common(context, user, NULL, NULL, NULL); -+ } -+ -+ Datum -+ sepgsql_set_role(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *role = TextDatumGetCString(PG_GETARG_TEXT_P(1)); -+ -+ return sepgsql_set_common(context, NULL, role, NULL, NULL); -+ } -+ -+ Datum -+ sepgsql_set_type(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *type = TextDatumGetCString(PG_GETARG_TEXT_P(1)); -+ -+ return sepgsql_set_common(context, NULL, NULL, type, NULL); -+ } -+ -+ Datum -+ sepgsql_set_range(PG_FUNCTION_ARGS) -+ { -+ security_context_t context = TextDatumGetCString(PG_GETARG_TEXT_P(0)); -+ char *range = TextDatumGetCString(PG_GETARG_TEXT_P(1)); -+ -+ return sepgsql_set_common(context, NULL, NULL, NULL, range); -+ } -diff -Nrpc base/src/backend/security/sepgsql/perms.c sepgsql/src/backend/security/sepgsql/perms.c -*** base/src/backend/security/sepgsql/perms.c Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/perms.c Sun Sep 6 19:31:39 2009 -*************** -*** 0 **** ---- 1,464 ---- -+ /* -+ * src/backend/utils/sepgsql/perms.c -+ * SE-PostgreSQL permission checks -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #include "postgres.h" -+ -+ #include "catalog/pg_database.h" -+ #include "catalog/pg_proc.h" -+ #include "catalog/pg_largeobject.h" -+ #include "catalog/pg_namespace.h" -+ #include "catalog/pg_type.h" -+ #include "miscadmin.h" -+ #include "security/sepgsql.h" -+ #include "utils/lsyscache.h" -+ -+ /* -+ * Dynamic object class/permissions mapping -+ * -+ * SELinux exports the list of object classes and permissions at -+ * /selinux/class. The libselinux provides an interface to translate -+ * between their names and codes. -+ */ -+ static struct -+ { -+ const char *class_name; -+ security_class_t class_code; -+ struct -+ { -+ const char *perm_name; -+ access_vector_t perm_code; -+ } av[sizeof(access_vector_t) * 8]; -+ } selinux_catalog[] = { -+ { -+ "process", SEPG_CLASS_PROCESS, -+ { -+ {"translation", SEPG_PROCESS__TRANSITION }, -+ {NULL, 0} -+ } -+ }, -+ { -+ "file", SEPG_CLASS_FILE, -+ { -+ {"read", SEPG_FILE__READ }, -+ {"write", SEPG_FILE__WRITE }, -+ {NULL, 0} -+ } -+ }, -+ { -+ "dir", SEPG_CLASS_DIR, -+ { -+ {"read", SEPG_DIR__READ }, -+ {"write", SEPG_DIR__WRITE }, -+ {NULL,0} -+ } -+ }, -+ { -+ "lnk_file", SEPG_CLASS_LNK_FILE, -+ { -+ {"read", SEPG_LNK_FILE__READ }, -+ {"write", SEPG_LNK_FILE__WRITE }, -+ {NULL,0} -+ } -+ }, -+ { -+ "chr_file", SEPG_CLASS_CHR_FILE, -+ { -+ {"read", SEPG_CHR_FILE__READ }, -+ {"write", SEPG_CHR_FILE__WRITE }, -+ {NULL,0} -+ } -+ }, -+ { -+ "blk_file", SEPG_CLASS_BLK_FILE, -+ { -+ {"read", SEPG_BLK_FILE__READ }, -+ {"write", SEPG_BLK_FILE__WRITE }, -+ {NULL,0} -+ } -+ }, -+ { -+ "sock_file", SEPG_CLASS_SOCK_FILE, -+ { -+ {"read", SEPG_SOCK_FILE__READ }, -+ {"write", SEPG_SOCK_FILE__WRITE }, -+ {NULL,0} -+ } -+ }, -+ { -+ "fifo_file", SEPG_CLASS_FIFO_FILE, -+ { -+ {"read", SEPG_FIFO_FILE__READ }, -+ {"write", SEPG_FIFO_FILE__WRITE }, -+ {NULL, 0UL } -+ } -+ }, -+ { -+ "db_database", SEPG_CLASS_DB_DATABASE, -+ { -+ { "create", SEPG_DB_DATABASE__CREATE }, -+ { "drop", SEPG_DB_DATABASE__DROP }, -+ { "getattr", SEPG_DB_DATABASE__GETATTR }, -+ { "setattr", SEPG_DB_DATABASE__SETATTR }, -+ { "relabelfrom", SEPG_DB_DATABASE__RELABELFROM }, -+ { "relabelto", SEPG_DB_DATABASE__RELABELTO }, -+ { "access", SEPG_DB_DATABASE__ACCESS }, -+ { "install_module", SEPG_DB_DATABASE__INSTALL_MODULE }, -+ { "load_module", SEPG_DB_DATABASE__LOAD_MODULE }, -+ { "superuser", SEPG_DB_DATABASE__SUPERUSER }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_schema", SEPG_CLASS_DB_SCHEMA, -+ { -+ { "create", SEPG_DB_SCHEMA__CREATE }, -+ { "drop", SEPG_DB_SCHEMA__DROP }, -+ { "getattr", SEPG_DB_SCHEMA__GETATTR }, -+ { "setattr", SEPG_DB_SCHEMA__SETATTR }, -+ { "relabelfrom", SEPG_DB_SCHEMA__RELABELFROM }, -+ { "relabelto", SEPG_DB_SCHEMA__RELABELTO }, -+ { "search", SEPG_DB_SCHEMA__SEARCH }, -+ { "add_name", SEPG_DB_SCHEMA__ADD_NAME }, -+ { "remove_name", SEPG_DB_SCHEMA__REMOVE_NAME }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_schema_temp", SEPG_CLASS_DB_SCHEMA_TEMP, -+ { -+ { "create", SEPG_DB_SCHEMA_TEMP__CREATE }, -+ { "drop", SEPG_DB_SCHEMA_TEMP__DROP}, -+ { "getattr", SEPG_DB_SCHEMA_TEMP__GETATTR }, -+ { "setattr", SEPG_DB_SCHEMA_TEMP__SETATTR }, -+ { "relabelfrom", SEPG_DB_SCHEMA_TEMP__RELABELFROM }, -+ { "relabelto", SEPG_DB_SCHEMA_TEMP__RELABELTO }, -+ { "search", SEPG_DB_SCHEMA_TEMP__SEARCH }, -+ { "add_name", SEPG_DB_SCHEMA_TEMP__ADD_NAME }, -+ { "remove_name", SEPG_DB_SCHEMA_TEMP__REMOVE_NAME }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_table", SEPG_CLASS_DB_TABLE, -+ { -+ { "create", SEPG_DB_TABLE__CREATE }, -+ { "drop", SEPG_DB_TABLE__DROP }, -+ { "getattr", SEPG_DB_TABLE__GETATTR }, -+ { "setattr", SEPG_DB_TABLE__SETATTR }, -+ { "relabelfrom", SEPG_DB_TABLE__RELABELFROM }, -+ { "relabelto", SEPG_DB_TABLE__RELABELTO }, -+ { "select", SEPG_DB_TABLE__SELECT }, -+ { "update", SEPG_DB_TABLE__UPDATE }, -+ { "insert", SEPG_DB_TABLE__INSERT }, -+ { "delete", SEPG_DB_TABLE__DELETE }, -+ { "lock", SEPG_DB_TABLE__LOCK }, -+ { "reference", SEPG_DB_TABLE__REFERENCE }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_sequence", SEPG_CLASS_DB_SEQUENCE, -+ { -+ { "create", SEPG_DB_SEQUENCE__CREATE }, -+ { "drop", SEPG_DB_SEQUENCE__DROP }, -+ { "getattr", SEPG_DB_SEQUENCE__GETATTR }, -+ { "setattr", SEPG_DB_SEQUENCE__SETATTR }, -+ { "relabelfrom", SEPG_DB_SEQUENCE__RELABELFROM }, -+ { "relabelto", SEPG_DB_SEQUENCE__RELABELTO }, -+ { "get_value", SEPG_DB_SEQUENCE__GET_VALUE }, -+ { "next_value", SEPG_DB_SEQUENCE__NEXT_VALUE }, -+ { "set_value", SEPG_DB_SEQUENCE__SET_VALUE }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_procedure", SEPG_CLASS_DB_PROCEDURE, -+ { -+ { "create", SEPG_DB_PROCEDURE__CREATE }, -+ { "drop", SEPG_DB_PROCEDURE__DROP }, -+ { "getattr", SEPG_DB_PROCEDURE__GETATTR }, -+ { "setattr", SEPG_DB_PROCEDURE__SETATTR }, -+ { "relabelfrom", SEPG_DB_PROCEDURE__RELABELFROM }, -+ { "relabelto", SEPG_DB_PROCEDURE__RELABELTO }, -+ { "execute", SEPG_DB_PROCEDURE__EXECUTE }, -+ { "entrypoint", SEPG_DB_PROCEDURE__ENTRYPOINT }, -+ { "install", SEPG_DB_PROCEDURE__INSTALL }, -+ { "untrusted", SEPG_DB_PROCEDURE__UNTRUSTED }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_column", SEPG_CLASS_DB_COLUMN, -+ { -+ { "create", SEPG_DB_COLUMN__CREATE }, -+ { "drop", SEPG_DB_COLUMN__DROP }, -+ { "getattr", SEPG_DB_COLUMN__GETATTR }, -+ { "setattr", SEPG_DB_COLUMN__SETATTR }, -+ { "relabelfrom", SEPG_DB_COLUMN__RELABELFROM }, -+ { "relabelto", SEPG_DB_COLUMN__RELABELTO }, -+ { "select", SEPG_DB_COLUMN__SELECT }, -+ { "update", SEPG_DB_COLUMN__UPDATE }, -+ { "insert", SEPG_DB_COLUMN__INSERT }, -+ { "reference", SEPG_DB_COLUMN__REFERENCE }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_tuple", SEPG_CLASS_DB_TUPLE, -+ { -+ { "relabelfrom", SEPG_DB_TUPLE__RELABELFROM }, -+ { "relabelto", SEPG_DB_TUPLE__RELABELTO }, -+ { "select", SEPG_DB_TUPLE__SELECT }, -+ { "update", SEPG_DB_TUPLE__UPDATE }, -+ { "insert", SEPG_DB_TUPLE__INSERT }, -+ { "delete", SEPG_DB_TUPLE__DELETE }, -+ { NULL, 0UL }, -+ } -+ }, -+ { -+ "db_blob", SEPG_CLASS_DB_BLOB, -+ { -+ { "create", SEPG_DB_BLOB__CREATE }, -+ { "drop", SEPG_DB_BLOB__DROP }, -+ { "getattr", SEPG_DB_BLOB__GETATTR }, -+ { "setattr", SEPG_DB_BLOB__SETATTR }, -+ { "relabelfrom", SEPG_DB_BLOB__RELABELFROM }, -+ { "relabelto", SEPG_DB_BLOB__RELABELTO }, -+ { "read", SEPG_DB_BLOB__READ }, -+ { "write", SEPG_DB_BLOB__WRITE }, -+ { "import", SEPG_DB_BLOB__IMPORT }, -+ { "export", SEPG_DB_BLOB__EXPORT }, -+ { NULL, 0UL }, -+ } -+ } -+ }; -+ -+ /* -+ * sepgsqlTransToExternalClass -+ * It translate the given class code (defined as SEPGCLASS_(class)) into -+ * external code which is necessary to communicate in-kernel SELinux -+ */ -+ extern security_class_t -+ sepgsqlTransToExternalClass(security_class_t tclass) -+ { -+ Assert(tclass < SEPG_CLASS_MAX); -+ -+ return string_to_security_class(selinux_catalog[tclass].class_name); -+ } -+ -+ /* -+ * sepgsqlTransToInternalPerms -+ * It translate the given permission masks into internal representation -+ * defined as SEPG_(class)_(permission). -+ */ -+ extern void -+ sepgsqlTransToInternalPerms(security_class_t tclass, struct av_decision *avd) -+ { -+ security_class_t tclass_ex; -+ struct av_decision i_avd; -+ int i, deny_unknown; -+ -+ Assert(tclass < SEPG_CLASS_MAX); -+ -+ memset(&i_avd, 0, sizeof(struct av_decision)); -+ -+ deny_unknown = security_deny_unknown(); -+ -+ tclass_ex = sepgsqlTransToExternalClass(tclass); -+ for (i=0; selinux_catalog[tclass].av[i].perm_name; i++) -+ { -+ const char *perm_name = selinux_catalog[tclass].av[i].perm_name; -+ access_vector_t perm_code = selinux_catalog[tclass].av[i].perm_code; -+ access_vector_t perm_code_ex; -+ -+ perm_code_ex = string_to_av_perm(tclass_ex, perm_name); -+ if (!perm_code_ex) -+ { -+ /* fill up undefined permission */ -+ if (!deny_unknown) -+ i_avd.allowed |= perm_code; -+ i_avd.decided |= perm_code; -+ i_avd.auditdeny |= perm_code; -+ continue; -+ } -+ -+ if (avd->allowed & perm_code_ex) -+ i_avd.allowed |= perm_code; -+ if (avd->decided & perm_code_ex) -+ i_avd.decided |= perm_code; -+ if (avd->auditallow & perm_code_ex) -+ i_avd.auditallow |= perm_code; -+ if (avd->auditdeny & perm_code_ex) -+ i_avd.auditdeny |= perm_code; -+ } -+ -+ avd->allowed = i_avd.allowed; -+ avd->decided = i_avd.decided; -+ avd->auditallow = i_avd.auditallow; -+ avd->auditdeny = i_avd.auditdeny; -+ } -+ -+ /* -+ * sepgsqlGetClassString -+ * sepgsqlGetPermissionString -+ * It returns text representation of object classes/permissions -+ */ -+ const char * -+ sepgsqlGetClassString(uint16 tclass) -+ { -+ Assert(tclass < SEPG_CLASS_MAX); -+ -+ return selinux_catalog[tclass].class_name; -+ } -+ -+ const char * -+ sepgsqlGetPermString(uint16 tclass, uint32 permission) -+ { -+ int i; -+ -+ Assert(tclass < SEPG_CLASS_MAX); -+ -+ for (i=0; selinux_catalog[tclass].av[i].perm_name; i++) -+ { -+ if (selinux_catalog[tclass].av[i].perm_code == permission) -+ return selinux_catalog[tclass].av[i].perm_name; -+ } -+ return NULL; -+ } -+ -+ /* -+ * sepgsqlAuditName -+ * returns an identifier string to generate audit record for -+ * the given tuple. Please note that its results can indicate -+ * an address within the given tuple, so we should not refer -+ * the returned pointer after HeapTuple is released. -+ */ -+ const char * -+ sepgsqlAuditName(Oid relid, HeapTuple tuple) -+ { -+ static char buffer[NAMEDATALEN * 2 + 10]; -+ -+ switch (relid) -+ { -+ case DatabaseRelationId: -+ return NameStr(((Form_pg_database) GETSTRUCT(tuple))->datname); -+ -+ case NamespaceRelationId: -+ return NameStr(((Form_pg_namespace) GETSTRUCT(tuple))->nspname); -+ -+ case RelationRelationId: -+ return NameStr(((Form_pg_class) GETSTRUCT(tuple))->relname); -+ -+ case AttributeRelationId: -+ if (!IsBootstrapProcessingMode()) -+ { -+ Form_pg_attribute attForm -+ = (Form_pg_attribute) GETSTRUCT(tuple); -+ char *relname -+ = get_rel_name(attForm->attrelid); -+ -+ if (relname) -+ { -+ snprintf(buffer, sizeof(buffer), "%s.%s", -+ relname, NameStr(attForm->attname)); -+ pfree(relname); -+ return buffer; -+ } -+ } -+ return NameStr(((Form_pg_attribute) GETSTRUCT(tuple))->attname); -+ -+ case ProcedureRelationId: -+ return NameStr(((Form_pg_proc) GETSTRUCT(tuple))->proname); -+ } -+ return NULL; -+ } -+ -+ /* -+ * sepgsqlFileObjectClass -+ * -+ * It returns proper object class of filesystem object already opened. -+ * It is necessary to check privileges voluntarily. -+ */ -+ security_class_t -+ sepgsqlFileObjectClass(int fdesc) -+ { -+ struct stat stbuf; -+ -+ if (fstat(fdesc, &stbuf) != 0) -+ ereport(ERROR, -+ (errcode_for_file_access(), -+ errmsg("could not stat file descriptor: %d", fdesc))); -+ -+ if (S_ISDIR(stbuf.st_mode)) -+ return SEPG_CLASS_DIR; -+ else if (S_ISCHR(stbuf.st_mode)) -+ return SEPG_CLASS_CHR_FILE; -+ else if (S_ISBLK(stbuf.st_mode)) -+ return SEPG_CLASS_BLK_FILE; -+ else if (S_ISFIFO(stbuf.st_mode)) -+ return SEPG_CLASS_FIFO_FILE; -+ else if (S_ISLNK(stbuf.st_mode)) -+ return SEPG_CLASS_LNK_FILE; -+ else if (S_ISSOCK(stbuf.st_mode)) -+ return SEPG_CLASS_SOCK_FILE; -+ -+ return SEPG_CLASS_FILE; -+ } -+ -+ /* -+ * sepgsqlTupleObjectClass -+ * -+ * It returns correct object class of given tuple -+ */ -+ security_class_t -+ sepgsqlTupleObjectClass(Oid relid, HeapTuple tuple) -+ { -+ Form_pg_namespace nspForm; -+ Form_pg_class clsForm; -+ Form_pg_attribute attForm; -+ -+ switch (relid) -+ { -+ case DatabaseRelationId: -+ return SEPG_CLASS_DB_DATABASE; -+ -+ case NamespaceRelationId: -+ nspForm = (Form_pg_namespace) GETSTRUCT(tuple); -+ if (strncmp(NameStr(nspForm->nspname), "pg_temp_", 8) == 0 || -+ strncmp(NameStr(nspForm->nspname), "pg_toast_temp_", 14) == 0) -+ return SEPG_CLASS_DB_SCHEMA_TEMP; -+ return SEPG_CLASS_DB_SCHEMA; -+ -+ case RelationRelationId: -+ clsForm = (Form_pg_class) GETSTRUCT(tuple); -+ if (clsForm->relkind == RELKIND_RELATION) -+ return SEPG_CLASS_DB_TABLE; -+ if (clsForm->relkind == RELKIND_SEQUENCE) -+ return SEPG_CLASS_DB_SEQUENCE; -+ break; -+ -+ case AttributeRelationId: -+ attForm = (Form_pg_attribute) GETSTRUCT(tuple); -+ if (IsBootstrapProcessingMode() && -+ (attForm->attrelid == TypeRelationId || -+ attForm->attrelid == ProcedureRelationId || -+ attForm->attrelid == AttributeRelationId || -+ attForm->attrelid == RelationRelationId)) -+ return SEPG_CLASS_DB_COLUMN; -+ -+ if (get_rel_relkind(attForm->attrelid) == RELKIND_RELATION) -+ return SEPG_CLASS_DB_COLUMN; -+ break; -+ -+ case ProcedureRelationId: -+ return SEPG_CLASS_DB_PROCEDURE; -+ -+ case LargeObjectRelationId: -+ return SEPG_CLASS_DB_BLOB; -+ } -+ return SEPG_CLASS_DB_TUPLE; -+ } -diff -Nrpc base/src/backend/security/sepgsql/policy/Makefile sepgsql/src/backend/security/sepgsql/policy/Makefile -*** base/src/backend/security/sepgsql/policy/Makefile Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/policy/Makefile Wed Jul 15 19:35:52 2009 -*************** -*** 0 **** ---- 1,28 ---- -+ # -+ # Makefile for SE-PostgreSQL security policy module -+ # -+ top_builddir = ../../../../.. -+ include $(top_builddir)/src/Makefile.global -+ -+ POLICY_BASEDIR := $(DESTDIR)/usr/share/selinux -+ POLICY_MAKEFILE := $(POLICY_BASEDIR)/devel/Makefile -+ POLICY_INSTDIR := $(POLICY_BASEDIR)/packages -+ PREFIX_RULE := "s/%%__prefix__%%/$(shell echo $(prefix)|sed 's/\//\\\//g')/g" -+ BINDIR_RULE := "s/%%__bindir__%%/$(shell echo $(bindir)|sed 's/\//\\\//g')/g" -+ LIBDIR_RULE := "s/%%__libdir__%%/$(shell echo $(pkglibdir)|sed 's/\//\\\//g')/g" -+ -+ all: sepostgresql-devel.pp -+ -+ install: all -+ test -d $(POLICY_INSTDIR) || mkdir -p $(POLICY_INSTDIR) -+ install -p -m 0644 sepostgresql-devel.pp $(POLICY_INSTDIR) -+ -+ sepostgresql-devel.pp: sepostgresql-devel.te sepostgresql-devel.fc -+ $(MAKE) -f $(POLICY_MAKEFILE) -+ -+ sepostgresql-devel.fc: sepostgresql-devel.fc.template -+ cat $< | sed -e $(PREFIX_RULE) -e $(BINDIR_RULE) -e $(LIBDIR_RULE) > $@ -+ -+ clean: -+ $(MAKE) -f $(POLICY_MAKEFILE) clean -+ rm -f *.fc -diff -Nrpc base/src/backend/security/sepgsql/policy/sepostgresql-devel.fc.template sepgsql/src/backend/security/sepgsql/policy/sepostgresql-devel.fc.template -*** base/src/backend/security/sepgsql/policy/sepostgresql-devel.fc.template Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/policy/sepostgresql-devel.fc.template Wed Jul 15 19:35:52 2009 -*************** -*** 0 **** ---- 1,12 ---- -+ # -+ # SE-PostgreSQL install path -+ # -+ %%__prefix__%%(/.*)? -- gen_context(system_u:object_r:usr_t,s0) -+ -+ %%__bindir__%%/(se)?postgres -- gen_context(system_u:object_r:postgresql_exec_t,s0) -+ %%__bindir__%%/(se)?pg_ctl -- gen_context(system_u:object_r:initrc_exec_t,s0) -+ %%__bindir__%%/initdb(\.sepgsql)? -- gen_context(system_u:object_r:postgresql_exec_t,s0) -+ %%__bindir__%%(/.*)? -- gen_context(system_u:object_r:bin_t,s0) -+ -+ %%__libdir__%%(/.*)? -- gen_context(system_u:object_r:lib_t,s0) -+ -diff -Nrpc base/src/backend/security/sepgsql/policy/sepostgresql-devel.te sepgsql/src/backend/security/sepgsql/policy/sepostgresql-devel.te -*** base/src/backend/security/sepgsql/policy/sepostgresql-devel.te Thu Jan 1 09:00:00 1970 ---- sepgsql/src/backend/security/sepgsql/policy/sepostgresql-devel.te Thu Sep 10 15:43:44 2009 -*************** -*** 0 **** ---- 1,121 ---- -+ policy_module(sepostgresql-devel, 3.28) -+ -+ gen_require(` -+ class db_database all_db_database_perms; -+ class db_table all_db_table_perms; -+ class db_procedure all_db_procedure_perms; -+ class db_column all_db_column_perms; -+ class db_tuple all_db_tuple_perms; -+ class db_blob all_db_blob_perms; -+ -+ attribute sepgsql_client_type; -+ attribute sepgsql_unconfined_type; -+ -+ attribute sepgsql_database_type; -+ attribute sepgsql_table_type; -+ attribute sepgsql_sysobj_table_type; -+ attribute sepgsql_procedure_type; -+ attribute sepgsql_blob_type; -+ attribute sepgsql_module_type; -+ -+ # for regression test -+ type bin_t; -+ type user_home_t; -+ type sepgsql_trusted_proc_t; -+ -+ attribute tmpfile; -+ attribute ptynode; -+ ') -+ -+ ################################# -+ # -+ # Domain for Testcases -+ # -+ -+ role sepgsql_test_r; -+ -+ userdom_unpriv_user_template(sepgsql_test) -+ postgresql_role(sepgsql_test_r, sepgsql_test_t) -+ -+ allow sepgsql_test_t tmpfile : dir search_dir_perms; -+ allow sepgsql_test_t tmpfile : file rw_file_perms; -+ allow sepgsql_test_t ptynode : chr_file rw_file_perms; -+ -+ optional_policy(` -+ gen_require(` -+ type unconfined_t; -+ role unconfined_r; -+ ') -+ -+ tunable_policy(`sepgsql_regression_test_mode',` -+ allow unconfined_t sepgsql_test_t : process transition; -+ ') -+ allow sepgsql_test_t unconfined_t : fifo_file read_file_perms; -+ role unconfined_r types sepgsql_test_t; -+ role unconfined_r types sepgsql_trusted_proc_t; -+ ') -+ -+ ################################# -+ # -+ # SE-PostgreSQL Declarations -+ # -+ -+ ## -+ ##

-+ ## Allow to generate auditallow logs -+ ##

-+ ##
-+ gen_tunable(sepgsql_enable_auditallow, false) -+ -+ ## -+ ##

-+ ## Allow to generate auditdeny logs -+ ##

-+ ##
-+ gen_tunable(sepgsql_enable_auditdeny, true) -+ -+ ## -+ ##

-+ ## Allow widespread permissions for regression test -+ ## Don't set TRUE on operation phase -+ ##

-+ ##
-+ gen_tunable(sepgsql_regression_test_mode, false) -+ -+ ######################################## -+ # -+ # SE-PostgreSQL audit switch for debugging -+ # -+ tunable_policy(`sepgsql_enable_auditallow',` -+ auditallow domain sepgsql_database_type : db_database *; -+ auditallow domain sepgsql_table_type : db_table *; -+ auditallow domain sepgsql_table_type : db_column *; -+ auditallow domain sepgsql_table_type : db_tuple { relabelfrom relabelto }; -+ auditallow domain sepgsql_sysobj_table_type : db_tuple *; -+ auditallow domain sepgsql_procedure_type : db_procedure *; -+ auditallow domain sepgsql_blob_type : db_blob *; -+ auditallow domain sepgsql_module_type : db_database { install_module }; -+ auditallow sepgsql_database_type sepgsql_module_type : db_database { load_module }; -+ ') -+ -+ tunable_policy(`! sepgsql_enable_auditdeny',` -+ dontaudit domain sepgsql_database_type : db_database *; -+ dontaudit domain sepgsql_table_type : db_table *; -+ dontaudit domain sepgsql_table_type : db_column *; -+ dontaudit domain sepgsql_table_type : db_tuple { relabelfrom relabelto }; -+ dontaudit domain sepgsql_sysobj_table_type : db_tuple *; -+ dontaudit domain sepgsql_procedure_type : db_procedure *; -+ dontaudit domain sepgsql_blob_type : db_blob *; -+ dontaudit domain sepgsql_module_type : db_database { install_module }; -+ dontaudit sepgsql_database_type sepgsql_module_type : db_database { load_module }; -+ ') -+ -+ ######################################## -+ # -+ # SE-PostgreSQL regression test mode switch -+ # -+ tunable_policy(`sepgsql_regression_test_mode',` -+ allow sepgsql_client_type user_home_t : db_database { install_module }; -+ allow sepgsql_unconfined_type user_home_t : db_database { install_module }; -+ allow sepgsql_database_type user_home_t : db_database { load_module }; -+ ') -diff -Nrpc base/src/backend/storage/file/fd.c sepgsql/src/backend/storage/file/fd.c -*** base/src/backend/storage/file/fd.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/storage/file/fd.c Wed Jul 15 19:48:58 2009 -*************** FileTruncate(File file, off_t offset) -*** 1319,1324 **** ---- 1319,1331 ---- - return returnCode; - } - -+ int -+ FileRawDescriptor(File file) -+ { -+ Assert(FileIsValid(file)); -+ -+ return VfdCache[file].fd; -+ } - - /* - * Routines that want to use stdio (ie, FILE*) should use AllocateFile -diff -Nrpc base/src/backend/storage/ipc/ipci.c sepgsql/src/backend/storage/ipc/ipci.c -*** base/src/backend/storage/ipc/ipci.c Thu May 7 08:49:32 2009 ---- sepgsql/src/backend/storage/ipc/ipci.c Wed Jul 15 19:35:52 2009 -*************** -*** 25,30 **** ---- 25,31 ---- - #include "postmaster/autovacuum.h" - #include "postmaster/bgwriter.h" - #include "postmaster/postmaster.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/ipc.h" - #include "storage/pg_shmem.h" -*************** CreateSharedMemoryAndSemaphores(bool mak -*** 119,124 **** ---- 120,126 ---- - #ifdef EXEC_BACKEND - size = add_size(size, ShmemBackendArraySize()); - #endif -+ size = add_size(size, sepgsqlShmemSize()); - - /* freeze the addin request size and include it */ - addin_request_allowed = false; -diff -Nrpc base/src/backend/storage/large_object/inv_api.c sepgsql/src/backend/storage/large_object/inv_api.c -*** base/src/backend/storage/large_object/inv_api.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/storage/large_object/inv_api.c Tue Sep 8 23:55:48 2009 -*************** -*** 39,44 **** ---- 39,45 ---- - #include "catalog/pg_largeobject.h" - #include "commands/comment.h" - #include "libpq/libpq-fs.h" -+ #include "security/sepgsql.h" - #include "storage/large_object.h" - #include "utils/fmgroids.h" - #include "utils/rel.h" -*************** close_lo_relation(bool isCommit) -*** 137,148 **** - * read with can be specified. - */ - static bool -! myLargeObjectExists(Oid loid, Snapshot snapshot) - { - bool retval = false; - Relation pg_largeobject; - ScanKeyData skey[1]; - SysScanDesc sd; - - /* - * See if we can find any tuples belonging to the specified LO ---- 138,150 ---- - * read with can be specified. - */ - static bool -! myLargeObjectExists(LargeObjectDesc *lobj) - { - bool retval = false; - Relation pg_largeobject; - ScanKeyData skey[1]; - SysScanDesc sd; -+ HeapTuple tuple; - - /* - * See if we can find any tuples belonging to the specified LO -*************** myLargeObjectExists(Oid loid, Snapshot s -*** 150,164 **** - ScanKeyInit(&skey[0], - Anum_pg_largeobject_loid, - BTEqualStrategyNumber, F_OIDEQ, -! ObjectIdGetDatum(loid)); - - pg_largeobject = heap_open(LargeObjectRelationId, AccessShareLock); - - sd = systable_beginscan(pg_largeobject, LargeObjectLOidPNIndexId, true, -! snapshot, 1, skey); - -! if (systable_getnext(sd) != NULL) - retval = true; - - systable_endscan(sd); - ---- 152,170 ---- - ScanKeyInit(&skey[0], - Anum_pg_largeobject_loid, - BTEqualStrategyNumber, F_OIDEQ, -! ObjectIdGetDatum(lobj->id)); - - pg_largeobject = heap_open(LargeObjectRelationId, AccessShareLock); - - sd = systable_beginscan(pg_largeobject, LargeObjectLOidPNIndexId, true, -! lobj->snapshot, 1, skey); - -! tuple = systable_getnext(sd); -! if (HeapTupleIsValid(tuple)) -! { - retval = true; -+ lobj->secid = HeapTupleGetSecid(tuple); -+ } - - systable_endscan(sd); - -*************** inv_open(Oid lobjId, int flags, MemoryCo -*** 260,266 **** - elog(ERROR, "invalid flags: %d", flags); - - /* Can't use LargeObjectExists here because it always uses SnapshotNow */ -! if (!myLargeObjectExists(lobjId, retval->snapshot)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("large object %u does not exist", lobjId))); ---- 266,272 ---- - elog(ERROR, "invalid flags: %d", flags); - - /* Can't use LargeObjectExists here because it always uses SnapshotNow */ -! if (!myLargeObjectExists(retval)) - ereport(ERROR, - (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("large object %u does not exist", lobjId))); -*************** inv_write(LargeObjectDesc *obj_desc, con -*** 642,647 **** ---- 648,655 ---- - replace[Anum_pg_largeobject_data - 1] = true; - newtup = heap_modify_tuple(oldtuple, RelationGetDescr(lo_heap_r), - values, nulls, replace); -+ if (HeapTupleHasSecid(newtup)) -+ HeapTupleSetSecid(newtup, obj_desc->secid); - simple_heap_update(lo_heap_r, &newtup->t_self, newtup); - CatalogIndexInsert(indstate, newtup); - heap_freetuple(newtup); -*************** inv_write(LargeObjectDesc *obj_desc, con -*** 685,690 **** ---- 693,700 ---- - values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); - newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls); -+ if (HeapTupleHasSecid(newtup)) -+ HeapTupleSetSecid(newtup, obj_desc->secid); - simple_heap_insert(lo_heap_r, newtup); - CatalogIndexInsert(indstate, newtup); - heap_freetuple(newtup); -*************** inv_truncate(LargeObjectDesc *obj_desc, -*** 845,850 **** ---- 855,862 ---- - values[Anum_pg_largeobject_pageno - 1] = Int32GetDatum(pageno); - values[Anum_pg_largeobject_data - 1] = PointerGetDatum(&workbuf); - newtup = heap_form_tuple(lo_heap_r->rd_att, values, nulls); -+ if (HeapTupleHasSecid(newtup)) -+ HeapTupleSetSecid(newtup, obj_desc->secid); - simple_heap_insert(lo_heap_r, newtup); - CatalogIndexInsert(indstate, newtup); - heap_freetuple(newtup); -*************** inv_truncate(LargeObjectDesc *obj_desc, -*** 868,870 **** ---- 880,978 ---- - */ - CommandCounterIncrement(); - } -+ -+ Oid -+ inv_get_security(Oid loid) -+ { -+ Relation rel; -+ ScanKeyData skey; -+ SysScanDesc scan; -+ HeapTuple tuple; -+ Oid secid = InvalidOid; -+ -+ ScanKeyInit(&skey, -+ Anum_pg_largeobject_loid, -+ BTEqualStrategyNumber, -+ F_OIDEQ, ObjectIdGetDatum(loid)); -+ -+ rel = heap_open(LargeObjectRelationId, AccessShareLock); -+ -+ scan = systable_beginscan(rel, LargeObjectLOidPNIndexId, true, -+ SnapshotNow, 1, &skey); -+ tuple = systable_getnext(scan); -+ -+ if (HeapTupleIsValid(tuple)) -+ { -+ /* -+ * SELinux: check db_blob:{getattr} -+ */ -+ sepgsqlCheckBlobGetattr(tuple); -+ secid = HeapTupleGetSecid(tuple); -+ } -+ systable_endscan(scan); -+ -+ heap_close(rel, AccessShareLock); -+ -+ return secid; -+ } -+ -+ void -+ inv_set_security(Oid loid, Oid secid) -+ { -+ Relation rel; -+ ScanKeyData skey; -+ SysScanDesc scan; -+ HeapTuple tuple; -+ CatalogIndexState ind; -+ bool found = false; -+ -+ ScanKeyInit(&skey, -+ Anum_pg_largeobject_loid, -+ BTEqualStrategyNumber, -+ F_OIDEQ, ObjectIdGetDatum(loid)); -+ -+ rel = heap_open(LargeObjectRelationId, RowExclusiveLock); -+ -+ ind = CatalogOpenIndexes(rel); -+ -+ scan = systable_beginscan(rel, LargeObjectLOidPNIndexId, true, -+ SnapshotNow, 1, &skey); -+ while (HeapTupleIsValid(tuple = systable_getnext(scan))) -+ { -+ HeapTuple newtuple; -+ Datum values[Natts_pg_largeobject]; -+ bool nulls[Natts_pg_largeobject]; -+ bool replaces[Natts_pg_largeobject]; -+ -+ memset(replaces, false, sizeof(replaces)); -+ -+ newtuple = heap_modify_tuple(tuple, RelationGetDescr(rel), -+ values, nulls, replaces); -+ if (!HeapTupleHasSecid(newtuple)) -+ elog(ERROR, "Unable to assign security label on \"%s\"", -+ RelationGetRelationName(rel)); -+ HeapTupleSetSecid(newtuple, secid); -+ -+ /* -+ * SELinux: check db_blob:{setattr relabelfrom relabelto} -+ */ -+ if (!found) -+ sepgsqlCheckBlobRelabel(tuple, newtuple); -+ -+ simple_heap_update(rel, &tuple->t_self, newtuple); -+ CatalogUpdateIndexes(rel, newtuple); -+ found = true; -+ } -+ systable_endscan(scan); -+ -+ CatalogCloseIndexes(ind); -+ -+ heap_close(rel, RowExclusiveLock); -+ -+ CommandCounterIncrement(); -+ -+ if (!found) -+ ereport(ERROR, -+ (errcode(ERRCODE_UNDEFINED_OBJECT), -+ errmsg("large object %u does not exist", loid))); -+ } -diff -Nrpc base/src/backend/tcop/fastpath.c sepgsql/src/backend/tcop/fastpath.c -*** base/src/backend/tcop/fastpath.c Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/tcop/fastpath.c Mon Sep 7 00:55:45 2009 -*************** -*** 26,31 **** ---- 26,32 ---- - #include "libpq/pqformat.h" - #include "mb/pg_wchar.h" - #include "miscadmin.h" -+ #include "security/sepgsql.h" - #include "tcop/fastpath.h" - #include "tcop/tcopprot.h" - #include "utils/acl.h" -*************** HandleFunctionRequest(StringInfo msgBuf) -*** 343,353 **** ---- 344,356 ---- - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_NAMESPACE, - get_namespace_name(fip->namespace)); -+ sepgsqlCheckSchemaSearch(fip->namespace, true); - - aclresult = pg_proc_aclcheck(fid, GetUserId(), ACL_EXECUTE); - if (aclresult != ACLCHECK_OK) - aclcheck_error(aclresult, ACL_KIND_PROC, - get_func_name(fid)); -+ sepgsqlCheckProcedureExecute(fid); - - /* - * Prepare function call info block and insert arguments. -diff -Nrpc base/src/backend/tcop/pquery.c sepgsql/src/backend/tcop/pquery.c -*** base/src/backend/tcop/pquery.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/tcop/pquery.c Wed Jul 15 19:30:50 2009 -*************** PortalStart(Portal portal, ParamListInfo -*** 573,579 **** - Assert(pstmt->returningLists); - portal->tupDesc = - ExecCleanTypeFromTL((List *) linitial(pstmt->returningLists), -! false); - } - - /* ---- 573,579 ---- - Assert(pstmt->returningLists); - portal->tupDesc = - ExecCleanTypeFromTL((List *) linitial(pstmt->returningLists), -! false, false); - } - - /* -diff -Nrpc base/src/backend/tcop/utility.c sepgsql/src/backend/tcop/utility.c -*** base/src/backend/tcop/utility.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/tcop/utility.c Wed Jul 15 21:17:18 2009 -*************** -*** 50,55 **** ---- 50,56 ---- - #include "postmaster/bgwriter.h" - #include "rewrite/rewriteDefine.h" - #include "rewrite/rewriteRemove.h" -+ #include "security/sepgsql.h" - #include "storage/fd.h" - #include "tcop/pquery.h" - #include "tcop/utility.h" -*************** check_xact_readonly(Node *parsetree) -*** 162,167 **** ---- 163,169 ---- - case T_AlterRoleSetStmt: - case T_AlterObjectSchemaStmt: - case T_AlterOwnerStmt: -+ case T_AlterSecLabelStmt: - case T_AlterSeqStmt: - case T_AlterTableStmt: - case T_RenameStmt: -*************** ProcessUtility(Node *parsetree, -*** 612,617 **** ---- 614,623 ---- - ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree); - break; - -+ case T_AlterSecLabelStmt: -+ ExecAlterSecLabelStmt((AlterSecLabelStmt *) parsetree); -+ break; -+ - case T_AlterTableStmt: - { - List *stmts; -*************** ProcessUtility(Node *parsetree, -*** 893,898 **** ---- 899,905 ---- - LoadStmt *stmt = (LoadStmt *) parsetree; - - closeAllVfds(); /* probably not necessary... */ -+ - /* Allowed names are restricted if you're not superuser */ - load_file(stmt->filename, !superuser()); - } -*************** CreateCommandTag(Node *parsetree) -*** 1635,1640 **** ---- 1642,1672 ---- - } - break; - -+ case T_AlterSecLabelStmt: -+ switch (((AlterSecLabelStmt *) parsetree)->objectType) -+ { -+ case OBJECT_DATABASE: -+ tag = "ALTER DATABASE"; -+ break; -+ case OBJECT_SCHEMA: -+ tag = "ALTER SCHEMA"; -+ break; -+ case OBJECT_TABLE: -+ case OBJECT_COLUMN: -+ tag = "ALTER TABLE"; -+ break; -+ case OBJECT_SEQUENCE: -+ tag = "ALTER SEQUENCE"; -+ break; -+ case OBJECT_FUNCTION: -+ tag = "ALTER FUNCTION"; -+ break; -+ default: -+ tag = "???"; -+ break; -+ } -+ break; -+ - case T_AlterTableStmt: - switch (((AlterTableStmt *) parsetree)->relkind) - { -*************** GetCommandLogLevel(Node *parsetree) -*** 2213,2218 **** ---- 2245,2254 ---- - lev = LOGSTMT_DDL; - break; - -+ case T_AlterSecLabelStmt: -+ lev = LOGSTMT_DDL; -+ break; -+ - case T_AlterTableStmt: - lev = LOGSTMT_DDL; - break; -diff -Nrpc base/src/backend/utils/adt/genfile.c sepgsql/src/backend/utils/adt/genfile.c -*** base/src/backend/utils/adt/genfile.c Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/utils/adt/genfile.c Wed Jul 15 19:48:58 2009 -*************** -*** 24,29 **** ---- 24,30 ---- - #include "funcapi.h" - #include "miscadmin.h" - #include "postmaster/syslogger.h" -+ #include "security/sepgsql.h" - #include "storage/fd.h" - #include "utils/builtins.h" - #include "utils/memutils.h" -*************** pg_read_file(PG_FUNCTION_ARGS) -*** 105,110 **** ---- 106,114 ---- - errmsg("could not open file \"%s\" for reading: %m", - filename))); - -+ /* SELinux: check file:{read} permission */ -+ sepgsqlCheckFileRead(fileno(file), filename); -+ - if (fseeko(file, (off_t) seek_offset, - (seek_offset >= 0) ? SEEK_SET : SEEK_END) != 0) - ereport(ERROR, -diff -Nrpc base/src/backend/utils/adt/ri_triggers.c sepgsql/src/backend/utils/adt/ri_triggers.c -*** base/src/backend/utils/adt/ri_triggers.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/utils/adt/ri_triggers.c Wed Jul 15 19:39:56 2009 -*************** -*** 39,44 **** ---- 39,45 ---- - #include "parser/parse_coerce.h" - #include "parser/parse_relation.h" - #include "miscadmin.h" -+ #include "security/rowlevel.h" - #include "utils/acl.h" - #include "utils/builtins.h" - #include "utils/fmgroids.h" -*************** RI_Initial_Check(Trigger *trigger, Relat -*** 2627,2632 **** ---- 2628,2634 ---- - const char *sep; - int i; - int old_work_mem; -+ int save_rowlv; - char workmembuf[32]; - int spi_result; - SPIPlanPtr qplan; -*************** RI_Initial_Check(Trigger *trigger, Relat -*** 2759,2764 **** ---- 2761,2771 ---- - SPI_result, querybuf.data); - - /* -+ * Disables the Row-level stuff during the internal consistency checks. -+ */ -+ save_rowlv = rowlvSetPerformingMode(ROWLV_BYPASS_MODE); -+ -+ /* - * Run the plan. For safety we force a current snapshot to be used. (In - * serializable mode, this arguably violates serializability, but we - * really haven't got much choice.) We don't need to register the -*************** RI_Initial_Check(Trigger *trigger, Relat -*** 2771,2776 **** ---- 2778,2786 ---- - InvalidSnapshot, - true, false, 1); - -+ /* Restore Row-level stuff */ -+ rowlvSetPerformingMode(save_rowlv); -+ - /* Check result */ - if (spi_result != SPI_OK_SELECT) - elog(ERROR, "SPI_execute_snapshot returned %d", spi_result); -*************** ri_PerformCheck(RI_QueryKey *qkey, SPIPl -*** 3264,3269 **** ---- 3274,3280 ---- - int spi_result; - Oid save_userid; - bool save_secdefcxt; -+ int save_rowlv, temp_rowlv; - Datum vals[RI_MAX_NUMKEYS * 2]; - char nulls[RI_MAX_NUMKEYS * 2]; - -*************** ri_PerformCheck(RI_QueryKey *qkey, SPIPl -*** 3346,3357 **** ---- 3357,3375 ---- - GetUserIdAndContext(&save_userid, &save_secdefcxt); - SetUserIdAndContext(RelationGetForm(query_rel)->relowner, true); - -+ /* Switch Row-level stuff behavior on FK checks, if necessary */ -+ temp_rowlv = (detectNewRows ? ROWLV_ABORT_MODE : ROWLV_FILTER_MODE); -+ save_rowlv = rowlvSetPerformingMode(temp_rowlv); -+ - /* Finally we can run the query. */ - spi_result = SPI_execute_snapshot(qplan, - vals, nulls, - test_snapshot, crosscheck_snapshot, - false, false, limit); - -+ /* Restore Row-level stuff behavior */ -+ rowlvSetPerformingMode(save_rowlv); -+ - /* Restore UID */ - SetUserIdAndContext(save_userid, save_secdefcxt); - -diff -Nrpc base/src/backend/utils/adt/trigfuncs.c sepgsql/src/backend/utils/adt/trigfuncs.c -*** base/src/backend/utils/adt/trigfuncs.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/utils/adt/trigfuncs.c Tue Sep 8 23:55:48 2009 -*************** suppress_redundant_updates_trigger(PG_FU -*** 76,81 **** ---- 76,85 ---- - !OidIsValid(HeapTupleHeaderGetOid(newheader))) - HeapTupleHeaderSetOid(newheader, HeapTupleHeaderGetOid(oldheader)); - -+ if (HeapTupleHeaderHasSecid(newheader) && -+ !OidIsValid(HeapTupleHeaderGetSecid(newheader))) -+ HeapTupleHeaderSetSecid(newheader, HeapTupleHeaderGetSecid(oldheader)); -+ - /* if the tuple payload is the same ... */ - if (newtuple->t_len == oldtuple->t_len && - newheader->t_hoff == oldheader->t_hoff && -diff -Nrpc base/src/backend/utils/cache/plancache.c sepgsql/src/backend/utils/cache/plancache.c -*** base/src/backend/utils/cache/plancache.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/utils/cache/plancache.c Sun Sep 6 19:53:10 2009 -*************** PlanCacheComputeResultDesc(List *stmt_li -*** 859,870 **** - if (IsA(node, Query)) - { - query = (Query *) node; -! return ExecCleanTypeFromTL(query->targetList, false); - } - if (IsA(node, PlannedStmt)) - { - pstmt = (PlannedStmt *) node; -! return ExecCleanTypeFromTL(pstmt->planTree->targetlist, false); - } - /* other cases shouldn't happen, but return NULL */ - break; ---- 859,870 ---- - if (IsA(node, Query)) - { - query = (Query *) node; -! return ExecCleanTypeFromTL(query->targetList, false, false); - } - if (IsA(node, PlannedStmt)) - { - pstmt = (PlannedStmt *) node; -! return ExecCleanTypeFromTL(pstmt->planTree->targetlist, false, false); - } - /* other cases shouldn't happen, but return NULL */ - break; -*************** PlanCacheComputeResultDesc(List *stmt_li -*** 875,887 **** - { - query = (Query *) node; - Assert(query->returningList); -! return ExecCleanTypeFromTL(query->returningList, false); - } - if (IsA(node, PlannedStmt)) - { - pstmt = (PlannedStmt *) node; - Assert(pstmt->returningLists); -! return ExecCleanTypeFromTL((List *) linitial(pstmt->returningLists), false); - } - /* other cases shouldn't happen, but return NULL */ - break; ---- 875,888 ---- - { - query = (Query *) node; - Assert(query->returningList); -! return ExecCleanTypeFromTL(query->returningList, false, false); - } - if (IsA(node, PlannedStmt)) - { - pstmt = (PlannedStmt *) node; - Assert(pstmt->returningLists); -! return ExecCleanTypeFromTL((List *) linitial(pstmt->returningLists), -! false, false); - } - /* other cases shouldn't happen, but return NULL */ - break; -diff -Nrpc base/src/backend/utils/cache/relcache.c sepgsql/src/backend/utils/cache/relcache.c -*** base/src/backend/utils/cache/relcache.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/utils/cache/relcache.c Wed Sep 9 13:14:37 2009 -*************** -*** 47,52 **** ---- 47,53 ---- - #include "catalog/pg_opclass.h" - #include "catalog/pg_proc.h" - #include "catalog/pg_rewrite.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_type.h" - #include "commands/trigger.h" - #include "miscadmin.h" -*************** RelationBuildDesc(Oid targetRelId, Relat -*** 865,870 **** ---- 866,875 ---- - /* extract reloptions if any */ - RelationParseRelOptions(relation, pg_class_tuple); - -+ /* Fixup relation->rd_att->tdhassecid */ -+ RelationGetDescr(relation)->tdhassecid -+ = securityTupleDescHasSecid(relid, relp->relkind); -+ - /* - * initialize the relation lock manager information - */ -*************** formrdesc(const char *relationName, Oid -*** 1458,1463 **** ---- 1463,1473 ---- - RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid; - relation->rd_rel->relfilenode = RelationGetRelid(relation); - -+ /* Fixup relation->rd_att->tdhassecid */ -+ RelationGetDescr(relation)->tdhassecid -+ = securityTupleDescHasSecid(RelationGetRelid(relation), -+ RELKIND_RELATION); -+ - /* - * initialize the relation lock manager information - */ -*************** BuildHardcodedDescriptor(int natts, Form -*** 2699,2704 **** ---- 2709,2721 ---- - result = CreateTemplateTupleDesc(natts, hasoids); - result->tdtypeid = RECORDOID; /* not right, but we don't care */ - result->tdtypmod = -1; -+ /* -+ * NOTE: we assume the returned TupleDesc is only used for -+ * references to toast'ed data, and it is not delivered to -+ * heap_form_tuple(), so TupleDesc->tdhassecid don't give us -+ * any effect. -+ * We omit to invoke securityTupleDescHasSecid() here. -+ */ - - for (i = 0; i < natts; i++) - { -*************** load_relcache_init_file(void) -*** 3453,3458 **** ---- 3470,3480 ---- - rel->rd_options = NULL; - } - -+ /* Fixup rel->rd_att->tdhassecid */ -+ RelationGetDescr(rel)->tdhassecid -+ = securityTupleDescHasSecid(RelationGetRelid(rel), -+ RelationGetForm(rel)->relkind); -+ - /* mark not-null status */ - if (has_not_null) - { -diff -Nrpc base/src/backend/utils/cache/syscache.c sepgsql/src/backend/utils/cache/syscache.c -*** base/src/backend/utils/cache/syscache.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/utils/cache/syscache.c Wed Sep 9 21:29:33 2009 -*************** -*** 41,46 **** ---- 41,47 ---- - #include "catalog/pg_opfamily.h" - #include "catalog/pg_proc.h" - #include "catalog/pg_rewrite.h" -+ #include "catalog/pg_security.h" - #include "catalog/pg_statistic.h" - #include "catalog/pg_ts_config.h" - #include "catalog/pg_ts_config_map.h" -*************** static const struct cachedesc cacheinfo[ -*** 584,589 **** ---- 585,614 ---- - }, - 1024 - }, -+ {SecurityRelationId, /* SECURITYATTR */ -+ SecuritySecattrIndexId, -+ Anum_pg_security_relid, -+ 4, -+ { -+ Anum_pg_security_datid, -+ Anum_pg_security_relid, -+ Anum_pg_security_seckind, -+ Anum_pg_security_secattr -+ }, -+ 128, -+ }, -+ {SecurityRelationId, /* SECURITYSECID */ -+ SecuritySecidIndexId, -+ Anum_pg_security_relid, -+ 2, -+ { -+ Anum_pg_security_secid, -+ Anum_pg_security_datid, -+ 0, -+ 0 -+ }, -+ 128 -+ }, - {StatisticRelationId, /* STATRELATT */ - StatisticRelidAttnumIndexId, - Anum_pg_statistic_starelid, -*************** GetSysCacheOid(int cacheId, -*** 931,937 **** - return result; - } - -- - /* - * SearchSysCacheAttName - * ---- 956,961 ---- -diff -Nrpc base/src/backend/utils/fmgr/dfmgr.c sepgsql/src/backend/utils/fmgr/dfmgr.c -*** base/src/backend/utils/fmgr/dfmgr.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/utils/fmgr/dfmgr.c Sun Sep 6 19:53:10 2009 -*************** -*** 23,28 **** ---- 23,29 ---- - #endif - #include "lib/stringinfo.h" - #include "miscadmin.h" -+ #include "security/sepgsql.h" - #include "utils/dynamic_loader.h" - #include "utils/hsearch.h" - -*************** load_external_function(char *filename, c -*** 109,114 **** ---- 110,118 ---- - /* Expand the possibly-abbreviated filename to an exact path name */ - fullname = expand_dynamic_library_name(filename); - -+ /* SELinux checks db_database:{load_module} */ -+ sepgsqlCheckDatabaseLoadModule(fullname); -+ - /* Load the shared library, unless we already did */ - lib_handle = internal_load_library(fullname); - -*************** load_file(const char *filename, bool res -*** 149,154 **** ---- 153,161 ---- - /* Expand the possibly-abbreviated filename to an exact path name */ - fullname = expand_dynamic_library_name(filename); - -+ /* SELinux checks db_database:{load_module} */ -+ sepgsqlCheckDatabaseLoadModule(fullname); -+ - /* Unload the library if currently loaded */ - internal_unload_library(fullname); - -diff -Nrpc base/src/backend/utils/fmgr/fmgr.c sepgsql/src/backend/utils/fmgr/fmgr.c -*** base/src/backend/utils/fmgr/fmgr.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/backend/utils/fmgr/fmgr.c Wed Jul 15 19:35:52 2009 -*************** -*** 24,29 **** ---- 24,30 ---- - #include "miscadmin.h" - #include "nodes/nodeFuncs.h" - #include "pgstat.h" -+ #include "security/sepgsql.h" - #include "utils/builtins.h" - #include "utils/fmgrtab.h" - #include "utils/guc.h" -*************** fmgr_info_cxt_security(Oid functionId, F -*** 289,294 **** ---- 290,296 ---- - } - - finfo->fn_oid = functionId; -+ sepgsqlCheckProcedureEntrypoint(finfo, procedureTuple); - ReleaseSysCache(procedureTuple); - } - -diff -Nrpc base/src/backend/utils/init/postinit.c sepgsql/src/backend/utils/init/postinit.c -*** base/src/backend/utils/init/postinit.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/utils/init/postinit.c Mon Sep 7 00:55:45 2009 -*************** -*** 32,37 **** ---- 32,38 ---- - #include "pgstat.h" - #include "postmaster/autovacuum.h" - #include "postmaster/postmaster.h" -+ #include "security/sepgsql.h" - #include "storage/backendid.h" - #include "storage/bufmgr.h" - #include "storage/fd.h" -*************** CheckMyDatabase(const char *name, bool a -*** 201,207 **** - name))); - - /* -! * Check privilege to connect to the database. (The am_superuser test - * is redundant, but since we have the flag, might as well check it - * and save a few cycles.) - */ ---- 202,208 ---- - name))); - - /* -! * Check privilege to connect to the database. (The am_superuser test - * is redundant, but since we have the flag, might as well check it - * and save a few cycles.) - */ -*************** CheckMyDatabase(const char *name, bool a -*** 213,218 **** ---- 214,222 ---- - errmsg("permission denied for database \"%s\"", name), - errdetail("User does not have CONNECT privilege."))); - -+ /* SELinux: db_database:{access} */ -+ sepgsqlCheckDatabaseAccess(MyDatabaseId); -+ - /* - * Check connection limit for this database. - * -*************** InitPostgres(const char *in_dbname, Oid -*** 575,580 **** ---- 579,587 ---- - */ - RelationCacheInitializePhase2(); - -+ /* Initialize SE-PostgreSQL internal facilities */ -+ sepgsqlAvcInitialize(); -+ - /* - * Figure out our postgres user id, and see if we are a superuser. - * -diff -Nrpc base/src/backend/utils/misc/guc.c sepgsql/src/backend/utils/misc/guc.c -*** base/src/backend/utils/misc/guc.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/utils/misc/guc.c Sun Sep 6 19:53:10 2009 -*************** -*** 56,61 **** ---- 56,62 ---- - #include "postmaster/syslogger.h" - #include "postmaster/walwriter.h" - #include "regex/regex.h" -+ #include "security/sepgsql.h" - #include "storage/bufmgr.h" - #include "storage/fd.h" - #include "tcop/tcopprot.h" -*************** static struct config_bool ConfigureNames -*** 1220,1225 **** ---- 1221,1252 ---- - &IgnoreSystemIndexes, - false, NULL, NULL - }, -+ #ifdef HAVE_SELINUX -+ { -+ {"sepostgresql", PGC_POSTMASTER, CONN_AUTH_SECURITY, -+ gettext_noop("SE-PostgreSQL activation option to be turned on/off"), -+ NULL, -+ }, -+ &sepostgresql_is_enabled, -+ false, NULL, NULL -+ }, -+ { -+ {"sepostgresql_row_level", PGC_POSTMASTER, CONN_AUTH_SECURITY, -+ gettext_noop("Row-level access controls on SE-PostgreSQL"), -+ NULL, -+ }, -+ &sepostgresql_row_level, -+ true, NULL, NULL -+ }, -+ { -+ {"sepostgresql_mcstrans", PGC_USERSET, CONN_AUTH_SECURITY, -+ gettext_noop("SE-PostgreSQL uses mcstrans on printing security labels"), -+ NULL, -+ }, -+ &sepostgresql_use_mcstrans, -+ true, NULL, NULL -+ }, -+ #endif - - /* End-of-list marker */ - { -diff -Nrpc base/src/backend/utils/misc/postgresql.conf.sample sepgsql/src/backend/utils/misc/postgresql.conf.sample -*** base/src/backend/utils/misc/postgresql.conf.sample Sun Sep 6 19:40:49 2009 ---- sepgsql/src/backend/utils/misc/postgresql.conf.sample Thu Sep 10 00:06:47 2009 -*************** -*** 51,57 **** - - - #------------------------------------------------------------------------------ -! # CONNECTIONS AND AUTHENTICATION - #------------------------------------------------------------------------------ - - # - Connection Settings - ---- 51,57 ---- - - - #------------------------------------------------------------------------------ -! # CONNECTIONS, AUTHENTICATION AND SECURITY - #------------------------------------------------------------------------------ - - # - Connection Settings - -*************** -*** 95,101 **** - # 0 selects the system default - #tcp_keepalives_count = 0 # TCP_KEEPCNT; - # 0 selects the system default -! - - #------------------------------------------------------------------------------ - # RESOURCE USAGE (except WAL) ---- 95,102 ---- - # 0 selects the system default - #tcp_keepalives_count = 0 # TCP_KEEPCNT; - # 0 selects the system default -! #sepostgresql = off # SE-PostgreSQL support -! sepostgresql = on - - #------------------------------------------------------------------------------ - # RESOURCE USAGE (except WAL) -diff -Nrpc base/src/backend/utils/misc/superuser.c sepgsql/src/backend/utils/misc/superuser.c -*** base/src/backend/utils/misc/superuser.c Sat Jan 3 13:01:35 2009 ---- sepgsql/src/backend/utils/misc/superuser.c Wed Jul 15 19:35:52 2009 -*************** -*** 21,26 **** ---- 21,27 ---- - #include "postgres.h" - - #include "catalog/pg_authid.h" -+ #include "security/sepgsql.h" - #include "utils/inval.h" - #include "utils/syscache.h" - #include "miscadmin.h" -*************** superuser_arg(Oid roleid) -*** 60,70 **** - - /* Quick out for cache hit */ - if (OidIsValid(last_roleid) && last_roleid == roleid) -! return last_roleid_is_super; - - /* Special escape path in case you deleted all your users. */ - if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID) -! return true; - - /* OK, look up the information in pg_authid */ - rtup = SearchSysCache(AUTHOID, ---- 61,77 ---- - - /* Quick out for cache hit */ - if (OidIsValid(last_roleid) && last_roleid == roleid) -! { -! result = last_roleid_is_super; -! goto out; -! } - - /* Special escape path in case you deleted all your users. */ - if (!IsUnderPostmaster && roleid == BOOTSTRAP_SUPERUSERID) -! { -! result = true; -! goto out; -! } - - /* OK, look up the information in pg_authid */ - rtup = SearchSysCache(AUTHOID, -*************** superuser_arg(Oid roleid) -*** 94,99 **** ---- 101,110 ---- - last_roleid = roleid; - last_roleid_is_super = result; - -+ out: -+ if (result) -+ result = sepgsqlCheckDatabaseSuperuser(); -+ - return result; - } - -diff -Nrpc base/src/bin/initdb/initdb.c sepgsql/src/bin/initdb/initdb.c -*** base/src/bin/initdb/initdb.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/bin/initdb/initdb.c Wed Jul 15 19:35:52 2009 -*************** static bool debug = false; -*** 87,92 **** ---- 87,93 ---- - static bool noclean = false; - static bool show_setting = false; - static char *xlog_dir = ""; -+ static bool enable_selinux = false; - - - /* internal vars */ -*************** setup_config(void) -*** 1205,1210 **** ---- 1206,1218 ---- - "#default_text_search_config = 'pg_catalog.simple'", - repltok); - -+ if (enable_selinux) -+ { -+ strcpy(repltok, "sepostgresql = on"); -+ conflines = replace_token(conflines, -+ "#sepostgresql = off", repltok); -+ } -+ - snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data); - - writefile(path, conflines); -*************** usage(const char *progname) -*** 2443,2448 **** ---- 2451,2457 ---- - printf(_(" -U, --username=NAME database superuser name\n")); - printf(_(" -W, --pwprompt prompt for a password for the new superuser\n")); - printf(_(" -X, --xlogdir=XLOGDIR location for the transaction log directory\n")); -+ printf(_(" --enable-selinux enables SELinux support, if compiled\n")); - printf(_("\nLess commonly used options:\n")); - printf(_(" -d, --debug generate lots of debugging output\n")); - printf(_(" -L DIRECTORY where to find the input files\n")); -*************** main(int argc, char *argv[]) -*** 2478,2483 **** ---- 2487,2493 ---- - {"auth", required_argument, NULL, 'A'}, - {"pwprompt", no_argument, NULL, 'W'}, - {"pwfile", required_argument, NULL, 9}, -+ {"enable-selinux", no_argument, NULL, 10}, - {"username", required_argument, NULL, 'U'}, - {"help", no_argument, NULL, '?'}, - {"version", no_argument, NULL, 'V'}, -*************** main(int argc, char *argv[]) -*** 2594,2599 **** ---- 2604,2612 ---- - case 9: - pwfilename = xstrdup(optarg); - break; -+ case 10: -+ enable_selinux = true; -+ break; - case 's': - show_setting = true; - break; -diff -Nrpc base/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c -*** base/src/bin/pg_dump/pg_dump.c Sun Sep 6 19:40:49 2009 ---- sepgsql/src/bin/pg_dump/pg_dump.c Tue Sep 8 17:13:41 2009 -*************** static int disable_dollar_quoting = 0; -*** 112,117 **** ---- 112,119 ---- - static int dump_inserts = 0; - static int column_inserts = 0; - -+ /* flag to turn on/off security_context */ -+ static int security_context = 0; - - static void help(const char *progname); - static void expand_schema_name_patterns(SimpleStringList *patterns, -*************** main(int argc, char **argv) -*** 277,282 **** ---- 279,285 ---- - {"no-tablespaces", no_argument, &outputNoTablespaces, 1}, - {"role", required_argument, NULL, 3}, - {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, -+ {"security-context", no_argument, &security_context, 1}, - - {NULL, 0, NULL, 0} - }; -*************** main(int argc, char **argv) -*** 425,430 **** ---- 428,435 ---- - outputNoTablespaces = 1; - else if (strcmp(optarg, "use-set-session-authorization") == 0) - use_setsessauth = 1; -+ else if (strcmp(optarg, "security-context") == 0) -+ security_context = 1; - else - { - fprintf(stderr, -*************** main(int argc, char **argv) -*** 573,578 **** ---- 578,605 ---- - std_strings = PQparameterStatus(g_conn, "standard_conforming_strings"); - g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0); - -+ /* Check availability of SE-PostgreSQL */ -+ if (security_context > 0) -+ { -+ PGresult *res; -+ -+ res = PQexec(g_conn, "SHOW sepostgresql"); -+ if (PQresultStatus(res) != PGRES_TUPLES_OK || -+ PQntuples(res) != 1 || -+ strcmp(PQgetvalue(res, 0, 0), "on") != 0) -+ { -+ write_msg(NULL, "SE-PostgreSQL is not available now."); -+ exit(1); -+ } -+ } -+ -+ /* -+ * It needs to force column insertion mode, when --inserts -+ * and either --security-label or --security-acl is given. -+ */ -+ if (security_context > 0 && dump_inserts) -+ column_inserts = 1; -+ - /* Set the role if requested */ - if (use_role && g_fout->remoteVersion >= 80100) - { -*************** help(const char *progname) -*** 826,831 **** ---- 853,860 ---- - printf(_(" --use-set-session-authorization\n" - " use SET SESSION AUTHORIZATION commands instead of\n" - " ALTER OWNER commands to set ownership\n")); -+ printf(_(" --security-label dump SE-PostgreSQL security labels\n")); -+ printf(_(" --security-acl dump row-level database ACLs\n")); - - printf(_("\nConnection options:\n")); - printf(_(" -h, --host=HOSTNAME database server host or socket directory\n")); -*************** dumpTableData_insert(Archive *fout, void -*** 1227,1233 **** - if (fout->remoteVersion >= 70100) - { - appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR " -! "SELECT * FROM ONLY %s", - fmtQualifiedId(tbinfo->dobj.namespace->dobj.name, - classname)); - } ---- 1256,1263 ---- - if (fout->remoteVersion >= 70100) - { - appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR " -! "SELECT %s* FROM ONLY %s", -! (security_context > 0 ? "security_context, " : ""), - fmtQualifiedId(tbinfo->dobj.namespace->dobj.name, - classname)); - } -*************** dumpDatabase(Archive *AH) -*** 1583,1589 **** - i_collate, - i_ctype, - i_frozenxid, -! i_tablespace; - CatalogId dbCatId; - DumpId dbDumpId; - const char *datname, ---- 1613,1620 ---- - i_collate, - i_ctype, - i_frozenxid, -! i_tablespace, -! i_seclabel; - CatalogId dbCatId; - DumpId dbDumpId; - const char *datname, -*************** dumpDatabase(Archive *AH) -*** 1591,1597 **** - *encoding, - *collate, - *ctype, -! *tablespace; - uint32 frozenxid; - - datname = PQdb(g_conn); ---- 1622,1629 ---- - *encoding, - *collate, - *ctype, -! *tablespace, -! *seclabel; - uint32 frozenxid; - - datname = PQdb(g_conn); -*************** dumpDatabase(Archive *AH) -*** 1610,1620 **** - "pg_encoding_to_char(encoding) AS encoding, " - "datcollate, datctype, datfrozenxid, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " -! "shobj_description(oid, 'pg_database') AS description " -! - "FROM pg_database " - "WHERE datname = ", -! username_subquery); - appendStringLiteralAH(dbQry, datname, AH); - } - else if (g_fout->remoteVersion >= 80200) ---- 1642,1653 ---- - "pg_encoding_to_char(encoding) AS encoding, " - "datcollate, datctype, datfrozenxid, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " -! "shobj_description(oid, 'pg_database') AS description, " -! "%s as security_context " - "FROM pg_database " - "WHERE datname = ", -! username_subquery, -! security_context ? "security_context" : "NULL"); - appendStringLiteralAH(dbQry, datname, AH); - } - else if (g_fout->remoteVersion >= 80200) -*************** dumpDatabase(Archive *AH) -*** 1624,1631 **** - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, datfrozenxid, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " -! "shobj_description(oid, 'pg_database') AS description " -! - "FROM pg_database " - "WHERE datname = ", - username_subquery); ---- 1657,1664 ---- - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, datfrozenxid, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " -! "shobj_description(oid, 'pg_database') AS description, " -! "NULL as security_context " - "FROM pg_database " - "WHERE datname = ", - username_subquery); -*************** dumpDatabase(Archive *AH) -*** 1637,1643 **** - "(%s datdba) AS dba, " - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, datfrozenxid, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace " - "FROM pg_database " - "WHERE datname = ", - username_subquery); ---- 1670,1677 ---- - "(%s datdba) AS dba, " - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, datfrozenxid, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = dattablespace) AS tablespace, " -! "NULL as security_context " - "FROM pg_database " - "WHERE datname = ", - username_subquery); -*************** dumpDatabase(Archive *AH) -*** 1650,1656 **** - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, " - "0 AS datfrozenxid, " -! "NULL AS tablespace " - "FROM pg_database " - "WHERE datname = ", - username_subquery); ---- 1684,1691 ---- - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, " - "0 AS datfrozenxid, " -! "NULL AS tablespace, " -! "NULL AS security_context " - "FROM pg_database " - "WHERE datname = ", - username_subquery); -*************** dumpDatabase(Archive *AH) -*** 1665,1671 **** - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, " - "0 AS datfrozenxid, " -! "NULL AS tablespace " - "FROM pg_database " - "WHERE datname = ", - username_subquery); ---- 1700,1707 ---- - "pg_encoding_to_char(encoding) AS encoding, " - "NULL AS datcollate, NULL AS datctype, " - "0 AS datfrozenxid, " -! "NULL AS tablespace, " -! "NULL as security_context " - "FROM pg_database " - "WHERE datname = ", - username_subquery); -*************** dumpDatabase(Archive *AH) -*** 1699,1704 **** ---- 1735,1741 ---- - i_ctype = PQfnumber(res, "datctype"); - i_frozenxid = PQfnumber(res, "datfrozenxid"); - i_tablespace = PQfnumber(res, "tablespace"); -+ i_seclabel = PQfnumber(res, "security_context"); - - dbCatId.tableoid = atooid(PQgetvalue(res, 0, i_tableoid)); - dbCatId.oid = atooid(PQgetvalue(res, 0, i_oid)); -*************** dumpDatabase(Archive *AH) -*** 1708,1713 **** ---- 1745,1751 ---- - ctype = PQgetvalue(res, 0, i_ctype); - frozenxid = atooid(PQgetvalue(res, 0, i_frozenxid)); - tablespace = PQgetvalue(res, 0, i_tablespace); -+ seclabel = PQgetvalue(res, 0, i_seclabel); - - appendPQExpBuffer(creaQry, "CREATE DATABASE %s WITH TEMPLATE = template0", - fmtId(datname)); -*************** dumpDatabase(Archive *AH) -*** 1729,1734 **** ---- 1767,1775 ---- - if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0) - appendPQExpBuffer(creaQry, " TABLESPACE = %s", - fmtId(tablespace)); -+ if (strlen(seclabel) > 0) -+ appendPQExpBuffer(creaQry, " SECURITY_CONTEXT = '%s'", seclabel); -+ - appendPQExpBuffer(creaQry, ";\n"); - - if (binary_upgrade) -*************** getTables(int *numTables) -*** 3190,3195 **** ---- 3231,3237 ---- - int i_reltablespace; - int i_reloptions; - int i_toastreloptions; -+ int i_relseclabel; - - /* Make sure we are in proper schema */ - selectSourceSchema("pg_catalog"); -*************** getTables(int *numTables) -*** 3231,3237 **** - "d.refobjsubid AS owning_col, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "array_to_string(c.reloptions, ', ') AS reloptions, " -! "array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " ---- 3273,3280 ---- - "d.refobjsubid AS owning_col, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "array_to_string(c.reloptions, ', ') AS reloptions, " -! "array_to_string(array(SELECT 'toast.' || x FROM unnest(tc.reloptions) x), ', ') AS toast_reloptions, " -! "%s as security_context " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " -*************** getTables(int *numTables) -*** 3242,3247 **** ---- 3285,3291 ---- - "WHERE c.relkind in ('%c', '%c', '%c', '%c') " - "ORDER BY c.oid", - username_subquery, -+ security_context ? "c.security_context" : "NULL", - RELKIND_SEQUENCE, - RELKIND_RELATION, RELKIND_SEQUENCE, - RELKIND_VIEW, RELKIND_COMPOSITE_TYPE); -*************** getTables(int *numTables) -*** 3263,3269 **** - "d.refobjsubid AS owning_col, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "array_to_string(c.reloptions, ', ') AS reloptions, " -! "NULL AS toast_reloptions " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " ---- 3307,3314 ---- - "d.refobjsubid AS owning_col, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "array_to_string(c.reloptions, ', ') AS reloptions, " -! "NULL AS toast_reloptions, " -! "NULL as security_context " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " -*************** getTables(int *numTables) -*** 3294,3300 **** - "d.refobjsubid AS owning_col, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " ---- 3339,3346 ---- - "d.refobjsubid AS owning_col, " - "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions, " -! "NULL as security_context " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " -*************** getTables(int *numTables) -*** 3325,3331 **** - "d.refobjsubid AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " ---- 3371,3378 ---- - "d.refobjsubid AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions, " -! "NULL as security_context " - "FROM pg_class c " - "LEFT JOIN pg_depend d ON " - "(c.relkind = '%c' AND " -*************** getTables(int *numTables) -*** 3352,3358 **** - "NULL::int4 AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions " - "FROM pg_class " - "WHERE relkind IN ('%c', '%c', '%c') " - "ORDER BY oid", ---- 3399,3406 ---- - "NULL::int4 AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions, " -! "NULL AS security_context " - "FROM pg_class " - "WHERE relkind IN ('%c', '%c', '%c') " - "ORDER BY oid", -*************** getTables(int *numTables) -*** 3374,3380 **** - "NULL::int4 AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions " - "FROM pg_class " - "WHERE relkind IN ('%c', '%c', '%c') " - "ORDER BY oid", ---- 3422,3429 ---- - "NULL::int4 AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions, " -! "NULL AS security_context " - "FROM pg_class " - "WHERE relkind IN ('%c', '%c', '%c') " - "ORDER BY oid", -*************** getTables(int *numTables) -*** 3406,3412 **** - "NULL::int4 AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions " - "FROM pg_class c " - "WHERE relkind IN ('%c', '%c') " - "ORDER BY oid", ---- 3455,3462 ---- - "NULL::int4 AS owning_col, " - "NULL AS reltablespace, " - "NULL AS reloptions, " -! "NULL AS toast_reloptions, " -! "NULL as security_context " - "FROM pg_class c " - "WHERE relkind IN ('%c', '%c') " - "ORDER BY oid", -*************** getTables(int *numTables) -*** 3451,3456 **** ---- 3501,3507 ---- - i_reltablespace = PQfnumber(res, "reltablespace"); - i_reloptions = PQfnumber(res, "reloptions"); - i_toastreloptions = PQfnumber(res, "toast_reloptions"); -+ i_relseclabel = PQfnumber(res, "security_context"); - - if (lockWaitTimeout && g_fout->remoteVersion >= 70300) - { -*************** getTables(int *numTables) -*** 3498,3503 **** ---- 3549,3555 ---- - tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace)); - tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions)); - tblinfo[i].toast_reloptions = strdup(PQgetvalue(res, i, i_toastreloptions)); -+ tblinfo[i].relseclabel = strdup(PQgetvalue(res, i, i_relseclabel)); - - /* other fields were zeroed above */ - -*************** getTableAttrs(TableInfo *tblinfo, int nu -*** 4697,4702 **** ---- 4749,4755 ---- - int i_attlen; - int i_attalign; - int i_attislocal; -+ int i_attseclabel; - PGresult *res; - int ntups; - bool hasdefaults; -*************** getTableAttrs(TableInfo *tblinfo, int nu -*** 4741,4752 **** - "a.attstattarget, a.attstorage, t.typstorage, " - "a.attnotnull, a.atthasdef, a.attisdropped, " - "a.attlen, a.attalign, a.attislocal, " -! "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname " - "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t " - "ON a.atttypid = t.oid " - "WHERE a.attrelid = '%u'::pg_catalog.oid " - "AND a.attnum > 0::pg_catalog.int2 " - "ORDER BY a.attrelid, a.attnum", - tbinfo->dobj.catId.oid); - } - else if (g_fout->remoteVersion >= 70100) ---- 4794,4807 ---- - "a.attstattarget, a.attstorage, t.typstorage, " - "a.attnotnull, a.atthasdef, a.attisdropped, " - "a.attlen, a.attalign, a.attislocal, " -! "pg_catalog.format_type(t.oid,a.atttypmod) AS atttypname, " -! "%s as security_context " - "FROM pg_catalog.pg_attribute a LEFT JOIN pg_catalog.pg_type t " - "ON a.atttypid = t.oid " - "WHERE a.attrelid = '%u'::pg_catalog.oid " - "AND a.attnum > 0::pg_catalog.int2 " - "ORDER BY a.attrelid, a.attnum", -+ security_context ? "a.security_context" : "NULL", - tbinfo->dobj.catId.oid); - } - else if (g_fout->remoteVersion >= 70100) -*************** getTableAttrs(TableInfo *tblinfo, int nu -*** 4761,4767 **** - "t.typstorage, a.attnotnull, a.atthasdef, " - "false AS attisdropped, a.attlen, " - "a.attalign, false AS attislocal, " -! "format_type(t.oid,a.atttypmod) AS atttypname " - "FROM pg_attribute a LEFT JOIN pg_type t " - "ON a.atttypid = t.oid " - "WHERE a.attrelid = '%u'::oid " ---- 4816,4823 ---- - "t.typstorage, a.attnotnull, a.atthasdef, " - "false AS attisdropped, a.attlen, " - "a.attalign, false AS attislocal, " -! "format_type(t.oid,a.atttypmod) AS atttypname, " -! "NULL as security_context " - "FROM pg_attribute a LEFT JOIN pg_type t " - "ON a.atttypid = t.oid " - "WHERE a.attrelid = '%u'::oid " -*************** getTableAttrs(TableInfo *tblinfo, int nu -*** 4778,4784 **** - "attnotnull, atthasdef, false AS attisdropped, " - "attlen, attalign, " - "false AS attislocal, " -! "(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname " - "FROM pg_attribute a " - "WHERE attrelid = '%u'::oid " - "AND attnum > 0::int2 " ---- 4834,4841 ---- - "attnotnull, atthasdef, false AS attisdropped, " - "attlen, attalign, " - "false AS attislocal, " -! "(SELECT typname FROM pg_type WHERE oid = atttypid) AS atttypname, " -! "NULL as security_context " - "FROM pg_attribute a " - "WHERE attrelid = '%u'::oid " - "AND attnum > 0::int2 " -*************** getTableAttrs(TableInfo *tblinfo, int nu -*** 4804,4809 **** ---- 4861,4867 ---- - i_attlen = PQfnumber(res, "attlen"); - i_attalign = PQfnumber(res, "attalign"); - i_attislocal = PQfnumber(res, "attislocal"); -+ i_attseclabel = PQfnumber(res, "security_context"); - - tbinfo->numatts = ntups; - tbinfo->attnames = (char **) malloc(ntups * sizeof(char *)); -*************** getTableAttrs(TableInfo *tblinfo, int nu -*** 4816,4821 **** ---- 4874,4880 ---- - tbinfo->attlen = (int *) malloc(ntups * sizeof(int)); - tbinfo->attalign = (char *) malloc(ntups * sizeof(char)); - tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool)); -+ tbinfo->attseclabel = (char **) malloc(ntups * sizeof(char *)); - tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool)); - tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *)); - tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool)); -*************** getTableAttrs(TableInfo *tblinfo, int nu -*** 4841,4846 **** ---- 4900,4906 ---- - tbinfo->attlen[j] = atoi(PQgetvalue(res, j, i_attlen)); - tbinfo->attalign[j] = *(PQgetvalue(res, j, i_attalign)); - tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't'); -+ tbinfo->attseclabel[j] = strdup(PQgetvalue(res, j, i_attseclabel)); - tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't'); - tbinfo->attrdefs[j] = NULL; /* fix below */ - if (PQgetvalue(res, j, i_atthasdef)[0] == 't') -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7091,7096 **** ---- 7151,7157 ---- - char *proconfig; - char *procost; - char *prorows; -+ char *proseclabel; - char *lanname; - char *rettypename; - int nallargs; -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7127,7135 **** - "pg_catalog.pg_get_function_result(oid) AS funcresult, " - "proiswindow, provolatile, proisstrict, prosecdef, " - "proconfig, procost, prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); - } - else if (g_fout->remoteVersion >= 80300) ---- 7188,7198 ---- - "pg_catalog.pg_get_function_result(oid) AS funcresult, " - "proiswindow, provolatile, proisstrict, prosecdef, " - "proconfig, procost, prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname, " -! "%s as security_context " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", -+ security_context ? "security_context" : "NULL", - finfo->dobj.catId.oid); - } - else if (g_fout->remoteVersion >= 80300) -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7140,7146 **** - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "proconfig, procost, prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); ---- 7203,7210 ---- - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "proconfig, procost, prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname, " -! "NULL AS security_context " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7153,7159 **** - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); ---- 7217,7224 ---- - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname, " -! "NULL AS security_context " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7168,7174 **** - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); ---- 7233,7240 ---- - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname, " -! "NULL AS security_context " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7183,7189 **** - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); ---- 7249,7256 ---- - "false AS proiswindow, " - "provolatile, proisstrict, prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) AS lanname, " -! "NULL AS security_context " - "FROM pg_catalog.pg_proc " - "WHERE oid = '%u'::pg_catalog.oid", - finfo->dobj.catId.oid); -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7200,7206 **** - "proisstrict, " - "false AS prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname " - "FROM pg_proc " - "WHERE oid = '%u'::oid", - finfo->dobj.catId.oid); ---- 7267,7274 ---- - "proisstrict, " - "false AS prosecdef, " - "null AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname, " -! "NULL AS security_context " - "FROM pg_proc " - "WHERE oid = '%u'::oid", - finfo->dobj.catId.oid); -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7217,7223 **** - "false AS proisstrict, " - "false AS prosecdef, " - "NULL AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname " - "FROM pg_proc " - "WHERE oid = '%u'::oid", - finfo->dobj.catId.oid); ---- 7285,7292 ---- - "false AS proisstrict, " - "false AS prosecdef, " - "NULL AS proconfig, 0 AS procost, 0 AS prorows, " -! "(SELECT lanname FROM pg_language WHERE oid = prolang) AS lanname, " -! "NULL AS security_context " - "FROM pg_proc " - "WHERE oid = '%u'::oid", - finfo->dobj.catId.oid); -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7261,7266 **** ---- 7330,7336 ---- - proconfig = PQgetvalue(res, 0, PQfnumber(res, "proconfig")); - procost = PQgetvalue(res, 0, PQfnumber(res, "procost")); - prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows")); -+ proseclabel = PQgetvalue(res, 0, PQfnumber(res, "security_context")); - lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname")); - - /* -*************** dumpFunc(Archive *fout, FuncInfo *finfo) -*** 7419,7424 **** ---- 7489,7497 ---- - if (prosecdef[0] == 't') - appendPQExpBuffer(q, " SECURITY DEFINER"); - -+ if (security_context > 0 && strlen(proseclabel) > 0) -+ appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", proseclabel); -+ - /* - * COST and ROWS are emitted only if present and not default, so as not to - * break backwards-compatibility of the dump without need. Keep this code -*************** dumpTableSchema(Archive *fout, TableInfo -*** 9877,9882 **** ---- 9950,9966 ---- - if (tbinfo->notnull[j] && - (!tbinfo->inhNotNull[j] || binary_upgrade)) - appendPQExpBuffer(q, " NOT NULL"); -+ -+ /* -+ * Security label -- if SE-PostgreSQL enabled -+ */ -+ if (security_context > 0 && -+ strlen(tbinfo->attseclabel[j]) > 0 && -+ strcmp(tbinfo->relseclabel, tbinfo->attseclabel[j]) != 0) -+ appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", -+ tbinfo->attseclabel[j]); -+ -+ actual_atts++; - } - } - -*************** dumpTableSchema(Archive *fout, TableInfo -*** 9939,9944 **** ---- 10023,10031 ---- - appendPQExpBuffer(q, ")"); - } - -+ if (security_context > 0 && strlen(tbinfo->relseclabel) > 0) -+ appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", tbinfo->relseclabel); -+ - appendPQExpBuffer(q, ";\n"); - - /* -*************** fmtCopyColumnList(const TableInfo *ti) -*** 11508,11513 **** ---- 11595,11607 ---- - - appendPQExpBuffer(q, "("); - needComma = false; -+ -+ if (security_context > 0) -+ { -+ appendPQExpBuffer(q, "security_context"); -+ needComma = true; -+ } -+ - for (i = 0; i < numatts; i++) - { - if (attisdropped[i]) -diff -Nrpc base/src/bin/pg_dump/pg_dump.h sepgsql/src/bin/pg_dump/pg_dump.h -*** base/src/bin/pg_dump/pg_dump.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/bin/pg_dump/pg_dump.h Wed Jul 15 20:03:59 2009 -*************** typedef struct _tableInfo -*** 228,233 **** ---- 228,234 ---- - bool hasoids; /* does it have OIDs? */ - uint32 frozenxid; /* for restore frozen xid */ - int ncheck; /* # of CHECK expressions */ -+ char *relseclabel; /* security labels of relation */ - /* these two are set only if table is a sequence owned by a column: */ - Oid owning_tab; /* OID of table owning sequence */ - int owning_col; /* attr # of column owning sequence */ -*************** typedef struct _tableInfo -*** 249,254 **** ---- 250,256 ---- - int *attlen; /* attribute length, used by binary_upgrade */ - char *attalign; /* attribute align, used by binary_upgrade */ - bool *attislocal; /* true if attr has local definition */ -+ char **attseclabel; /* security labels of attributes */ - - /* - * Note: we need to store per-attribute notnull, default, and constraint -diff -Nrpc base/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpall.c -*** base/src/bin/pg_dump/pg_dumpall.c Thu Jun 18 10:20:52 2009 ---- sepgsql/src/bin/pg_dump/pg_dumpall.c Wed Jul 15 20:03:59 2009 -*************** static int no_tablespaces = 0; -*** 69,74 **** ---- 69,77 ---- - static int use_setsessauth = 0; - static int server_version; - -+ static int security_label = 0; -+ static int security_acl = 0; -+ - static FILE *OPF; - static char *filename = NULL; - -*************** main(int argc, char *argv[]) -*** 130,135 **** ---- 133,140 ---- - {"no-tablespaces", no_argument, &no_tablespaces, 1}, - {"role", required_argument, NULL, 3}, - {"use-set-session-authorization", no_argument, &use_setsessauth, 1}, -+ {"security-label", no_argument, &security_label, 1}, -+ {"security-acl", no_argument, &security_acl, 1}, - - {NULL, 0, NULL, 0} - }; -*************** main(int argc, char *argv[]) -*** 283,288 **** ---- 288,297 ---- - no_tablespaces = 1; - else if (strcmp(optarg, "use-set-session-authorization") == 0) - use_setsessauth = 1; -+ else if (strcmp(optarg, "security-label") == 0) -+ security_label = 1; -+ else if (strcmp(optarg, "security-acl") == 0) -+ security_acl = 1; - else - { - fprintf(stderr, -*************** main(int argc, char *argv[]) -*** 328,333 **** ---- 337,346 ---- - appendPQExpBuffer(pgdumpopts, " --no-tablespaces"); - if (use_setsessauth) - appendPQExpBuffer(pgdumpopts, " --use-set-session-authorization"); -+ if (security_label) -+ appendPQExpBuffer(pgdumpopts, " --security-label"); -+ if (security_acl) -+ appendPQExpBuffer(pgdumpopts, " --security-acl"); - - if (optind < argc) - { -*************** main(int argc, char *argv[]) -*** 403,408 **** ---- 416,434 ---- - } - } - -+ if (security_label > 0) -+ { -+ PGresult *res -+ = PQexec(conn, "SHOW sepostgresql"); -+ if (PQresultStatus(res) != PGRES_TUPLES_OK || -+ PQntuples(res) != 1 || -+ strcmp(PQgetvalue(res, 0, 0), "on") != 0) -+ { -+ fprintf(stderr, "SE-PostgreSQL is not available now."); -+ exit(1); -+ } -+ } -+ - /* - * Open the output file if required, otherwise use stdout - */ -*************** dumpCreateDB(PGconn *conn) -*** 1130,1184 **** - - /* Now collect all the information about databases to dump */ - if (server_version >= 80400) -! res = executeQuery(conn, -! "SELECT datname, " - "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "datcollate, datctype, datfrozenxid, " - "datistemplate, datacl, datconnlimit, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " - "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " -! "WHERE datallowconn ORDER BY 1"); - else if (server_version >= 80100) -! res = executeQuery(conn, -! "SELECT datname, " - "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " - "datistemplate, datacl, datconnlimit, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " - "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " - "WHERE datallowconn ORDER BY 1"); - else if (server_version >= 80000) -! res = executeQuery(conn, -! "SELECT datname, " - "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " - "datistemplate, datacl, -1 as datconnlimit, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace " - "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " - "WHERE datallowconn ORDER BY 1"); - else if (server_version >= 70300) -! res = executeQuery(conn, -! "SELECT datname, " - "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " - "datistemplate, datacl, -1 as datconnlimit, " -! "'pg_default' AS dattablespace " - "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " - "WHERE datallowconn ORDER BY 1"); - else if (server_version >= 70100) -! res = executeQuery(conn, -! "SELECT datname, " - "coalesce(" - "(select usename from pg_shadow where usesysid=datdba), " - "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, " - "datistemplate, '' as datacl, -1 as datconnlimit, " -! "'pg_default' AS dattablespace " - "FROM pg_database d " - "WHERE datallowconn ORDER BY 1"); - else ---- 1156,1211 ---- - - /* Now collect all the information about databases to dump */ - if (server_version >= 80400) -! appendPQExpBuffer(buf, "SELECT datname, " - "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "datcollate, datctype, datfrozenxid, " - "datistemplate, datacl, datconnlimit, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace, " -! "%s AS security_label " - "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " -! "WHERE datallowconn ORDER BY 1", -! security_label ? "sepgsql_raw_to_trans(datselabel)" : "null::text"); - else if (server_version >= 80100) -! appendPQExpBuffer(buf, "SELECT datname, " - "coalesce(rolname, (select rolname from pg_authid where oid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " - "datistemplate, datacl, datconnlimit, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace, " -! "null::text " - "FROM pg_database d LEFT JOIN pg_authid u ON (datdba = u.oid) " - "WHERE datallowconn ORDER BY 1"); - else if (server_version >= 80000) -! appendPQExpBuffer(buf, "SELECT datname, " - "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " - "datistemplate, datacl, -1 as datconnlimit, " -! "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace, " -! "null::text " - "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " - "WHERE datallowconn ORDER BY 1"); - else if (server_version >= 70300) -! appendPQExpBuffer(buf, "SELECT datname, " - "coalesce(usename, (select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, datfrozenxid, " - "datistemplate, datacl, -1 as datconnlimit, " -! "'pg_default' AS dattablespace, " -! "null::text " - "FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) " - "WHERE datallowconn ORDER BY 1"); - else if (server_version >= 70100) -! appendPQExpBuffer(buf, "SELECT datname, " - "coalesce(" - "(select usename from pg_shadow where usesysid=datdba), " - "(select usename from pg_shadow where usesysid=(select datdba from pg_database where datname='template0'))), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, " - "datistemplate, '' as datacl, -1 as datconnlimit, " -! "'pg_default' AS dattablespace, " -! "null::text " - "FROM pg_database d " - "WHERE datallowconn ORDER BY 1"); - else -*************** dumpCreateDB(PGconn *conn) -*** 1187,1204 **** - * Note: 7.0 fails to cope with sub-select in COALESCE, so just deal - * with getting a NULL by not printing any OWNER clause. - */ -! res = executeQuery(conn, -! "SELECT datname, " - "(select usename from pg_shadow where usesysid=datdba), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, " - "'f' as datistemplate, " - "'' as datacl, -1 as datconnlimit, " -! "'pg_default' AS dattablespace " - "FROM pg_database d " - "ORDER BY 1"); - } - - for (i = 0; i < PQntuples(res); i++) - { - char *dbname = PQgetvalue(res, i, 0); ---- 1214,1233 ---- - * Note: 7.0 fails to cope with sub-select in COALESCE, so just deal - * with getting a NULL by not printing any OWNER clause. - */ -! appendPQExpBuffer(buf, "SELECT datname, " - "(select usename from pg_shadow where usesysid=datdba), " - "pg_encoding_to_char(d.encoding), " - "null::text AS datcollate, null::text AS datctype, 0 AS datfrozenxid, " - "'f' as datistemplate, " - "'' as datacl, -1 as datconnlimit, " -! "'pg_default' AS dattablespace, " -! "null::text " - "FROM pg_database d " - "ORDER BY 1"); - } - -+ res = PQexec(conn, buf->data); -+ - for (i = 0; i < PQntuples(res); i++) - { - char *dbname = PQgetvalue(res, i, 0); -*************** dumpCreateDB(PGconn *conn) -*** 1211,1216 **** ---- 1240,1246 ---- - char *dbacl = PQgetvalue(res, i, 7); - char *dbconnlimit = PQgetvalue(res, i, 8); - char *dbtablespace = PQgetvalue(res, i, 9); -+ char *dbseclabel = PQgetvalue(res, i, 9); - char *fdbname; - - fdbname = strdup(fmtId(dbname)); -*************** dumpCreateDB(PGconn *conn) -*** 1266,1271 **** ---- 1296,1305 ---- - appendPQExpBuffer(buf, " CONNECTION LIMIT = %s", - dbconnlimit); - -+ if (security_label > 0 && strlen(dbseclabel) > 0) -+ appendPQExpBuffer(buf, " SECURITY_LABEL = '%s'", -+ dbseclabel); -+ - appendPQExpBuffer(buf, ";\n"); - - if (strcmp(dbistemplate, "t") == 0) -diff -Nrpc base/src/include/access/htup.h sepgsql/src/include/access/htup.h -*** base/src/include/access/htup.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/access/htup.h Tue Sep 8 23:55:48 2009 -*************** typedef HeapTupleHeaderData *HeapTupleHe -*** 163,169 **** - #define HEAP_HASVARWIDTH 0x0002 /* has variable-width attribute(s) */ - #define HEAP_HASEXTERNAL 0x0004 /* has external stored attribute(s) */ - #define HEAP_HASOID 0x0008 /* has an object-id field */ -! /* bit 0x0010 is available */ - #define HEAP_COMBOCID 0x0020 /* t_cid is a combo cid */ - #define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */ - #define HEAP_XMAX_SHARED_LOCK 0x0080 /* xmax is shared locker */ ---- 163,169 ---- - #define HEAP_HASVARWIDTH 0x0002 /* has variable-width attribute(s) */ - #define HEAP_HASEXTERNAL 0x0004 /* has external stored attribute(s) */ - #define HEAP_HASOID 0x0008 /* has an object-id field */ -! #define HEAP_HASSECID 0x0010 /* has an security-id field */ - #define HEAP_COMBOCID 0x0020 /* t_cid is a combo cid */ - #define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */ - #define HEAP_XMAX_SHARED_LOCK 0x0080 /* xmax is shared locker */ -*************** do { \ -*** 290,295 **** ---- 290,298 ---- - (tup)->t_choice.t_datum.datum_typmod = (typmod) \ - ) - -+ #define HeapTupleHeaderHasOid(tup) \ -+ ((tup)->t_infomask & HEAP_HASOID) -+ - #define HeapTupleHeaderGetOid(tup) \ - ( \ - ((tup)->t_infomask & HEAP_HASOID) ? \ -*************** do { \ -*** 349,354 **** ---- 352,376 ---- - (tup)->t_infomask2 = ((tup)->t_infomask2 & ~HEAP_NATTS_MASK) | (natts) \ - ) - -+ #define HeapTupleHeaderHasSecid(tup) \ -+ ((tup)->t_infomask & HEAP_HASSECID) -+ -+ #define HeapTupleHeaderGetSecid(tup) \ -+ ( \ -+ HeapTupleHeaderHasSecid(tup) \ -+ ? (*(Oid *)((char *)(tup) + (tup)->t_hoff \ -+ - (HeapTupleHeaderHasOid(tup) ? sizeof(Oid) : 0) \ -+ - sizeof(Oid))) \ -+ : InvalidOid \ -+ ) -+ -+ #define HeapTupleHeaderSetSecid(tup, secid) \ -+ do { \ -+ Assert(HeapTupleHeaderHasSecid(tup)); \ -+ *((Oid *)((char *)(tup) + (tup)->t_hoff \ -+ - (HeapTupleHeaderHasOid(tup) ? sizeof(Oid) : 0) \ -+ - sizeof(Oid))) = (secid); \ -+ } while(0) - - /* - * BITMAPLEN(NATTS) - -*************** typedef HeapTupleData *HeapTuple; -*** 549,554 **** ---- 571,584 ---- - #define HeapTupleSetOid(tuple, oid) \ - HeapTupleHeaderSetOid((tuple)->t_data, (oid)) - -+ #define HeapTupleHasSecid(tuple) \ -+ HeapTupleHeaderHasSecid((tuple)->t_data) -+ -+ #define HeapTupleGetSecid(tuple) \ -+ HeapTupleHeaderGetSecid((tuple)->t_data) -+ -+ #define HeapTupleSetSecid(tuple, secid) \ -+ HeapTupleHeaderSetSecid((tuple)->t_data, (secid)) - - /* - * WAL record definitions for heapam.c's WAL operations -diff -Nrpc base/src/include/access/sysattr.h sepgsql/src/include/access/sysattr.h -*** base/src/include/access/sysattr.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/access/sysattr.h Wed Sep 9 16:47:01 2009 -*************** -*** 25,31 **** - #define MaxTransactionIdAttributeNumber (-5) - #define MaxCommandIdAttributeNumber (-6) - #define TableOidAttributeNumber (-7) -! #define FirstLowInvalidHeapAttributeNumber (-8) - - - #endif /* SYSATTR_H */ ---- 25,43 ---- - #define MaxTransactionIdAttributeNumber (-5) - #define MaxCommandIdAttributeNumber (-6) - #define TableOidAttributeNumber (-7) -! #define SecurityAttributeNumber (-8) -! #define FirstLowInvalidHeapAttributeNumber (-9) - -+ /* -+ * Attribute names for the system-defined attributes -+ */ -+ #define SelfItemPointerAttributeName "ctid" -+ #define ObjectIdAttributeName "oid" -+ #define MinTransactionIdAttributeName "xmin" -+ #define MinCommandIdAttributeName "cmin" -+ #define MaxTransactionIdAttributeName "xmax" -+ #define MaxCommandIdAttributeName "cmax" -+ #define TableOidAttributeName "tableoid" -+ #define SecurityAttributeName "security_context" - - #endif /* SYSATTR_H */ -diff -Nrpc base/src/include/access/tupdesc.h sepgsql/src/include/access/tupdesc.h -*** base/src/include/access/tupdesc.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/access/tupdesc.h Wed Sep 9 13:14:37 2009 -*************** typedef struct tupleDesc -*** 75,80 **** ---- 75,81 ---- - Oid tdtypeid; /* composite type ID for tuple type */ - int32 tdtypmod; /* typmod for tuple type */ - bool tdhasoid; /* tuple has oid attribute in its header */ -+ bool tdhassecid; /* tuple has secid attribute in its header */ - int tdrefcount; /* reference count, or -1 if not counting */ - } *TupleDesc; - -diff -Nrpc base/src/include/catalog/dependency.h sepgsql/src/include/catalog/dependency.h -*** base/src/include/catalog/dependency.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/catalog/dependency.h Thu Jul 16 17:22:29 2009 -*************** typedef enum ObjectClass -*** 155,160 **** ---- 155,163 ---- - extern void performDeletion(const ObjectAddress *object, - DropBehavior behavior); - -+ extern void performDeletionNoPerms(const ObjectAddress *object, -+ DropBehavior behavior); -+ - extern void performMultipleDeletions(const ObjectAddresses *objects, - DropBehavior behavior); - -diff -Nrpc base/src/include/catalog/heap.h sepgsql/src/include/catalog/heap.h -*** base/src/include/catalog/heap.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/catalog/heap.h Wed Jul 15 19:38:52 2009 -*************** extern Oid heap_create_with_catalog(cons -*** 56,62 **** - int oidinhcount, - OnCommitAction oncommit, - Datum reloptions, -! bool allow_system_table_mods); - - extern void heap_drop_with_catalog(Oid relid); - ---- 56,63 ---- - int oidinhcount, - OnCommitAction oncommit, - Datum reloptions, -! bool allow_system_table_mods, -! Oid *secLabels); - - extern void heap_drop_with_catalog(Oid relid); - -*************** extern List *heap_truncate_find_FKs(List -*** 68,79 **** - - extern void InsertPgAttributeTuple(Relation pg_attribute_rel, - Form_pg_attribute new_attribute, -! CatalogIndexState indstate); - - extern void InsertPgClassTuple(Relation pg_class_desc, - Relation new_rel_desc, - Oid new_rel_oid, -! Datum reloptions); - - extern List *AddRelationNewConstraints(Relation rel, - List *newColDefaults, ---- 69,82 ---- - - extern void InsertPgAttributeTuple(Relation pg_attribute_rel, - Form_pg_attribute new_attribute, -! CatalogIndexState indstate, -! Oid new_att_secid); - - extern void InsertPgClassTuple(Relation pg_class_desc, - Relation new_rel_desc, - Oid new_rel_oid, -! Datum reloptions, -! Oid new_rel_secid); - - extern List *AddRelationNewConstraints(Relation rel, - List *newColDefaults, -*************** extern Form_pg_attribute SystemAttribute -*** 103,108 **** ---- 106,113 ---- - extern Form_pg_attribute SystemAttributeByName(const char *attname, - bool relhasoids); - -+ extern bool SystemAttributeIsWritable(AttrNumber attnum); -+ - extern void CheckAttributeNamesTypes(TupleDesc tupdesc, char relkind); - - extern void CheckAttributeType(const char *attname, Oid atttypid); -diff -Nrpc base/src/include/catalog/indexing.h sepgsql/src/include/catalog/indexing.h -*** base/src/include/catalog/indexing.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/catalog/indexing.h Wed Jul 15 19:30:50 2009 -*************** DECLARE_UNIQUE_INDEX(pg_type_oid_index, -*** 249,254 **** ---- 249,259 ---- - DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, on pg_type using btree(typname name_ops, typnamespace oid_ops)); - #define TypeNameNspIndexId 2704 - -+ DECLARE_UNIQUE_INDEX(pg_security_secid_index, 3401, on pg_security using btree(secid oid_ops, datid oid_ops, relid oid_ops)); -+ #define SecuritySecidIndexId 3401 -+ DECLARE_UNIQUE_INDEX(pg_security_secattr_index, 3402, on pg_security using btree(datid oid_ops, relid oid_ops, seckind char_ops, secattr text_ops)); -+ #define SecuritySecattrIndexId 3402 -+ - DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_oid_index, 112, on pg_foreign_data_wrapper using btree(oid oid_ops)); - #define ForeignDataWrapperOidIndexId 112 - -diff -Nrpc base/src/include/catalog/pg_attribute.h sepgsql/src/include/catalog/pg_attribute.h -*** base/src/include/catalog/pg_attribute.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/catalog/pg_attribute.h Thu Sep 10 15:29:52 2009 -*************** DATA(insert ( 1247 cmin 29 0 4 -4 0 -*** 276,281 **** ---- 276,282 ---- - DATA(insert ( 1247 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1247 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1247 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_)); -+ DATA(insert ( 1247 security_context 25 0 -1 -8 0 -1 -1 f x i t f f t 0 _null_)); - - /* ---------------- - * pg_proc -*************** DATA(insert ( 1255 cmin 29 0 4 -4 0 -*** 340,345 **** ---- 341,347 ---- - DATA(insert ( 1255 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1255 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1255 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_)); -+ DATA(insert ( 1255 security_context 25 0 -1 -8 0 -1 -1 f x i t f f t 0 _null_)); - - /* ---------------- - * pg_attribute -*************** DATA(insert ( 1249 cmin 29 0 4 -4 0 -*** 390,395 **** ---- 392,398 ---- - DATA(insert ( 1249 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1249 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1249 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_)); -+ DATA(insert ( 1249 security_context 25 0 -1 -8 0 -1 -1 f x i t f f t 0 _null_)); - - /* ---------------- - * pg_class -*************** DATA(insert ( 1259 cmin 29 0 4 -4 0 -*** 454,459 **** ---- 457,463 ---- - DATA(insert ( 1259 xmax 28 0 4 -5 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1259 cmax 29 0 4 -6 0 -1 -1 t p i t f f t 0 _null_)); - DATA(insert ( 1259 tableoid 26 0 4 -7 0 -1 -1 t p i t f f t 0 _null_)); -+ DATA(insert ( 1259 security_context 25 0 -1 -8 0 -1 -1 f x i t f f t 0 _null_)); - - /* ---------------- - * pg_index -diff -Nrpc base/src/include/catalog/pg_namespace.h sepgsql/src/include/catalog/pg_namespace.h -*** base/src/include/catalog/pg_namespace.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/catalog/pg_namespace.h Wed Jul 15 19:35:52 2009 -*************** DESCR("standard public schema"); -*** 77,82 **** - /* - * prototypes for functions in pg_namespace.c - */ -! extern Oid NamespaceCreate(const char *nspName, Oid ownerId); - - #endif /* PG_NAMESPACE_H */ ---- 77,82 ---- - /* - * prototypes for functions in pg_namespace.c - */ -! extern Oid NamespaceCreate(const char *nspName, Oid ownerId, Oid nspsecid); - - #endif /* PG_NAMESPACE_H */ -diff -Nrpc base/src/include/catalog/pg_proc.h sepgsql/src/include/catalog/pg_proc.h -*** base/src/include/catalog/pg_proc.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/catalog/pg_proc.h Wed Jul 15 20:03:59 2009 -*************** DATA(insert OID = 958 ( lo_tell PGN -*** 1226,1231 **** ---- 1226,1235 ---- - DESCR("large object position"); - DATA(insert OID = 1004 ( lo_truncate PGNSP PGUID 12 1 0 0 f f f t f v 2 0 23 "23 23" _null_ _null_ _null_ _null_ lo_truncate _null_ _null_ _null_ )); - DESCR("truncate large object"); -+ DATA(insert OID = 1029 ( lo_get_security PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "26" _null_ _null_ _null_ _null_ lo_get_security _null_ _null_ _null_ )); -+ DESCR("get security label of large object"); -+ DATA(insert OID = 1030 ( lo_set_security PGNSP PGUID 12 1 0 0 f f f t f v 2 0 16 "26 25" _null_ _null_ _null_ _null_ lo_set_security _null_ _null_ _null_ )); -+ DESCR("set security label of large object"); - - DATA(insert OID = 959 ( on_pl PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "600 628" _null_ _null_ _null_ _null_ on_pl _null_ _null_ _null_ )); - DESCR("point on line?"); -*************** DESCR("I/O"); -*** 4335,4340 **** ---- 4339,4361 ---- - DATA(insert OID = 2963 ( uuid_hash PGNSP PGUID 12 1 0 0 f f f t f i 1 0 23 "2950" _null_ _null_ _null_ _null_ uuid_hash _null_ _null_ _null_ )); - DESCR("hash"); - -+ /* Security attribute reclaimer */ -+ DATA(insert OID = 3411 ( security_reclaim_label PGNSP PGUID 12 1 0 0 f f f t f v 0 0 23 "" _null_ _null_ _null_ _null_ security_reclaim_label _null_ _null_ _null_ )); -+ DATA(insert OID = 3413 ( security_reclaim_label PGNSP PGUID 12 1 0 0 f f f t f v 1 0 23 "2205" _null_ _null_ _null_ _null_ security_reclaim_table_label _null_ _null_ _null_ )); -+ DATA(insert OID = 3415 ( security_label_to_secid PGNSP PGUID 12 1 0 0 f f f t f v 1 0 26 "2249" _null_ _null_ _null_ _null_ security_label_to_secid _null_ _null_ _null_ )); -+ -+ /* SE-PostgreSQL related functions */ -+ DATA(insert OID = 3416 ( sepgsql_getcon PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ sepgsql_getcon _null_ _null_ _null_ )); -+ DATA(insert OID = 3417 ( sepgsql_server_getcon PGNSP PGUID 12 1 0 0 f f f t f v 0 0 25 "" _null_ _null_ _null_ _null_ sepgsql_server_getcon _null_ _null_ _null_ )); -+ DATA(insert OID = 3418 ( sepgsql_get_user PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "25" _null_ _null_ _null_ _null_ sepgsql_get_user _null_ _null_ _null_ )); -+ DATA(insert OID = 3419 ( sepgsql_set_user PGNSP PGUID 12 1 0 0 f f f t f v 2 0 25 "25 25" _null_ _null_ _null_ _null_ sepgsql_set_user _null_ _null_ _null_ )); -+ DATA(insert OID = 3420 ( sepgsql_get_role PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "25" _null_ _null_ _null_ _null_ sepgsql_get_role _null_ _null_ _null_ )); -+ DATA(insert OID = 3421 ( sepgsql_set_role PGNSP PGUID 12 1 0 0 f f f t f v 2 0 25 "25 25" _null_ _null_ _null_ _null_ sepgsql_set_role _null_ _null_ _null_ )); -+ DATA(insert OID = 3422 ( sepgsql_get_type PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "25" _null_ _null_ _null_ _null_ sepgsql_get_type _null_ _null_ _null_ )); -+ DATA(insert OID = 3423 ( sepgsql_set_type PGNSP PGUID 12 1 0 0 f f f t f v 2 0 25 "25 25" _null_ _null_ _null_ _null_ sepgsql_set_type _null_ _null_ _null_ )); -+ DATA(insert OID = 3424 ( sepgsql_get_range PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "25" _null_ _null_ _null_ _null_ sepgsql_get_range _null_ _null_ _null_ )); -+ DATA(insert OID = 3425 ( sepgsql_set_range PGNSP PGUID 12 1 0 0 f f f t f v 2 0 25 "25 25" _null_ _null_ _null_ _null_ sepgsql_set_range _null_ _null_ _null_ )); -+ - /* enum related procs */ - DATA(insert OID = 3504 ( anyenum_in PGNSP PGUID 12 1 0 0 f f f t f i 1 0 3500 "2275" _null_ _null_ _null_ _null_ anyenum_in _null_ _null_ _null_ )); - DESCR("I/O"); -diff -Nrpc base/src/include/catalog/pg_proc_fn.h sepgsql/src/include/catalog/pg_proc_fn.h -*** base/src/include/catalog/pg_proc_fn.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/catalog/pg_proc_fn.h Wed Jul 15 19:37:35 2009 -*************** extern Oid ProcedureCreate(const char *p -*** 37,43 **** - List *parameterDefaults, - Datum proconfig, - float4 procost, -! float4 prorows); - - extern bool function_parse_error_transpose(const char *prosrc); - ---- 37,44 ---- - List *parameterDefaults, - Datum proconfig, - float4 procost, -! float4 prorows, -! Node *proseclabel); - - extern bool function_parse_error_transpose(const char *prosrc); - -diff -Nrpc base/src/include/catalog/pg_security.h sepgsql/src/include/catalog/pg_security.h -*** base/src/include/catalog/pg_security.h Thu Jan 1 09:00:00 1970 ---- sepgsql/src/include/catalog/pg_security.h Thu Sep 10 15:18:03 2009 -*************** -*** 0 **** ---- 1,101 ---- -+ /* -+ * src/include/catalog/pg_security.h -+ * Definition of the security label relation (pg_security) -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #ifndef PG_SECURITY_H -+ #define PG_SECURITY_H -+ -+ #include "catalog/genbki.h" -+ -+ #include "access/htup.h" -+ #include "nodes/parsenodes.h" -+ #include "utils/acl.h" -+ #include "utils/relcache.h" -+ -+ #define SecurityRelationId 3400 -+ -+ CATALOG(pg_security,3400) BKI_SHARED_RELATION BKI_WITHOUT_OIDS -+ { -+ /* Identifier of the security attribute */ -+ Oid secid; -+ -+ /* OID of the database which referes the entry */ -+ Oid datid; -+ -+ /* OID of the table which refers the entry */ -+ Oid relid; -+ -+ /* See the SECKIND_SECURITY_* definition */ -+ char seckind; -+ -+ /* Text representation of security attribute */ -+ text secattr; -+ } FormData_pg_security; -+ -+ /* -+ * Form_pg_security corresponds to a pointer to a tuple with -+ * the format of pg_security relation. -+ */ -+ typedef FormData_pg_security *Form_pg_security; -+ -+ /* -+ * Compiler constants for pg_security -+ */ -+ #define Natts_pg_security 5 -+ #define Anum_pg_security_secid 1 -+ #define Anum_pg_security_datid 2 -+ #define Anum_pg_security_relid 3 -+ #define Anum_pg_security_seckind 4 -+ #define Anum_pg_security_secattr 5 -+ -+ /* -+ * Compiler constants for pg_security.seckind -+ */ -+ #define SECKIND_SECURITY_LABEL 'l' -+ -+ /* -+ * Functions to translate between security label and identifier -+ */ -+ extern void -+ securityPostBootstrapingMode(void); -+ -+ extern void -+ securityOnCreateDatabase(Oid src_datid, Oid dst_datid); -+ -+ extern void -+ securityOnDropDatabase(Oid datid); -+ -+ extern bool -+ securityTupleDescHasSecid(Oid relid, char relkind); -+ -+ extern Oid -+ securityRawSecLabelIn(Oid relid, char *seclabel); -+ -+ extern char * -+ securityRawSecLabelOut(Oid relid, Oid secid); -+ -+ extern Oid -+ securityTransSecLabelIn(Oid relid, char *seclabel); -+ -+ extern char * -+ securityTransSecLabelOut(Oid relid, Oid secid); -+ -+ extern Datum -+ securitySysattSecLabelOut(Oid relid, HeapTuple tuple); -+ -+ extern void -+ securityReclaimOnDropTable(Oid relid); -+ -+ extern Datum -+ security_reclaim_label(PG_FUNCTION_ARGS); -+ -+ extern Datum -+ security_reclaim_table_label(PG_FUNCTION_ARGS); -+ -+ extern Datum -+ security_label_to_secid(PG_FUNCTION_ARGS); -+ -+ #endif /* PG_SECURITY_H */ -diff -Nrpc base/src/include/catalog/toasting.h sepgsql/src/include/catalog/toasting.h -*** base/src/include/catalog/toasting.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/catalog/toasting.h Wed Jul 15 19:30:50 2009 -*************** DECLARE_TOAST(pg_database, 2844, 2845); -*** 58,62 **** ---- 58,65 ---- - DECLARE_TOAST(pg_shdescription, 2846, 2847); - #define PgShdescriptionToastTable 2846 - #define PgShdescriptionToastIndex 2847 -+ DECLARE_TOAST(pg_security, 3403, 3404); -+ #define PgSecurityToastTable 3403 -+ #define PgSecurityToastIndex 3404 - - #endif /* TOASTING_H */ -diff -Nrpc base/src/include/commands/alter.h sepgsql/src/include/commands/alter.h -*** base/src/include/commands/alter.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/commands/alter.h Wed Jul 15 19:37:35 2009 -*************** -*** 19,23 **** ---- 19,24 ---- - extern void ExecRenameStmt(RenameStmt *stmt); - extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt); - extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt); -+ extern void ExecAlterSecLabelStmt(AlterSecLabelStmt *stmt); - - #endif /* ALTER_H */ -diff -Nrpc base/src/include/commands/dbcommands.h sepgsql/src/include/commands/dbcommands.h -*** base/src/include/commands/dbcommands.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/commands/dbcommands.h Wed Jul 15 19:37:35 2009 -*************** extern void RenameDatabase(const char *o -*** 58,63 **** ---- 58,64 ---- - extern void AlterDatabase(AlterDatabaseStmt *stmt, bool isTopLevel); - extern void AlterDatabaseSet(AlterDatabaseSetStmt *stmt); - extern void AlterDatabaseOwner(const char *dbname, Oid newOwnerId); -+ extern void AlterDatabaseSecLabel(const char *dbname, DefElem *seclabel); - - extern Oid get_database_oid(const char *dbname); - extern char *get_database_name(Oid dbid); -diff -Nrpc base/src/include/commands/defrem.h sepgsql/src/include/commands/defrem.h -*** base/src/include/commands/defrem.h Thu Apr 9 00:13:21 2009 ---- sepgsql/src/include/commands/defrem.h Wed Jul 15 19:37:35 2009 -*************** extern void SetFunctionArgType(Oid funcO -*** 53,58 **** ---- 53,59 ---- - extern void RenameFunction(List *name, List *argtypes, const char *newname); - extern void AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId); - extern void AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId); -+ extern void AlterFunctionSecLabel(List *name, List *argtypes, DefElem *seclabel); - extern void AlterFunction(AlterFunctionStmt *stmt); - extern void CreateCast(CreateCastStmt *stmt); - extern void DropCast(DropCastStmt *stmt); -diff -Nrpc base/src/include/commands/schemacmds.h sepgsql/src/include/commands/schemacmds.h -*** base/src/include/commands/schemacmds.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/commands/schemacmds.h Wed Jul 15 19:37:35 2009 -*************** extern void RemoveSchemaById(Oid schemaO -*** 26,30 **** ---- 26,31 ---- - extern void RenameSchema(const char *oldname, const char *newname); - extern void AlterSchemaOwner(const char *name, Oid newOwnerId); - extern void AlterSchemaOwner_oid(Oid schemaOid, Oid newOwnerId); -+ extern void AlterSchemaSecLabel(const char *name, DefElem *seclabel); - - #endif /* SCHEMACMDS_H */ -diff -Nrpc base/src/include/commands/tablecmds.h sepgsql/src/include/commands/tablecmds.h -*** base/src/include/commands/tablecmds.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/commands/tablecmds.h Wed Jul 15 19:37:35 2009 -*************** extern void AlterRelationNamespaceIntern -*** 35,40 **** ---- 35,43 ---- - Oid oldNspOid, Oid newNspOid, - bool hasDependEntry); - -+ extern void AlterRelationSecLabel(RangeVar *relation, const char *attname, -+ ObjectType objtype, DefElem *seclabel); -+ - extern void CheckTableNotInUse(Relation rel, const char *stmt); - - extern void ExecuteTruncate(TruncateStmt *stmt); -diff -Nrpc base/src/include/executor/executor.h sepgsql/src/include/executor/executor.h -*** base/src/include/executor/executor.h Sun Sep 6 19:40:49 2009 ---- sepgsql/src/include/executor/executor.h Wed Sep 9 13:14:37 2009 -*************** extern TupleHashEntry FindTupleHashEntry -*** 130,136 **** - /* - * prototypes from functions in execJunk.c - */ -! extern JunkFilter *ExecInitJunkFilter(List *targetList, bool hasoid, - TupleTableSlot *slot); - extern JunkFilter *ExecInitJunkFilterConversion(List *targetList, - TupleDesc cleanTupType, ---- 130,136 ---- - /* - * prototypes from functions in execJunk.c - */ -! extern JunkFilter *ExecInitJunkFilter(List *targetList, bool hasoid, bool hasseclabel, - TupleTableSlot *slot); - extern JunkFilter *ExecInitJunkFilterConversion(List *targetList, - TupleDesc cleanTupType, -*************** extern void InitResultRelInfo(ResultRelI -*** 163,168 **** ---- 163,169 ---- - bool doInstrument); - extern ResultRelInfo *ExecGetTriggerResultRel(EState *estate, Oid relid); - extern bool ExecContextForcesOids(PlanState *planstate, bool *hasoids); -+ extern bool ExecContextForcesSecids(PlanState *planstate, bool *hassecids); - extern void ExecConstraints(ResultRelInfo *resultRelInfo, - TupleTableSlot *slot, EState *estate); - extern TupleTableSlot *EvalPlanQual(EState *estate, Index rti, -*************** extern void ExecInitScanTupleSlot(EState -*** 216,223 **** - extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); - extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, - TupleDesc tupType); -! extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid); -! extern TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid); - extern TupleDesc ExecTypeFromExprList(List *exprList); - extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg); - ---- 217,224 ---- - extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate); - extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, - TupleDesc tupType); -! extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid, bool hasseclabel); -! extern TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid, bool hasseclabel); - extern TupleDesc ExecTypeFromExprList(List *exprList); - extern void UpdateChangedParamSet(PlanState *node, Bitmapset *newchg); - -diff -Nrpc base/src/include/executor/tuptable.h sepgsql/src/include/executor/tuptable.h -*** base/src/include/executor/tuptable.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/executor/tuptable.h Wed Jul 15 19:38:52 2009 -*************** typedef struct TupleTableSlot -*** 127,132 **** ---- 127,133 ---- - MinimalTuple tts_mintuple; /* minimal tuple, or NULL if none */ - HeapTupleData tts_minhdr; /* workspace for minimal-tuple-only case */ - long tts_off; /* saved state for slot_deform_tuple */ -+ Datum tts_seclabel; /* temp storage for the given security_label */ - } TupleTableSlot; - - #define TTS_HAS_PHYSICAL_TUPLE(slot) \ -diff -Nrpc base/src/include/libpq/be-fsstubs.h sepgsql/src/include/libpq/be-fsstubs.h -*** base/src/include/libpq/be-fsstubs.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/libpq/be-fsstubs.h Wed Jul 15 19:48:58 2009 -*************** extern Datum lo_tell(PG_FUNCTION_ARGS); -*** 37,42 **** ---- 37,45 ---- - extern Datum lo_unlink(PG_FUNCTION_ARGS); - extern Datum lo_truncate(PG_FUNCTION_ARGS); - -+ extern Datum lo_get_security(PG_FUNCTION_ARGS); -+ extern Datum lo_set_security(PG_FUNCTION_ARGS); -+ - /* - * These are not fmgr-callable, but are available to C code. - * Probably these should have had the underscore-free names, -diff -Nrpc base/src/include/nodes/nodes.h sepgsql/src/include/nodes/nodes.h -*** base/src/include/nodes/nodes.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/nodes/nodes.h Wed Jul 15 19:37:35 2009 -*************** typedef enum NodeTag -*** 337,342 **** ---- 337,343 ---- - T_CreateUserMappingStmt, - T_AlterUserMappingStmt, - T_DropUserMappingStmt, -+ T_AlterSecLabelStmt, - - /* - * TAGS FOR PARSE TREE NODES (parsenodes.h) -diff -Nrpc base/src/include/nodes/parsenodes.h sepgsql/src/include/nodes/parsenodes.h -*** base/src/include/nodes/parsenodes.h Fri Jun 19 13:40:37 2009 ---- sepgsql/src/include/nodes/parsenodes.h Wed Jul 15 19:37:35 2009 -*************** typedef struct ColumnDef -*** 464,469 **** ---- 464,470 ---- - Node *raw_default; /* default value (untransformed parse tree) */ - char *cooked_default; /* nodeToString representation */ - List *constraints; /* other constraints on column */ -+ Node *secLabel; /* security label of column */ - } ColumnDef; - - /* -*************** typedef struct CreateSchemaStmt -*** 1070,1075 **** ---- 1071,1077 ---- - NodeTag type; - char *schemaname; /* the name of the schema to create */ - char *authid; /* the owner of the created schema */ -+ Node *secLabel; /* explicitly specified security label */ - List *schemaElts; /* schema components (list of parsenodes) */ - } CreateSchemaStmt; - -*************** typedef struct CreateStmt -*** 1335,1340 **** ---- 1337,1343 ---- - List *options; /* options from WITH clause */ - OnCommitAction oncommit; /* what do we do at COMMIT? */ - char *tablespacename; /* table space to use, or NULL */ -+ Node *secLabel; /* explicitly specified security label */ - } CreateStmt; - - /* ---------- -*************** typedef struct CreateSeqStmt -*** 1639,1644 **** ---- 1642,1648 ---- - NodeTag type; - RangeVar *sequence; /* the sequence to create */ - List *options; -+ Node *secLabel; - } CreateSeqStmt; - - typedef struct AlterSeqStmt -*************** typedef struct AlterOwnerStmt -*** 1993,1998 **** ---- 1997,2016 ---- - char *newowner; /* the new owner */ - } AlterOwnerStmt; - -+ /* ---------------------- -+ * Alter Object Security Label Statement -+ * ---------------------- -+ */ -+ typedef struct AlterSecLabelStmt -+ { -+ NodeTag type; -+ ObjectType objectType; /* OBJECT_TABLE, OBJECT_COLUMN, etc */ -+ RangeVar *relation; /* in case it's a table */ -+ List *object; /* in case it's some other object */ -+ List *objarg; /* argument types, if applicable */ -+ char *subname; /* column name, if needed */ -+ Node *secLabel; /* the new security label */ -+ } AlterSecLabelStmt; - - /* ---------------------- - * Create Rule Statement -diff -Nrpc base/src/include/nodes/plannodes.h sepgsql/src/include/nodes/plannodes.h -*** base/src/include/nodes/plannodes.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/nodes/plannodes.h Wed Jul 15 19:39:56 2009 -*************** -*** 16,21 **** ---- 16,22 ---- - - #include "access/sdir.h" - #include "nodes/bitmapset.h" -+ #include "nodes/parsenodes.h" - #include "nodes/primnodes.h" - #include "storage/itemptr.h" - -*************** typedef struct Scan -*** 239,244 **** ---- 240,251 ---- - { - Plan plan; - Index scanrelid; /* relid is index into the range table */ -+ -+ /* -+ * Row-level access control stuff. Zero means we don't need -+ * to apply row-level access control on the Scan. -+ */ -+ uint32 rowlvPerms; - } Scan; - - /* ---------------- -diff -Nrpc base/src/include/nodes/relation.h sepgsql/src/include/nodes/relation.h -*** base/src/include/nodes/relation.h Thu Jun 18 10:20:52 2009 ---- sepgsql/src/include/nodes/relation.h Wed Jul 15 19:39:56 2009 -*************** typedef struct RelOptInfo -*** 383,388 **** ---- 383,397 ---- - * list just to avoid recomputing the best inner indexscan repeatedly for - * similar outer relations. See comments for InnerIndexscanInfo. - */ -+ -+ /* -+ * Permissions used in Row-level access control features both of DAC -+ * and MAC. The lower 16bit is used for DAC, and rest of upper bits -+ * are used for MAC. When rowlvPerms is zero, so it means we don't need -+ * to apply the row-level stuff on the relation in both of levels. -+ * It can be used as a hint for optimization stuff. -+ */ -+ uint32 rowlvPerms; - } RelOptInfo; - - /* -diff -Nrpc base/src/include/pg_config.h.in sepgsql/src/include/pg_config.h.in -*** base/src/include/pg_config.h.in Thu Apr 9 00:13:21 2009 ---- sepgsql/src/include/pg_config.h.in Wed Jul 15 19:35:52 2009 -*************** -*** 391,396 **** ---- 391,399 ---- - /* Define to 1 if you have the header file. */ - #undef HAVE_SECURITY_PAM_APPL_H - -+ /* Define to 1 if you enable SELinux support */ -+ #undef HAVE_SELINUX -+ - /* Define to 1 if you have the `setproctitle' function. */ - #undef HAVE_SETPROCTITLE - -diff -Nrpc base/src/include/security/rowlevel.h sepgsql/src/include/security/rowlevel.h -*** base/src/include/security/rowlevel.h Thu Jan 1 09:00:00 1970 ---- sepgsql/src/include/security/rowlevel.h Thu Jul 16 17:22:29 2009 -*************** -*** 0 **** ---- 1,44 ---- -+ /* -+ * src/include/security/rowlevel.h -+ * Definition of the facility of row-level access controls -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #ifndef ROWLEVEL_H -+ #define ROWLEVEL_H -+ -+ #include "access/htup.h" -+ #include "executor/tuptable.h" -+ #include "nodes/plannodes.h" -+ #include "utils/relcache.h" -+ -+ #define ROWLV_BYPASS_MODE 1 -+ #define ROWLV_FILTER_MODE 2 -+ #define ROWLV_ABORT_MODE 3 -+ -+ extern int -+ rowlvGetPerformingMode(void); -+ -+ extern int -+ rowlvSetPerformingMode(int mode); -+ -+ extern uint32 -+ rowlvSetupPermissions(RangeTblEntry *rte); -+ -+ extern bool -+ rowlvExecScanFilter(Scan *scan, Relation rel, TupleTableSlot *slot); -+ -+ extern void -+ rowlvExecScanAbort(Scan *scan, Relation rel, TupleTableSlot *slot); -+ -+ extern void -+ rowlvHeapTupleInsert(Relation rel, HeapTuple newtup, bool internal); -+ -+ extern void -+ rowlvHeapTupleUpdate(Relation rel, ItemPointer otid, HeapTuple newtup); -+ -+ extern bool -+ rowlvCopyToTuple(Relation rel, HeapTuple tuple); -+ -+ #endif /* ROWLEVEL_H */ -diff -Nrpc base/src/include/security/sepgsql.h sepgsql/src/include/security/sepgsql.h -*** base/src/include/security/sepgsql.h Thu Jan 1 09:00:00 1970 ---- sepgsql/src/include/security/sepgsql.h Thu Sep 10 15:18:03 2009 -*************** -*** 0 **** ---- 1,534 ---- -+ /* -+ * src/include/security/sepgsql.h -+ * Headers of SE-PostgreSQL -+ * -+ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group -+ * Portions Copyright (c) 1994, Regents of the University of California -+ */ -+ #ifndef SEPGSQL_H -+ #define SEPGSQL_H -+ -+ #include "access/htup.h" -+ #include "catalog/dependency.h" -+ #include "executor/execdesc.h" -+ #include "fmgr.h" -+ #include "nodes/parsenodes.h" -+ #include "storage/large_object.h" -+ #include "utils/relcache.h" -+ -+ #ifdef HAVE_SELINUX -+ -+ #include -+ -+ /* GUC parameter to turn on/off SE-PostgreSQL */ -+ extern bool sepostgresql_is_enabled; -+ -+ /* GUC parameter to turn on/off Row-level controls */ -+ extern bool sepostgresql_row_level; -+ -+ /* GUC parameter to turn on/off mcstrans */ -+ extern bool sepostgresql_use_mcstrans; -+ -+ /* Objject classes and permissions internally used */ -+ enum SepgsqlClasses -+ { -+ SEPG_CLASS_PROCESS = 0, -+ SEPG_CLASS_FILE, -+ SEPG_CLASS_DIR, -+ SEPG_CLASS_LNK_FILE, -+ SEPG_CLASS_CHR_FILE, -+ SEPG_CLASS_BLK_FILE, -+ SEPG_CLASS_SOCK_FILE, -+ SEPG_CLASS_FIFO_FILE, -+ SEPG_CLASS_DB_DATABASE, -+ SEPG_CLASS_DB_SCHEMA, -+ SEPG_CLASS_DB_SCHEMA_TEMP, -+ SEPG_CLASS_DB_TABLE, -+ SEPG_CLASS_DB_SEQUENCE, -+ SEPG_CLASS_DB_PROCEDURE, -+ SEPG_CLASS_DB_COLUMN, -+ SEPG_CLASS_DB_TUPLE, -+ SEPG_CLASS_DB_BLOB, -+ SEPG_CLASS_MAX, -+ }; -+ -+ #define SEPG_PROCESS__TRANSITION (1<<0) -+ -+ #define SEPG_FILE__READ (1<<0) -+ #define SEPG_FILE__WRITE (1<<1) -+ -+ #define SEPG_DIR__READ (SEPG_FILE__READ) -+ #define SEPG_DIR__WRITE (SEPG_FILE__WRITE) -+ -+ #define SEPG_LNK_FILE__READ (SEPG_FILE__READ) -+ #define SEPG_LNK_FILE__WRITE (SEPG_FILE__WRITE) -+ -+ #define SEPG_CHR_FILE__READ (SEPG_FILE__READ) -+ #define SEPG_CHR_FILE__WRITE (SEPG_FILE__WRITE) -+ -+ #define SEPG_BLK_FILE__READ (SEPG_FILE__READ) -+ #define SEPG_BLK_FILE__WRITE (SEPG_FILE__WRITE) -+ -+ #define SEPG_SOCK_FILE__READ (SEPG_FILE__READ) -+ #define SEPG_SOCK_FILE__WRITE (SEPG_FILE__WRITE) -+ -+ #define SEPG_FIFO_FILE__READ (SEPG_FILE__READ) -+ #define SEPG_FIFO_FILE__WRITE (SEPG_FILE__WRITE) -+ -+ #define SEPG_DB_DATABASE__CREATE (1<<0) -+ #define SEPG_DB_DATABASE__DROP (1<<1) -+ #define SEPG_DB_DATABASE__GETATTR (1<<2) -+ #define SEPG_DB_DATABASE__SETATTR (1<<3) -+ #define SEPG_DB_DATABASE__RELABELFROM (1<<4) -+ #define SEPG_DB_DATABASE__RELABELTO (1<<5) -+ #define SEPG_DB_DATABASE__ACCESS (1<<6) -+ #define SEPG_DB_DATABASE__INSTALL_MODULE (1<<7) -+ #define SEPG_DB_DATABASE__LOAD_MODULE (1<<8) -+ #define SEPG_DB_DATABASE__SUPERUSER (1<<9) -+ -+ #define SEPG_DB_SCHEMA__CREATE (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_SCHEMA__DROP (SEPG_DB_DATABASE__DROP) -+ #define SEPG_DB_SCHEMA__GETATTR (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_SCHEMA__SETATTR (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_SCHEMA__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_SCHEMA__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_SCHEMA__SEARCH (1<<6) -+ #define SEPG_DB_SCHEMA__ADD_NAME (1<<7) -+ #define SEPG_DB_SCHEMA__REMOVE_NAME (1<<8) -+ -+ #define SEPG_DB_SCHEMA_TEMP__CREATE (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_SCHEMA_TEMP__DROP (SEPG_DB_DATABASE__DROP) -+ #define SEPG_DB_SCHEMA_TEMP__GETATTR (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_SCHEMA_TEMP__SETATTR (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_SCHEMA_TEMP__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_SCHEMA_TEMP__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_SCHEMA_TEMP__SEARCH (SEPG_DB_SCHEMA__SEARCH) -+ #define SEPG_DB_SCHEMA_TEMP__ADD_NAME (SEPG_DB_SCHEMA__ADD_NAME) -+ #define SEPG_DB_SCHEMA_TEMP__REMOVE_NAME (SEPG_DB_SCHEMA__REMOVE_NAME) -+ -+ #define SEPG_DB_TABLE__CREATE (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_TABLE__DROP (SEPG_DB_DATABASE__DROP) -+ #define SEPG_DB_TABLE__GETATTR (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_TABLE__SETATTR (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_TABLE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_TABLE__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_TABLE__SELECT (1<<6) -+ #define SEPG_DB_TABLE__UPDATE (1<<7) -+ #define SEPG_DB_TABLE__INSERT (1<<8) -+ #define SEPG_DB_TABLE__DELETE (1<<9) -+ #define SEPG_DB_TABLE__LOCK (1<<10) -+ #define SEPG_DB_TABLE__REFERENCE (1<<11) -+ -+ #define SEPG_DB_SEQUENCE__CREATE (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_SEQUENCE__DROP (SEPG_DB_DATABASE__DROP) -+ #define SEPG_DB_SEQUENCE__GETATTR (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_SEQUENCE__SETATTR (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_SEQUENCE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_SEQUENCE__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_SEQUENCE__GET_VALUE (1<<6) -+ #define SEPG_DB_SEQUENCE__NEXT_VALUE (1<<7) -+ #define SEPG_DB_SEQUENCE__SET_VALUE (1<<8) -+ -+ #define SEPG_DB_PROCEDURE__CREATE (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_PROCEDURE__DROP (SEPG_DB_DATABASE__DROP) -+ #define SEPG_DB_PROCEDURE__GETATTR (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_PROCEDURE__SETATTR (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_PROCEDURE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_PROCEDURE__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_PROCEDURE__EXECUTE (1<<6) -+ #define SEPG_DB_PROCEDURE__ENTRYPOINT (1<<7) -+ #define SEPG_DB_PROCEDURE__INSTALL (1<<8) -+ #define SEPG_DB_PROCEDURE__UNTRUSTED (1<<9) -+ -+ #define SEPG_DB_COLUMN__CREATE (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_COLUMN__DROP (SEPG_DB_DATABASE__DROP) -+ #define SEPG_DB_COLUMN__GETATTR (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_COLUMN__SETATTR (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_COLUMN__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_COLUMN__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_COLUMN__SELECT (1<<6) -+ #define SEPG_DB_COLUMN__UPDATE (1<<7) -+ #define SEPG_DB_COLUMN__INSERT (1<<8) -+ #define SEPG_DB_COLUMN__REFERENCE (1<<9) -+ -+ #define SEPG_DB_TUPLE__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_TUPLE__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_TUPLE__SELECT (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_TUPLE__UPDATE (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_TUPLE__INSERT (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_TUPLE__DELETE (SEPG_DB_DATABASE__DROP) -+ -+ #define SEPG_DB_BLOB__CREATE (SEPG_DB_DATABASE__CREATE) -+ #define SEPG_DB_BLOB__DROP (SEPG_DB_DATABASE__DROP) -+ #define SEPG_DB_BLOB__GETATTR (SEPG_DB_DATABASE__GETATTR) -+ #define SEPG_DB_BLOB__SETATTR (SEPG_DB_DATABASE__SETATTR) -+ #define SEPG_DB_BLOB__RELABELFROM (SEPG_DB_DATABASE__RELABELFROM) -+ #define SEPG_DB_BLOB__RELABELTO (SEPG_DB_DATABASE__RELABELTO) -+ #define SEPG_DB_BLOB__READ (1<<6) -+ #define SEPG_DB_BLOB__WRITE (1<<7) -+ #define SEPG_DB_BLOB__IMPORT (1<<8) -+ #define SEPG_DB_BLOB__EXPORT (1<<9) -+ -+ /* -+ * sepgsql_sid_t : alternative representation of security context -+ */ -+ typedef struct { -+ Oid relid; -+ Oid secid; -+ } sepgsql_sid_t; -+ -+ #define SidIsValid(sid) (OidIsValid((sid).relid) && OidIsValid((sid).secid)) -+ -+ /* -+ * avc.c : userspace access vector caches -+ */ -+ -+ /* Hook to record audit logs */ -+ typedef void (*sepgsqlAvcAuditHook_t)(bool denied, -+ const char *scontext, -+ const char *tcontext, -+ const char *tclass, -+ const char *permissions, -+ const char *audit_name); -+ extern PGDLLIMPORT sepgsqlAvcAuditHook_t sepgsqlAvcAuditHook; -+ -+ extern Size sepgsqlShmemSize(void); -+ extern void sepgsqlAvcInitialize(void); -+ -+ extern bool sepgsqlGetEnforce(void); -+ extern int sepgsqlSetEnforce(int new_mode); -+ extern void sepgsqlAvcReset(void); -+ extern void sepgsqlAvcSwitchClient(const char *scontext); -+ -+ extern bool -+ sepgsqlClientHasPerms(sepgsql_sid_t tsid, -+ uint16 tclass, uint32 required, -+ const char *audit_name, bool abort); -+ extern sepgsql_sid_t -+ sepgsqlClientCreateSecid(sepgsql_sid_t tsid, uint16 tclass, Oid nrelid); -+ -+ extern security_context_t -+ sepgsqlClientCreateLabel(sepgsql_sid_t tsid, uint16 tclass); -+ -+ extern bool -+ sepgsqlComputePerms(security_context_t scontext, -+ security_context_t tcontext, -+ uint16 tclass, uint32 required, -+ const char *audit_name, bool abort); -+ -+ extern security_context_t -+ sepgsqlComputeCreate(security_context_t scontext, -+ security_context_t tcontext, -+ uint16 tclass); -+ -+ extern pid_t sepgsqlStartupWorkerProcess(void); -+ -+ /* -+ * checker.c : check permission on given queries -+ */ -+ extern void -+ sepgsqlCheckRTEPerms(RangeTblEntry *rte); -+ -+ extern void -+ sepgsqlCheckCopyTable(Relation rel, List *attnumlist, bool is_from); -+ -+ extern void -+ sepgsqlCheckSelectInto(Oid relaionId); -+ -+ extern bool -+ sepgsqlExecScan(Relation rel, HeapTuple tuple, uint32 required, bool abort); -+ -+ extern uint32 -+ sepgsqlSetupTuplePerms(RangeTblEntry *rte); -+ -+ extern void -+ sepgsqlHeapTupleInsert(Relation rel, HeapTuple newtup, bool internal); -+ -+ extern void -+ sepgsqlHeapTupleUpdate(Relation rel, ItemPointer otid, HeapTuple newtup); -+ -+ /* -+ * core.c : core facilities -+ */ -+ extern security_context_t -+ sepgsqlGetServerLabel(void); -+ -+ extern security_context_t -+ sepgsqlGetClientLabel(void); -+ -+ extern security_context_t -+ sepgsqlSwitchClient(security_context_t new_client); -+ -+ extern bool -+ sepgsqlIsEnabled(void); -+ -+ extern void -+ sepgsqlInitialize(void); -+ -+ /* -+ * hooks.c : routines to check certain permissions -+ */ -+ extern Oid -+ sepgsqlCheckDatabaseCreate(const char *datname, DefElem *newLabel); -+ extern void -+ sepgsqlCheckDatabaseDrop(Oid datOid); -+ extern void -+ sepgsqlCheckDatabaseSetattr(Oid datOid); -+ extern Oid -+ sepgsqlCheckDatabaseRelabel(Oid datOid, DefElem *newLlabel); -+ extern void -+ sepgsqlCheckDatabaseAccess(Oid datOid); -+ extern bool -+ sepgsqlCheckDatabaseSuperuser(void); -+ extern void -+ sepgsqlCheckDatabaseLoadModule(const char *filename); -+ -+ extern Oid -+ sepgsqlCheckSchemaCreate(const char *nspName, DefElem *new_label, bool isTemp); -+ extern void -+ sepgsqlCheckSchemaDrop(Oid nspOid); -+ extern void -+ sepgsqlCheckSchemaSetattr(Oid nspOid); -+ extern Oid -+ sepgsqlCheckSchemaRelabel(Oid nspOid, DefElem *new_label); -+ extern void -+ sepgsqlCheckSchemaAddName(Oid nspOid); -+ extern void -+ sepgsqlCheckSchemaRemoveName(Oid nspOid); -+ extern bool -+ sepgsqlCheckSchemaSearch(Oid nspOid, bool abort); -+ -+ extern void -+ sepgsqlCheckTableDrop(Oid table_oid); -+ extern void -+ sepgsqlCheckTableSetattr(Oid table_oid); -+ extern Oid -+ sepgsqlCheckTableRelabel(Oid table_oid, DefElem *new_label); -+ extern void -+ sepgsqlCheckTableLock(Oid table_oid); -+ extern void -+ sepgsqlCheckTableTruncate(Relation rel); -+ extern void -+ sepgsqlCheckTableReference(Relation rel, int16 *attnums, int natts); -+ -+ extern void -+ sepgsqlCheckSequenceGetValue(Oid seqOid); -+ extern void -+ sepgsqlCheckSequenceNextValue(Oid seqOid); -+ extern void -+ sepgsqlCheckSequenceSetValue(Oid seqOid); -+ -+ extern Oid -+ sepgsqlCheckColumnCreate(Oid relOid, const char *attname, DefElem *newLabel); -+ extern void -+ sepgsqlCheckColumnDrop(Oid relOid, AttrNumber attno); -+ extern void -+ sepgsqlCheckColumnSetattr(Oid relOid, AttrNumber attno); -+ extern Oid -+ sepgsqlCheckColumnRelabel(Oid relOid, AttrNumber attno, DefElem *newLabel); -+ -+ extern Oid -+ sepgsqlCheckProcedureCreate(const char *procName, Oid procOid, -+ Oid procNsp, Oid procLang, DefElem *newLabel); -+ extern void -+ sepgsqlCheckProcedureDrop(Oid procOid); -+ extern void -+ sepgsqlCheckProcedureSetattr(Oid procOid); -+ extern Oid -+ sepgsqlCheckProcedureRelabel(Oid procOid, DefElem *newLabel); -+ extern void -+ sepgsqlCheckProcedureExecute(Oid procOid); -+ extern void -+ sepgsqlCheckProcedureInstall(Oid procOid); -+ extern bool -+ sepgsqlHintProcedureInlined(HeapTuple protup); -+ extern void -+ sepgsqlCheckProcedureEntrypoint(FmgrInfo *flinfo, HeapTuple protup); -+ -+ extern void -+ sepgsqlCheckBlobCreate(Relation rel, HeapTuple lotup); -+ extern void -+ sepgsqlCheckBlobDrop(Relation rel, HeapTuple lotup); -+ extern void -+ sepgsqlCheckBlobRead(LargeObjectDesc *lobj); -+ extern void -+ sepgsqlCheckBlobWrite(LargeObjectDesc *lobj); -+ extern void -+ sepgsqlCheckBlobGetattr(HeapTuple tuple); -+ extern void -+ sepgsqlCheckBlobSetattr(HeapTuple tuple); -+ extern void -+ sepgsqlCheckBlobExport(LargeObjectDesc *lobj, -+ int fdesc, const char *filename); -+ extern void -+ sepgsqlCheckBlobImport(LargeObjectDesc *lobj, -+ int fdesc, const char *filename); -+ extern void -+ sepgsqlCheckBlobRelabel(HeapTuple oldtup, HeapTuple newtup); -+ -+ extern void -+ sepgsqlCheckFileRead(int fdesc, const char *filename); -+ extern void -+ sepgsqlCheckFileWrite(int fdesc, const char *filename); -+ -+ extern Oid -+ sepgsqlCheckSysobjCreate(Oid relid, const char *auditName); -+ extern void -+ sepgsqlCheckSysobjGetattr(Oid relid, Oid secid, const char *auditName); -+ extern void -+ sepgsqlCheckSysobjSetattr(Oid relid, Oid secid, const char *auditName); -+ extern void -+ sepgsqlCheckSysobjDrop(const ObjectAddress *object); -+ -+ /* -+ * label.c : security label management -+ */ -+ extern bool -+ sepgsqlTupleDescHasSecid(Oid relid, char relkind); -+ -+ extern void sepgsqlSetDefaultSecid(Relation rel, HeapTuple tuple); -+ extern sepgsql_sid_t sepgsqlGetDefaultDatabaseSecid(void); -+ extern sepgsql_sid_t sepgsqlGetDefaultSchemaSecid(Oid database_oid); -+ extern sepgsql_sid_t sepgsqlGetDefaultSchemaTempSecid(Oid database_oid); -+ extern sepgsql_sid_t sepgsqlGetDefaultTableSecid(Oid namespace_oid); -+ extern sepgsql_sid_t sepgsqlGetDefaultSequenceSecid(Oid namespace_oid); -+ extern sepgsql_sid_t sepgsqlGetDefaultProcedureSecid(Oid namespace_oid); -+ extern sepgsql_sid_t sepgsqlGetDefaultColumnSecid(Oid table_oid); -+ extern sepgsql_sid_t sepgsqlGetDefaultTupleSecid(Oid table_oid); -+ extern sepgsql_sid_t sepgsqlGetDefaultBlobSecid(Oid database_oid); -+ -+ extern Oid *sepgsqlCreateTableColumns(CreateStmt *stmt, -+ const char *relname, Oid namespace_oid, -+ TupleDesc tupdesc, char relkind); -+ extern Oid *sepgsqlCopyTableColumns(Relation source); -+ -+ extern sepgsql_sid_t -+ sepgsqlGetTupleContext(Oid tableOid, HeapTuple tuple, uint16 *tclass); -+ extern sepgsql_sid_t -+ sepgsqlGetSysobjContext(Oid tableOid, Oid objectId, int32 objsubId, uint16 *tclass); -+ -+ extern char *sepgsqlTransSecLabelIn(char *seclabel); -+ extern char *sepgsqlTransSecLabelOut(char *seclabel); -+ extern char *sepgsqlRawSecLabelIn(char *seclabel); -+ extern char *sepgsqlRawSecLabelOut(char *seclabel); -+ extern char *sepgsqlSysattSecLabelOut(Oid relid, HeapTuple tuple); -+ -+ /* -+ * perms.c : SELinux permission related stuff -+ */ -+ extern const char *sepgsqlAuditName(Oid relid, HeapTuple tuple); -+ -+ extern security_class_t sepgsqlFileObjectClass(int fdesc); -+ -+ extern security_class_t sepgsqlTupleObjectClass(Oid relid, HeapTuple tuple); -+ -+ extern security_class_t sepgsqlTransToExternalClass(security_class_t tclass_in); -+ -+ extern void sepgsqlTransToInternalPerms(security_class_t tclass_ex, -+ struct av_decision *avd); -+ extern const char *sepgsqlGetClassString(uint16 tclass); -+ extern const char *sepgsqlGetPermString(uint16 tclass, uint32 permission); -+ -+ #else /* HAVE_SELINUX */ -+ -+ /* avc.c */ -+ #define sepgsqlShmemSize() (0) -+ #define sepgsqlStartupWorkerProcess() (0) -+ -+ /* checker.c */ -+ #define sepgsqlCheckRTEPerms(a) do {} while(0) -+ #define sepgsqlCheckCopyTable(a,b,c) do {} while(0) -+ #define sepgsqlCheckSelectInto(a) do {} while(0) -+ #define sepgsqlExecScan(a,b,c) (true) -+ #define sepgsqlSetupTuplePerms(a) (0) -+ #define sepgsqlHeapTupleInsert(a,b,c) do {} while(0) -+ #define sepgsqlHeapTupleUpdate(a,b,c) do {} while(0) -+ -+ /* core.c */ -+ #define sepgsqlIsEnabled() (false) -+ #define sepgsqlInitialize() do {} while(0) -+ -+ /* hooks.c */ -+ #define sepgsqlCheckDatabaseCreate(a,b) (InvalidOid) -+ #define sepgsqlCheckDatabaseDrop(a) do {} while(0) -+ #define sepgsqlCheckDatabaseSetattr(a) do {} while(0) -+ #define sepgsqlCheckDatabaseRelabel(a,b) (InvalidOid) -+ #define sepgsqlCheckDatabaseAccess(a) (true) -+ #define sepgsqlCheckDatabaseSuperuser() (true) -+ #define sepgsqlCheckDatabaseLoadModule(a) do {} while(0) -+ -+ #define sepgsqlCheckSchemaCreate(a,b,c) (InvalidOid) -+ #define sepgsqlCheckSchemaDrop(a) do {} while(0) -+ #define sepgsqlCheckSchemaSetattr(a) do {} while(0) -+ #define sepgsqlCheckSchemaRelabel(a,b) (InvalidOid) -+ #define sepgsqlCheckSchemaAddName(a) do {} while(0) -+ #define sepgsqlCheckSchemaRemoveName(a) do {} while(0) -+ #define sepgsqlCheckSchemaSearch(a,b) (true) -+ -+ #define sepgsqlCheckTableDrop(a) do {} while(0) -+ #define sepgsqlCheckTableSetattr(a) do {} while(0) -+ #define sepgsqlCheckTableRelabel(a,b) (InvalidOid) -+ #define sepgsqlCheckTableLock(a) do {} while(0) -+ #define sepgsqlCheckTableTruncate(a) do {} while(0) -+ #define sepgsqlCheckTableReference(a,b,c) do {} while(0) -+ -+ #define sepgsqlCheckSequenceGetValue(a) do {} while(0) -+ #define sepgsqlCheckSequenceNextValue(a) do {} while(0) -+ #define sepgsqlCheckSequenceSetValue(a) do {} while(0) -+ -+ #define sepgsqlCheckColumnCreate(a,b,c) (InvalidOid) -+ #define sepgsqlCheckColumnDrop(a,b) do {} while(0) -+ #define sepgsqlCheckColumnSetattr(a,b) do {} while(0) -+ #define sepgsqlCheckColumnRelabel(a,b,c) (InvalidOid) -+ -+ #define sepgsqlCheckProcedureCreate(a,b,c,d) (InvalidOid) -+ #define sepgsqlCheckProcedureDrop(a) do {} while(0) -+ #define sepgsqlCheckProcedureSetattr(a) do {} while(0) -+ #define sepgsqlCheckProcedureRelabel(a,b) (InvalidOid) -+ #define sepgsqlCheckProcedureExecute(a) (true) -+ #define sepgsqlCheckProcedureInstall(a) do {} while(0) -+ #define sepgsqlHintProcedureInlined(a) (true) -+ #define sepgsqlCheckProcedureEntrypoint(a,b) do {} while(0) -+ -+ #define sepgsqlCheckBlobCreate(a,b) do {} while(0) -+ #define sepgsqlCheckBlobDrop(a,b) do {} while(0) -+ #define sepgsqlCheckBlobRead(a) do {} while(0) -+ #define sepgsqlCheckBlobWrite(a) do {} while(0) -+ #define sepgsqlCheckBlobGetattr(a) do {} while(0) -+ #define sepgsqlCheckBlobSetattr(a) do {} while(0) -+ #define sepgsqlCheckBlobExport(a,b,c) do {} while(0) -+ #define sepgsqlCheckBlobImport(a,b,c) do {} while(0) -+ #define sepgsqlCheckBlobRelabel(a,b) do {} while(0) -+ #define sepgsqlCheckFileRead(a,b) do {} while(0) -+ #define sepgsqlCheckFileWrite(a,b) do {} while(0) -+ -+ #define sepgsqlCheckSysobjCreate(a,b) (InvalidOid) -+ #define sepgsqlCheckSysobjGetattr(a,b,c) do {} while(0) -+ #define sepgsqlCheckSysobjSetattr(a,b,c) do {} while(0) -+ #define sepgsqlCheckSysobjDrop(a) do {} while(0) -+ -+ /* label.c */ -+ #define sepgsqlTupleDescHasSecLabel(a,b) (false) -+ #define sepgsqlSetDefaultSecLabel(a,b) do {} while(0) -+ #define sepgsqlCreateTableColumns(a,b,c,d,e) (NULL) -+ #define sepgsqlCopyTableColumns(a) (NULL) -+ #define sepgsqlMetaSecurityLabel() (NULL) -+ #define sepgsqlTransSecLabelIn(a) (a) -+ #define sepgsqlTransSecLabelOut(a) (a) -+ #define sepgsqlRawSecLabelIn(a) (a) -+ #define sepgsqlRawSecLabelOut(a) (a) -+ -+ #endif /* HAVE_SELINUX */ -+ -+ extern Datum sepgsql_getcon(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_server_getcon(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_get_user(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_get_role(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_get_type(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_get_range(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_set_user(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_set_role(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_set_type(PG_FUNCTION_ARGS); -+ extern Datum sepgsql_set_range(PG_FUNCTION_ARGS); -+ -+ #endif /* SEPGSQL_H */ -diff -Nrpc base/src/include/storage/fd.h sepgsql/src/include/storage/fd.h -*** base/src/include/storage/fd.h Tue Jan 13 09:22:28 2009 ---- sepgsql/src/include/storage/fd.h Wed Jul 15 19:48:58 2009 -*************** extern int FileWrite(File file, char *bu -*** 68,73 **** ---- 68,74 ---- - extern int FileSync(File file); - extern off_t FileSeek(File file, off_t offset, int whence); - extern int FileTruncate(File file, off_t offset); -+ extern int FileRawDescriptor(File file); - - /* Operations that allow use of regular stdio --- USE WITH CAUTION */ - extern FILE *AllocateFile(const char *name, const char *mode); -diff -Nrpc base/src/include/storage/large_object.h sepgsql/src/include/storage/large_object.h -*** base/src/include/storage/large_object.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/storage/large_object.h Wed Jul 15 19:48:58 2009 -*************** typedef struct LargeObjectDesc -*** 44,49 **** ---- 44,50 ---- - #define IFS_RDLOCK (1 << 0) - #define IFS_WRLOCK (1 << 1) - -+ Oid secid; /* security identifier of largeobject */ - } LargeObjectDesc; - - -*************** extern int inv_tell(LargeObjectDesc *obj -*** 79,83 **** ---- 80,86 ---- - extern int inv_read(LargeObjectDesc *obj_desc, char *buf, int nbytes); - extern int inv_write(LargeObjectDesc *obj_desc, const char *buf, int nbytes); - extern void inv_truncate(LargeObjectDesc *obj_desc, int len); -+ extern Oid inv_get_security(Oid loid); -+ extern void inv_set_security(Oid loid, Oid secid); - - #endif /* LARGE_OBJECT_H */ -diff -Nrpc base/src/include/storage/lwlock.h sepgsql/src/include/storage/lwlock.h -*** base/src/include/storage/lwlock.h Fri Mar 6 09:45:33 2009 ---- sepgsql/src/include/storage/lwlock.h Wed Jul 15 19:35:52 2009 -*************** typedef enum LWLockId -*** 67,72 **** ---- 67,73 ---- - AutovacuumLock, - AutovacuumScheduleLock, - SyncScanLock, -+ SepgsqlAvcLock, - /* Individual lock IDs end here */ - FirstBufMappingLock, - FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS, -diff -Nrpc base/src/include/utils/errcodes.h sepgsql/src/include/utils/errcodes.h -*** base/src/include/utils/errcodes.h Fri Mar 6 09:45:33 2009 ---- sepgsql/src/include/utils/errcodes.h Wed Jul 15 19:35:52 2009 -*************** -*** 347,352 **** ---- 347,357 ---- - #define ERRCODE_NO_DATA_FOUND MAKE_SQLSTATE('P','0', '0','0','2') - #define ERRCODE_TOO_MANY_ROWS MAKE_SQLSTATE('P','0', '0','0','3') - -+ /* Class SE - SE-PostgreSQL Error */ -+ #define ERRCODE_SELINUX_ERROR MAKE_SQLSTATE('S','E', '0','0','1') -+ #define ERRCODE_SELINUX_AUDIT MAKE_SQLSTATE('S','E', '0','0','2') -+ #define ERRCODE_SELINUX_INFO MAKE_SQLSTATE('S','E', '0','0','3') -+ - /* Class XX - Internal Error (PostgreSQL-specific error class) */ - /* (this is for "can't-happen" conditions and software bugs) */ - #define ERRCODE_INTERNAL_ERROR MAKE_SQLSTATE('X','X', '0','0','0') -diff -Nrpc base/src/include/utils/syscache.h sepgsql/src/include/utils/syscache.h -*** base/src/include/utils/syscache.h Sat Jan 3 12:25:21 2009 ---- sepgsql/src/include/utils/syscache.h Wed Sep 9 21:29:33 2009 -*************** enum SysCacheIdentifier -*** 69,74 **** ---- 69,76 ---- - RELNAMENSP, - RELOID, - RULERELNAME, -+ SECURITYATTR, -+ SECURITYSECID, - STATRELATT, - TSCONFIGMAP, - TSCONFIGNAMENSP, -diff -Nrpc base/src/test/regress/expected/sanity_check.out sepgsql/src/test/regress/expected/sanity_check.out -*** base/src/test/regress/expected/sanity_check.out Tue Feb 10 10:10:02 2009 ---- sepgsql/src/test/regress/expected/sanity_check.out Thu Jul 16 23:18:11 2009 -*************** SELECT relname, relhasindex -*** 112,117 **** ---- 112,118 ---- - pg_pltemplate | t - pg_proc | t - pg_rewrite | t -+ pg_security | t - pg_shdepend | t - pg_shdescription | t - pg_statistic | t -*************** SELECT relname, relhasindex -*** 151,157 **** - timetz_tbl | f - tinterval_tbl | f - varchar_tbl | f -! (140 rows) - - -- - -- another sanity check: every system catalog that has OIDs should have ---- 152,158 ---- - timetz_tbl | f - tinterval_tbl | f - varchar_tbl | f -! (141 rows) - - -- - -- another sanity check: every system catalog that has OIDs should have diff --git a/sepostgresql-fedora-prefix.patch b/sepostgresql-fedora-prefix.patch deleted file mode 100644 index a9dd24b..0000000 --- a/sepostgresql-fedora-prefix.patch +++ /dev/null @@ -1,87 +0,0 @@ -Index: sepgsql/src/Makefile.global.in -=================================================================== ---- sepgsql/src/Makefile.global.in (revision 2237) -+++ sepgsql/src/Makefile.global.in (working copy) -@@ -75,14 +75,14 @@ - datadir := @datadir@ - ifeq "$(findstring pgsql, $(datadir))" "" - ifeq "$(findstring postgres, $(datadir))" "" --override datadir := $(datadir)/postgresql -+override datadir := $(datadir)/sepgsql - endif - endif - - sysconfdir := @sysconfdir@ - ifeq "$(findstring pgsql, $(sysconfdir))" "" - ifeq "$(findstring postgres, $(sysconfdir))" "" --override sysconfdir := $(sysconfdir)/postgresql -+override sysconfdir := $(sysconfdir)/sepgsql - endif - endif - -@@ -91,7 +91,7 @@ - pkglibdir = $(libdir) - ifeq "$(findstring pgsql, $(pkglibdir))" "" - ifeq "$(findstring postgres, $(pkglibdir))" "" --override pkglibdir := $(pkglibdir)/postgresql -+override pkglibdir := $(pkglibdir)/sepgsql - endif - endif - -@@ -100,7 +100,7 @@ - pkgincludedir = $(includedir) - ifeq "$(findstring pgsql, $(pkgincludedir))" "" - ifeq "$(findstring postgres, $(pkgincludedir))" "" --override pkgincludedir := $(pkgincludedir)/postgresql -+override pkgincludedir := $(pkgincludedir)/sepgsql - endif - endif - -@@ -109,7 +109,7 @@ - docdir := @docdir@ - ifeq "$(findstring pgsql, $(docdir))" "" - ifeq "$(findstring postgres, $(docdir))" "" --override docdir := $(docdir)/postgresql -+override docdir := $(docdir)/sepgsql - endif - endif - -Index: sepgsql/src/bin/pg_ctl/pg_ctl.c -=================================================================== ---- sepgsql/src/bin/pg_ctl/pg_ctl.c (revision 2237) -+++ sepgsql/src/bin/pg_ctl/pg_ctl.c (working copy) -@@ -643,7 +643,7 @@ - - postmaster_path = pg_malloc(MAXPGPATH); - -- if ((ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR, -+ if ((ret = find_other_exec(argv0, "sepostgres", PG_BACKEND_VERSIONSTR, - postmaster_path)) < 0) - { - char full_path[MAXPGPATH]; -Index: sepgsql/src/bin/initdb/initdb.c -=================================================================== ---- sepgsql/src/bin/initdb/initdb.c (revision 2237) -+++ sepgsql/src/bin/initdb/initdb.c (working copy) -@@ -2763,7 +2763,7 @@ - sprintf(pgdenv, "PGDATA=%s", pg_data); - putenv(pgdenv); - -- if ((ret = find_other_exec(argv[0], "postgres", PG_BACKEND_VERSIONSTR, -+ if ((ret = find_other_exec(argv[0], "sepostgres", PG_BACKEND_VERSIONSTR, - backend_exec)) < 0) - { - char full_path[MAXPGPATH]; -Index: sepgsql/src/bin/pg_dump/pg_dumpall.c -=================================================================== ---- sepgsql/src/bin/pg_dump/pg_dumpall.c (revision 2237) -+++ sepgsql/src/bin/pg_dump/pg_dumpall.c (working copy) -@@ -157,7 +157,7 @@ - } - } - -- if ((ret = find_other_exec(argv[0], "pg_dump", PGDUMP_VERSIONSTR, -+ if ((ret = find_other_exec(argv[0], "sepg_dump", PGDUMP_VERSIONSTR, - pg_dump_bin)) < 0) - { - char full_path[MAXPGPATH]; diff --git a/sepostgresql.8 b/sepostgresql.8 deleted file mode 100644 index 9c60ef5..0000000 --- a/sepostgresql.8 +++ /dev/null @@ -1,137 +0,0 @@ -.TH "sepostgresql" "8" "Jul 15 2007" "kaigai@kaigai.gr.jp" "Security-Enhanced PostgreSQL" - -.SH "NAME" -sepostgresql \- Security-Enhances PostgreSQL - -.SH "DESCRIPTION" -Security-Enhanced PostgreSQL (SE-PostgreSQL) is an enhancement of PostgreSQL, -to apply fine grained mandatory access control for database objects based on -the security policy of SELinux. -These features enable to apply flexible integrated access control policy -on both of operating system and database management system, during all -stages of the life of the information. -.PP -This document describes the way to customize SE-PostgreSQL on the default -security policy. - -.SH "BOOLEANS" -The SELinux policy is customizable via BOOLEAN variable. This variable has -two states, 1 (on) or 0 (off). We can validate or invalidate a part of the -security policy depending on the state of boolean variables. - -\fBsepgsql_enable_users_ddl\fP enables to toggle permissions of confined -users/applications to invoke DDL statement, like CREATE TABLE. It is set to -\fBon\fP in the default. -In most cases, DDL statements are used to set up initial database structure, -and permissions to invoke them are not necessary on operation phase. -You can turn off this boolean as follows: - -.EX -setsebool -P sepgsql_enable_users_ddl ( \fBon\fP | off ) -.EE - -Rest of booleans are provided by \fBselinux-devel.pp\fP policy module. -It provides developments/debugs related permissions. -You can install it as follows: - -.EX -semodule -i /usr/share/selinux/targeted/sepostgresql-devel.pp -.EE - -\fBsepgsql_enable_auditallow\fP toggles output of audit messages in the case -when required permission checks are allowed, except for tuples because it -easily make a flood of audit logs. -In the default, it is set to off. You can set it as follows: - -.EX -setsebool -P sepgsql_enable_auditallow ( on | \fBoff\fP ) -.EE - -\fBsepgsql_enable_auditdeny\fP toggles output of audit messages in the case -when required permission checks are denied, except for tuples because it -easily make a flood of audit logs. -In the default, it is set to on. You can set it as follows: - -.EX -setsebool -P sepgsql_enable_auditdeny ( \fBon\fP | off ) -.EE - -\fBsepgsql_regression_test_mode\fP allows to load shared libraries deployed -on user's home directory. We recommend you to keep \fBoff\fP in operation -phase to prevent to load malicious libraries. -However, typical PostgreSQL regression test requires to load it, so we -have to reduce several restriction during the test. -In the default, it is set to off. You can set it as follows: - -.EX -setsebool -P sepgsql_regression_test_mode ( on | \fBoff\fP ) -.EE - -.SH "TYPES" - -\fBsepgsql_db_t\fP is a only type for database itself. -It is attched for newly created databases in the default. - -\fBsepgsql_table_t\fP is a type for tables, columns and tuples. -It is the default type of newly created tables by unconfined or -non-roled domain. It allows confined clietns to access with any -kind of operations except for relabeling, so we can use this type -for compatible purpose. - -\fBsepgsql_secret_table_t\fP is a type for tables, columns and tuples. -It never allows confined clients to access, so we can use this type -to store sensitive information. We reccomend to apply trusted procedures -to access tables/columns/tuples with this type under safe operation. - -\fBsepgsql_ro_table_t\fP is a type for read-only tables, columns and tuples. -It does not allow confined clients to modify any objects with this type. - -\fBsepgsql_fixed_table_t\fP is a type for non-manupulatable tables, columns -and tuples. It does not allow confined clients to update or delete any -objects with this type. - -\fBsepgsql_ROLE_table_t\fP is a type for a role specific tables, columns -and tuples. It allows confined clients with its role to access with any -kind of operations except for relabeling. -It is the default type of newly created tables by confined clients with -its role, and we can use this type to describe role level separation. - -\fBsepgsql_proc_t\fP is a type for procedures. -It is attached for newly created procedures by unconfined clients. -It allows any clients to invoke procedures with this type. -All of PostgreSQL built-in functions are labeled as this type in the default. - -\fBsepgsql_ROLE_proc_t\fP is a type for a role specific procedure. -It is attached for newly created procedures by confined clients with its role. -It allows clients with same role to invoke procedure with this type. -Note that unconfined clients cannot invoke this type to avoid to execute -dangerous functions with unconfined authorities. They have to confirm its -contains and relabel to \fBsepgsql_proc_t\fP for its invocation. - -\fBsepgsql_trusted_proc_exec_t\fP is a type for trusted procedures. -To call procedures with this type invokes domain transition to -unconfined domain, so it can access any kind of database objects. -We can use this type to provide a secure method to access sensitive -information. - -\fBsepgsql_blob_t\fP is a type for binary large objects (blob). -It is attached for newly created blob in the default. -Non-administrative clients can read and write the blobs with this type. - -\fBsepgsql_ro_blob_t\fP is a type for read-only binary large objects (blob). -Non-administrative clients cannot write the blobs with this type. - -.SH "BACKUP and RESTORE" -\fI--enable-selinux\fP option in \fBsepg_dump\fP and \fBsepg_dumpall\fP enable to dump database image with security context. We can restore the dumped image using the standard \fIpg_restore\fP and so on. - -.EX -Example) -$ sepg_dump -Ft -b --enable-selinux postgres | gzip -c > postgres.tgz -.EE - -.SH AUTHOR -This manual page was written by KaiGai Kohei - -.SH "SEE ALSO" - -selinux(8), boolean(8) diff --git a/sepostgresql.init b/sepostgresql.init deleted file mode 100644 index 866aaba..0000000 --- a/sepostgresql.init +++ /dev/null @@ -1,212 +0,0 @@ -#!/bin/sh -# sepostgresql This is the init script for starting up SE-PostgreSQL -# -# chkconfig: - 62 38 -# description: Starts and stops the SE-PostgreSQL backend daemon -# processname: postmaster -# pidfile: /var/run/postmaster.pid -#--------------------------------------------------------------------- - -PGVERSION="8.4.1" -PGMAJORVERSION=`echo "$PGVERSION" | sed 's/^\([0-9]*\.[0-9a-z]*\).*$/\1/'` - -# source function library -. /etc/rc.d/init.d/functions - -# get config -. /etc/sysconfig/network - -# find the name of the script -NAME=`basename $0` -if [ ${NAME:0:1} = "S" -o ${NAME:0:1} = "K" ]; then - NAME=${NAME:3} -fi - -# set defaults for configurable variables -SEPGSQL_BIN="/usr/bin" -SEPGSQL_DATA="/var/lib/sepgsql/data" -SEPGSQL_OPTS="-i -p 5432" -SEPGSQL_STARTUP_LOG="/var/lib/sepgsql/pgstartup.log" -SEPGSQL_LOG="/var/log/sepostgresql.log" -SEPGSQL_FALLBACK_CONTEXT="user_u:user_r:user_t" - -# override defaults from /etc/sysconfig/sepostgresql -test -f /etc/sysconfig/${NAME} && . /etc/sysconfig/${NAME} - -export SEPGSQL_FALLBACK_CONTEXT - -# Check that networking is up. -test "${NETWORKING}" = "no" && exit 0 -test -f "${SEPGSQL_BIN}/sepostgres" || exit 1 - -script_result=0 - -do_start() { - PSQL_START=$"Starting ${NAME} service: " - echo -n "$PSQL_START" - - # make sure startup-time log file is valid - if [ ! -e "${SEPGSQL_STARTUP_LOG}" -a ! -h "${SEPGSQL_STARTUP_LOG}" ]; then - touch "${SEPGSQL_STARTUP_LOG}" || exit 1 - chown sepgsql:sepgsql "${SEPGSQL_STARTUP_LOG}" - chmod 600 "${SEPGSQL_STARTUP_LOG}" - /sbin/restorecon "${SEPGSQL_STARTUP_LOG}" - fi - - # check for the SEPGSQL_DATA structure - if [ -f "${SEPGSQL_DATA}/PG_VERSION" ] && [ -d "${SEPGSQL_DATA}/base" ]; then - if [ x`cat "${SEPGSQL_DATA}/PG_VERSION"` != x"${PGMAJORVERSION}" ]; then - echo_failure - echo - echo "HINT: An old version of the database format was found." - echo "HINT: You need to upgrade the data format before using SE-PostgreSQL." - exit 1 - fi - else - echo_failure - echo - echo "HINT: ${SEPGSQL_DATA} is missing." - echo "HINT: Use '/etc/init.d/${NAME} initdb'" - echo "HINT: to initialize the database cluster first." - exit 1 - fi - - # make sure SEPGSQL_LOG - touch ${SEPGSQL_LOG} - chown sepgsql:sepgsql ${SEPGSQL_LOG} - chmod 600 ${SEPGSQL_LOG} - test -x /sbin/restorecon && /sbin/restorecon ${SEPGSQL_LOG} - - cd ${SEPGSQL_BIN} - /sbin/runuser sepgsql -c "./sepg_ctl -w -t 10 -l ${SEPGSQL_LOG} -D ${SEPGSQL_DATA} -o '${SEPGSQL_OPTS}' start" \ - >> ${SEPGSQL_STARTUP_LOG} 2>&1 < /dev/null - sleep 1 - PID=`/sbin/runuser sepgsql -c "./sepg_ctl -D ${SEPGSQL_DATA} status 2>/dev/null \ - | sed 's/^.*PID: //g' | sed 's/[^0-9].*$//g'"` - if [ ${PIPESTATUS[0]} -eq 0 ]; then - echo "$PID" > "/var/run/${NAME}.pid" - touch "/var/lock/subsys/${NAME}.lock" - echo_success - else - script_result=1 - echo_failure - fi - echo -} - -do_stop() { - echo -n $"Stopping ${NAME} service: " - cd ${SEPGSQL_BIN} - /sbin/runuser sepgsql -c "./sepg_ctl -D ${SEPGSQL_DATA} stop" \ - >> ${SEPGSQL_STARTUP_LOG} 2>&1 < /dev/null - ret=$? - if [ $ret -eq 0 ]; then - echo_success - else - echo_failure - script_result=1 - fi - echo - rm -f "/var/run/${NAME}.pid" - rm -f "/var/lock/subsys/${NAME}.lock" -} - -do_status() { - cd ${SEPGSQL_BIN} - /sbin/runuser sepgsql -- -c "./sepg_ctl -D ${SEPGSQL_DATA} status" 2>/dev/null \ - | head -1 | sed "s/^sepg_ctl:/${NAME}:/g" - - if [ ${PIPESTATUS[0]} -ne 0 ]; then - script_result=3 - test -e "/var/run/${NAME}.pid" && script_result=1 - test -e "/var/lock/subsys/${NAME}.lock" && script_result=2 - fi -} - -do_condrestart() { - cd ${SEPGSQL_BIN} - /sbin/runuser sepgsql -- -c "./sepg_ctl -D ${SEPGSQL_DATA} status" &>/dev/null && do_stop && do_start -} - -do_condstop() { - cd ${SEPGSQL_BIN} - /sbin/runuser sepgsql -- -c "./sepg_ctl -D ${SEPGSQL_DATA} status" &>/dev/null && do_stop -} - -do_reload() { - echo -n $"Reloading ${NAME} service: " - cd ${SEPGSQL_BIN} - /sbin/runuser sepgsql -- -c "./sepg_ctl -D ${SEPGSQL_DATA} reload" &>/dev/null < /dev/null - if [ $? -eq 0 ]; then - echo_success - else - echo_failure - script_result=1 - fi - echo -} - -do_initdb() { - echo -n $"Initializing database: " - - if [ -f "${SEPGSQL_DATA}/PG_VERSION" ]; then - echo_failure - echo - echo "HINT: Data directory is not empty" - script_result=1 - else - if [ ! -e "${SEPGSQL_DATA}" -a ! -h "${SEPGSQL_DATA}" ]; then - mkdir -p "${SEPGSQL_DATA}" || exit 1 - chown sepgsql:sepgsql "${SEPGSQL_DATA}" - chmod 600 "${SEPGSQL_DATA}" - fi - # cleanup SELinux labeling for "${SEPGSQL_DATA}" - test -x /sbin/restorecon && /sbin/restorecon -R "${SEPGSQL_DATA}" - # Initialize the database - cd ${SEPGSQL_BIN} - /sbin/runuser -- sepgsql -c "./initdb.sepgsql --enable-selinux --pgdata='${SEPGSQL_DATA}' --auth='ident'" \ - >> "${SEPGSQL_STARTUP_LOG}" 2>&1 < /dev/null - if [ -f "${SEPGSQL_DATA}/PG_VERSION" ]; then - echo_success - else - echo_failure - script_result=1 - fi - echo - fi -} - -# see how we were called. -case "$1" in - start) - do_start - ;; - stop) - do_stop - ;; - status) - do_status - ;; - restart) - do_stop - do_start - ;; - condrestart) - do_condrestart - ;; - condstop) - do_condstop - ;; - reload|force-reload) - do_reload - ;; - initdb) - do_initdb - ;; - *) - echo $"Usage: $0 {start|stop|status|restart|condrestart|condstop|reload|force-reload|initdb}" - exit 1 - ;; -esac - -exit $script_result diff --git a/sepostgresql.logrotate b/sepostgresql.logrotate deleted file mode 100644 index 3ed7081..0000000 --- a/sepostgresql.logrotate +++ /dev/null @@ -1,11 +0,0 @@ -# logrotate configuration for SE-PostgreSQL - -/var/log/sepostgresql.log { - rotate 4 - compress - size 4M - notifempty - postrotate - /sbin/service sepostgresql restart >& /dev/null - endscript -} diff --git a/sepostgresql.spec b/sepostgresql.spec deleted file mode 100644 index 49d6727..0000000 --- a/sepostgresql.spec +++ /dev/null @@ -1,460 +0,0 @@ -# -# Security Enhanced PostgreSQL (SE-PostgreSQL) -# -# Copyright 2007 KaiGai Kohei -# ----------------------------------------------------- - -# SE-PostgreSQL status extension -%define selinux_policy_stores targeted mls - -%{!?ssl:%define ssl 1} - -Summary: Security Enhanced PostgreSQL -Name: sepostgresql -Version: 8.4.1 -Release: 2305%{?dist} -License: BSD -Group: Applications/Databases -Url: http://code.google.com/p/sepgsql/ -Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX) -Source0: ftp://ftp.postgresql.org/pub/source/v%{version}/postgresql-%{version}.tar.bz2 -Source1: sepostgresql.init -Source2: sepostgresql.8 -Source3: sepostgresql.logrotate -Patch0: sepostgresql-8.4.patch -Patch1: sepostgresql-fedora-prefix.patch -BuildRequires: perl glibc-devel bison flex readline-devel zlib-devel >= 1.0.4 -BuildRequires: checkpolicy libselinux-devel >= 2.0.80 -BuildRequires: selinux-policy >= 3.6.8 -%if %{ssl} -BuildRequires: openssl-devel -%endif -Requires(pre): shadow-utils -Requires(post): policycoreutils /sbin/chkconfig -Requires(preun): /sbin/chkconfig /sbin/service -Requires(postun): policycoreutils -Requires: postgresql-server = %{version} -Requires: policycoreutils >= 2.0.16 libselinux >= 2.0.80 -Requires: selinux-policy >= 3.6.8 -Requires: tzdata logrotate - -%description -Security Enhanced PostgreSQL is an extension of PostgreSQL -based on SELinux security policy, that applies fine grained -mandatory access control to many objects within the database, -and takes advantage of user authorization integrated within -the operating system. SE-PostgreSQL works as a userspace -reference monitor to check any SQL query. - -%prep -%setup -q -n postgresql-%{version} -%patch0 -p1 -%patch1 -p1 - -%build -CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS -CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS - -# build SE-PostgreSQL -%configure --disable-rpath \ - --enable-selinux \ -%if %{ssl} - --with-openssl \ -%endif - --enable-debug \ - --enable-cassert \ - --libdir=%{_libdir}/pgsql \ - --datadir=%{_datadir}/sepgsql \ - --with-system-tzdata=/usr/share/zoneinfo - -# parallel build, if possible -make %{?_smp_mflags} -touch src/backend/security/sepgsql/policy/sepostgresql-devel.fc -make -C src/backend/security/sepgsql/policy - -%install -rm -rf %{buildroot} - -make DESTDIR=%{buildroot} install - -install -d %{buildroot}%{_datadir}/selinux/packages -install -p -m 644 src/backend/security/sepgsql/policy/sepostgresql-devel.pp \ - %{buildroot}%{_datadir}/selinux/packages - -# avoid to conflict with native postgresql package -mv %{buildroot}%{_bindir} %{buildroot}%{_bindir}.orig -install -d %{buildroot}%{_bindir} -mv %{buildroot}%{_bindir}.orig/initdb %{buildroot}%{_bindir}/initdb.sepgsql -mv %{buildroot}%{_bindir}.orig/pg_ctl %{buildroot}%{_bindir}/sepg_ctl -mv %{buildroot}%{_bindir}.orig/postgres %{buildroot}%{_bindir}/sepostgres -mv %{buildroot}%{_bindir}.orig/pg_dump %{buildroot}%{_bindir}/sepg_dump -mv %{buildroot}%{_bindir}.orig/pg_dumpall %{buildroot}%{_bindir}/sepg_dumpall - -# remove unnecessary files -rm -rf %{buildroot}%{_bindir}.orig -rm -rf %{buildroot}%{_libdir} -rm -rf %{buildroot}%{_includedir} -rm -rf %{buildroot}%{_datadir}/doc -rm -rf %{buildroot}%{_datadir}/sepgsql/timezone -rm -rf %{buildroot}%{_mandir} - -# /var/lib/sepgsql -install -d -m 700 %{buildroot}%{_localstatedir}/lib/sepgsql -install -d -m 700 %{buildroot}%{_localstatedir}/lib/sepgsql/data -install -d -m 700 %{buildroot}%{_localstatedir}/lib/sepgsql/backups - -# /etc/rc.d/init.d/* -mkdir -p %{buildroot}%{_initrddir} -install -p -m 755 %{SOURCE1} %{buildroot}%{_initrddir}/sepostgresql - -# /usr/share/man/* -mkdir -p %{buildroot}%{_mandir}/man8 -install -p -m 644 %{SOURCE2} %{buildroot}%{_mandir}/man8 - -# /etc/logrotate.d/ -mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d -install -p -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/logrotate.d/sepostgresql - -%clean -rm -rf %{buildroot} - -%pre -getent group sepgsql >/dev/null || groupadd -r sepgsql -getent passwd sepgsql >/dev/null || \ - useradd -r -g sepgsql -d %{_localstatedir}/lib/sepgsql -s /bin/bash \ - -c "SE-PostgreSQL server" sepgsql -exit 0 - -%post -/sbin/chkconfig --add %{name} -/sbin/ldconfig - -for store in %{selinux_policy_stores} -do - # clean up legacy policy module (now it is unnecessary) - %{_sbindir}/semodule -s ${store} -r sepostgresql >& /dev/null || : - if %{_sbindir}/semodule -s ${store} -l 2>/dev/null | grep -Eq "^sepostgresql-devel"; then - %{_sbindir}/semodule -s ${store} \ - -i %{_datadir}/selinux/packages/sepostgresql-devel.pp >& /dev/null || : - fi -done - -# Fix up non-standard file contexts -/sbin/fixfiles -R %{name} restore || : -/sbin/restorecon -R %{_localstatedir}/lib/sepgsql || : - -%preun -if [ $1 -eq 0 ]; then # rpm -e case - /sbin/service %{name} condstop >/dev/null 2>&1 - /sbin/chkconfig --del %{name} -fi - -%postun -/sbin/ldconfig -if [ $1 -ge 1 ]; then # rpm -U case - /sbin/service %{name} condrestart >/dev/null 2>&1 || : -fi -if [ $1 -eq 0 ]; then # rpm -e case - for store in %{selinux_policy_stores} - do - %{_sbindir}/semodule -s ${store} -r sepostgresql-devel >& /dev/null || : - done - /sbin/fixfiles -R %{name} restore || : - test -d %{_localstatedir}/lib/sepgsql && /sbin/restorecon -R %{_localstatedir}/lib/sepgsql || : -fi - -%files -%defattr(-,root,root,-) -%doc COPYRIGHT README -%{_initrddir}/sepostgresql -%{_sysconfdir}/logrotate.d/sepostgresql -%{_bindir}/initdb.sepgsql -%{_bindir}/sepg_ctl -%{_bindir}/sepostgres -%{_bindir}/sepg_dump -%{_bindir}/sepg_dumpall -%{_mandir}/man8/sepostgresql.* -%dir %{_datadir}/sepgsql -%{_datadir}/sepgsql/postgres.bki -%{_datadir}/sepgsql/postgres.description -%{_datadir}/sepgsql/postgres.shdescription -%{_datadir}/sepgsql/system_views.sql -%{_datadir}/sepgsql/*.sample -%{_datadir}/sepgsql/snowball_create.sql -%{_datadir}/sepgsql/timezonesets/ -%{_datadir}/sepgsql/tsearch_data/ -%{_datadir}/sepgsql/conversion_create.sql -%{_datadir}/sepgsql/information_schema.sql -%{_datadir}/sepgsql/sql_features.txt -%attr(644,root,root) %{_datadir}/selinux/packages/sepostgresql-devel.pp -%attr(700,sepgsql,sepgsql) %dir %{_localstatedir}/lib/sepgsql -%attr(700,sepgsql,sepgsql) %dir %{_localstatedir}/lib/sepgsql/data -%attr(700,sepgsql,sepgsql) %dir %{_localstatedir}/lib/sepgsql/backups - -%changelog -* Fri Sep 11 2009 KaiGai Kohei - 8.4.1-2305 -- Upgrade base SE-PostgreSQL v8.4.0->v8.4.1 -- rework: backport features from v8.5devel tree - -* Fri Aug 21 2009 Tomas Mraz - 8.4.0-2238 -- rebuilt with new openssl - -* Wed Aug 19 2009 KaiGai Kohei - 8.4.0-2237 -- Upgrade SE-PostgreSQL to 8.4.x series - -* Sun Jul 26 2009 Fedora Release Engineering - 8.3.7-1991 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild - -* Tue Jun 9 2009 KaiGai Kohei - 8.3.7-1990 -- backport features from v8.4devel, it also needs libselinux-2.0.80 - -* Fri Apr 17 2009 KaiGai Kohei - 8.3.7-1772 -- bugfix: /etc/init.d/sepostgresql initdb didn't work correctly - -* Fri Mar 27 2009 KaiGai Kohei - 8.3.7-1770 -- upgrade base PostgreSQL versin 8.3.6->8.3.7 -- backport features from v8.4devel - -* Thu Feb 26 2009 KaiGai Kohei - 8.3.6-2.1635 -- bugfix: possible information leak by the order of permission checks - in row level permission checks. - -* Wed Feb 25 2009 Fedora Release Engineering - 8.3.6-3.1518 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild - -* Fri Feb 6 2009 - 8.3.6-2.1523 -- upgrade base PostgreSQL version 8.3.5->8.3.6 -- backport features from 8.4devel tree -- security policy fix for Fedora 9 - -* Sat Jan 17 2009 Tomas Mraz - 8.3.5-2.1183 -- rebuild with new openssl - -* Wed Nov 5 2008 - 8.3.5-2.1182 -- upgrade base PostgreSQL version 8.3.4->8.3.5 -- backport cumulative bugfixes from 8.4devel series - -* Thu Oct 2 2008 - 8.3.4-2.1076 -- bugfix: "(null)" audit logs for non-cached decision making. -- A hook is added for "COPY TO/FROM " cases. - -* Sat Sep 27 2008 - 8.3.4-2.1066 -- update base version to 8.3.4 -- sepostgresql.pp was marked as obsolute - -* Tue Sep 23 2008 - 8.3.3-2.1043 -- bugfix: a case when INSERT a FK reference to invisible PK - -* Wed Aug 13 2008 - 8.3.3-2.964 -- bugfix: trusted procedure invokation - -* Fri Jul 11 2008 - 8.3.3-2.952 -- Security policy module updates - -* Fri Jul 11 2008 - 8.3.3-2.945 -- Add OpenSSL support -- backport 8.4devel fixes - -* Sun Jun 15 2008 - 8.3.3-2.889 -- backport 8.4devel features. - -* Fri Jun 13 2008 - 8.3.3-2.869 -- upgrade base PostgreSQL 8.3.1 -> 8.3.3 - -* Wed Apr 30 2008 - 8.3.1-2.197 -- Inconsistent version number format at Changelogs - -* Wed Apr 30 2008 - 8.3.1-2.196 -- BUGFIX: ROW-level control did not work correctly on TRUNCATE - -* Sun Mar 9 2008 - 8.3.0-2.129 -- BUGFIX: more conprehensive fixes in "SELECT COUNT(*) ..." - -* Sun Mar 2 2008 - 8.3.0-2.120 -- BUGFIX: CREATE TABLE statement with explicit labeled columns -- BUGFIX: SELECT count(*) does not filter unallowed tuples - -* Wed Feb 27 2008 - 8.3.0-2.117 -- ".beta" removed. - -* Wed Feb 27 2008 - 8.3.0-2.114 -- Security policy updates - -* Tue Feb 26 2008 - 8.3.0-2.113 -- BUGFIX: CREATE/ALTER TABLE with CONTEXT='...' did nothing. - -* Thu Feb 7 2008 - 8.3.0-2.108 -- add /etc/logrotate.d/sepostgresql - -* Thu Feb 7 2008 - 8.3.0-2.105 -- update base version to stable 8.3.0 -- add tzdata dependency -- allow db_database:{get_param set_param} for generic domain -- error message cleanups -- Improve large object hooks in PGACE framework -- BUGFIX: db_blob:{drop} was checked at loread() -- BUGFIX: incorrect permission in DELETE with RETURNING clause -- incorrect permission when we read and update security_context in same time. - -* Fri Jan 25 2008 - 8.3RC2-2.62 -- BUGFIX: add handling to invalid contexts already stored - -* Tue Jan 22 2008 - 8.3RC2-2.56 -- BUGFIX: lack of locks when refering buffer pages at update/delete hooks -- BUGFIX: explicit labeling using SELECT ... INTO statement. - -* Sun Jan 20 2008 - 8.3RC2-2.52 -- shares /usr/lib/pgsql/*.so libraries, with original postgresql. - -* Thu Jan 10 2008 - 8.3RC1-2.37 -- add sepg_dump/sepg_dumpall support for 8.3base package. - -* Mon Nov 26 2007 - 8.3beta3-2.0 -- Branch from 8.2.x tree - -* Wed Nov 21 2007 - 8.2.5-1.66 -- Add a policy module hotfix for labeled networking - -* Thu Nov 1 2007 - 8.2.5-1.51 -- Re-organize repository to prepare to branch 8.3.x based tree. - (no differences from 8.2.5-1.33) - -* Wed Oct 17 2007 - 8.2.5-1.33 -- Fix bug: security context was not canonicalized - when irregular context (but interpretable) was inputed. - -* Mon Oct 15 2007 - 8.2.5-1.31 -- Fix bug: type definitions of security_label_to_text() - and text_to_security_label() are mismatched. - -* Sat Sep 22 2007 - 8.2.5-1.23 -- update base PostgreSQL to 8.2.5 - -* Mon Sep 1 2007 - 8.2.4-1.0 -- mark as SE-PostgreSQL 8.2.4-1.0 - -* Thu Aug 28 2007 - 8.2.4-0.434.beta -- add Requires: postgresql-server, instead of Conflicts: tag - (Some sharable files are removed from sepostgresql package) - -* Fri Aug 24 2007 - 8.2.4-0.429.beta -- add policycoreutils to Requires(post/postun) -- upstreamed selinux-policy got SE-PostgreSQL related object classes definition. - -* Sat Aug 18 2007 - 8.2.4-0.427.beta -- sepg_dumpall uses /usr/bin/sepg_dump - -* Fri Aug 17 2007 - 8.2.4-0.423.beta -- fix policy not to execute sepgsql_user_proc_t from administrative domain - -* Fri Aug 10 2007 - 8.2.4-0.418.beta -- object classes are renamed with "db_" prefix -- /etc/init.d/sepostgresql script is improved. - -* Thu Aug 2 2007 - 8.2.4-0.409.beta -- specfile updated based on the following comments - https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=249522#c5 - -* Mon Jul 30 2007 - 8.2.4-0.407.beta -- fix spec file based on Fedora reviewing process -- add rawhide support - -* Mon Jul 23 2007 - 8.2.4-0.402.beta -- add manpage of sepostgresql -- fix specfile convention for Fedora suitable - -* Sun Jul 15 2007 - 8.2.4-0.398.beta -- SECCLASS_DATABASE is updated (fc7->62, fc6->61) - -* Sun Jul 1 2007 - 8.2.4-0.391.beta -- Mark as a beta version. - -* Sat Jun 30 2007 - 8.2.4-0.384.alpha -- add fallback context support with $SEPGSQL_FALLBACK_CONTEXT -- add sepgsql_enable_users_ddl boolean to restrict sepgsql_sysobj_t -- BUGFIX: incorrect inherited attribute expanding for RECORD type (attno=0) -- BUGFIX: trigger functions were not checked in COPY FROM statement - -* Tue Jun 26 2007 - 8.2.4-0.376.alpha -- add pgaceExecutorStart() to hook ExecutorStart() - -* Mon Jun 25 2007 - 8.2.4-0.372.alpha -- add table name prefix for column name on audit messages -- use security_label_raw_in as an alternative for security_label_in -- add hook for query execution path with SPI_ interface -- add trigger function suppoer -- BUGFIX: remove unnecessary checks for COPY TO/FROM on non-table relation -- BUGFIX: remove unnecessary checks for LOCK on non-table relation -- BUGFIX: incorrect object id for tuples within pg_security -- BUGFIX: CommandCounterIncrement() might be called during heap_create_with_catalog. -- BUGFIX: correct self-deadlock -- update security policy: sepgsql_sysobj_t, sepgsql_user_proc_t, sepgsql_ro_blob_t - -* Tue Jun 19 2007 - 8.2.4-0.351.alpha -- BUGFIX: sepgsql_compute_avc_datum() accessed userspace AVC without - holding any lock. -- improve build scripts. - -* Sat Jun 16 2007 - 8.2.4-0.320.alpha -- update: sepostgresql.pp security policy fot strict/mls suitable -- BUGFIX: column:drop evaluation for ALTER TABLE tbl DROP col; statement -- add --enable-security option for pg_dumpall command -- add {use} permission for table/column/tuple object classes - -* Tue May 29 2007 - 8.2.4-0.306.alpha -- BUGFIX: RangeTblEntry->requiredPerms are polluted. - -* Sun May 27 2007 - 8.2.4-0.304.alpha -- add support for dynamic object class/access vector mapping -- BUGFIX: Lack of implicit labeling on COPY FROM statement for system catalogs -- BUGFIX: Incorrect security context handling for inherited tables - -* Fri May 25 2007 - 8.2.4-0.292.alpha -- add pg_dump/pg_dumpall/pg_restore with --enable-security option -- add support on OUTER JOIN by rewriting query. -- add security_context support on COPY TO/FROM statement -- add unlabeled security context support (enable to obtain /selinux/initial_contexts/*) -- BUGFIX: lack of checks on JOIN ON condition -- BUGFIX: pseudo relation object (sequence, toast, ...) are not handled as database obj. -- BUGFIX: lack of tuple:insert checks at COPY FROM statement -- BUGFIX: server crash when CREATE TABLE command with newly defined CONTEXT = '...'. - -* Wed May 16 2007 - 8.2.4-0.266.alpha -- BUGFIX: incorrect security context of newly generated system object. -- BUGFIX: missing error text when audit log is disabled. -- BUGFIX: incorrect Oid of newly generated tuples within pg_security. -- BUGFIX: sepgsql_enable_audittuple is misconditioned. -- add checks for T_RowExpr/T_RowCompareExpr/T_BooleanTest - T_DistinctExpr/T_ConvertRowtypeExpr -- add support CONTEXT = 'xxx' for CREATE TABLE/FUNCTION/DATABASE statement - -* Sun Apr 30 2007 - 8.2.4-0.240.alpha -- update base version 8.2.3 -> 8.2.4 -- BUGFIX: unexpected expose in OUTER JOIN statement. - add rewrite OUTER JOIN into SUBQUERY to ensure filtering violated tuples. -- BUGFIX: strange operation in text_to_security_label() -- BUGFIX: infinite recursive call on security label -> oid mapping -- BUGFIX: sepgsql_avc_init() is called in policy state monitoring process - to avoid nonsense initialization of avc_shmem. - -* Fri Apr 27 2007 - 8.2.3-0.232.alpha -- object class numbers were redefined. (SECCLASS_DATABASE got into 61) -- is_selinux_enabled() was cached on the shared memory segment. -- BUGFIX: server went into infinit loop on foreign key constraint. - -* Mon Apr 16 2007 - 8.2.3-0.226.alpha -- BUGFIX: cases when several variables with same type in a single table - -* Sat Apr 07 2007 - 8.2.3-0.214.alpha -- add the first implementation of SE-PostgreSQL on PGACE framework - -* Wed Mar 21 2007 - 8.2.3-0.212.alpha -- BUGFIX: SetOperation didn't handle its subquery correctly. - So, it caused server crash. - -* Wed Mar 07 2007 - 8.2.3-0.209.alpha -- BUGFIX: var->varlevelsup was ignored, so outer references - from subqueries cause a fault. - -* Tue Feb 27 2007 - 8.2.3-0.178.alpha -- Initial RPM build diff --git a/sources b/sources deleted file mode 100644 index 91e78c6..0000000 --- a/sources +++ /dev/null @@ -1 +0,0 @@ -f2015af17bacbbfe140daf0d1067f9c9 postgresql-8.4.1.tar.bz2