rpms/sepostgresql/devel sepostgresql-core-8.3.patch, NONE, 1.1 sepostgresql-test-8.3.patch, NONE, 1.1 sepostgresql-utils-8.3.patch, NONE, 1.1 .cvsignore, 1.13, 1.14 sepostgresql.init, 1.30, 1.31 sepostgresql.spec, 1.33, 1.34 sources, 1.10, 1.11 sepostgresql-pg_dump-8.3.6-2.patch, 1.1, NONE sepostgresql-policy-8.3.6-2.patch, 1.2, NONE sepostgresql-sepgsql-8.3.6-2.patch, 1.2, NONE

KaiGai Kohei kaigai at fedoraproject.org
Fri Mar 27 03:54:43 UTC 2009


Author: kaigai

Update of /cvs/pkgs/rpms/sepostgresql/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv9053

Modified Files:
	.cvsignore sepostgresql.init sepostgresql.spec sources 
Added Files:
	sepostgresql-core-8.3.patch sepostgresql-test-8.3.patch 
	sepostgresql-utils-8.3.patch 
Removed Files:
	sepostgresql-pg_dump-8.3.6-2.patch 
	sepostgresql-policy-8.3.6-2.patch 
	sepostgresql-sepgsql-8.3.6-2.patch 
Log Message:
- upgrade base PostgreSQL 8.3.6->8.3.7
- backport features from 8.4devel tree


sepostgresql-core-8.3.patch:

--- NEW FILE sepostgresql-core-8.3.patch ---
diff -rpNU3 base/configure sepgsql-new/configure
--- base/configure	2009-03-15 17:47:25.000000000 +0900
+++ sepgsql-new/configure	2009-03-15 17:58:10.000000000 +0900
@@ -314,7 +314,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS configure_args build build_cpu build_vendor build_os host host_cpu host_vendor host_os PORTNAME docdir enable_nls WANTED_LANGUAGES default_port enable_shared enable_rpath enable_debug enable_profiling DTRACE DTRACEFLAGS enable_dtrace CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GCC TAS autodepend INCLUDES enable_thread_safety with_tcl with_perl with_python with_gssapi with_krb5 krb_srvtab with_pam with_ldap with_bonjour with_openssl with_ossp_uuid XML2_CONFIG with_libxml with_libxslt with_system_tzdata with_zlib EGREP ELF_SYS LDFLAGS_SL LD with_gnu_ld ld_R_works RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP STRIP_STATIC_LIB STRIP_SHARED
 _LIB TAR LN_S AWK YACC YFLAGS FLEX FLEXFLAGS PERL perl_archlibexp perl_privlibexp perl_useshrplib perl_embed_ldflags PYTHON python_version python_configdir python_includespec python_libdir python_libspec python_additional_libs OSSP_UUID_LIBS HAVE_IPV6 LIBOBJS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS LDAP_LIBS_FE LDAP_LIBS_BE HAVE_POSIX_SIGNALS MSGFMT MSGMERGE XGETTEXT localedir TCLSH TCL_CONFIG_SH TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIBS TCL_LIB_SPEC TCL_SHARED_BUILD TCL_SHLIB_LD_LIBS NSGMLS JADE have_docbook DOCBOOKSTYLE COLLATEINDEX SGMLSPL vpath_build LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS configure_args build build_cpu build_vendor build_os host host_cpu host_vendor host_os PORTNAME docdir enable_nls WANTED_LANGUAGES default_port enable_shared enable_rpath enable_debug enable_profiling DTRACE DTRACEFLAGS enable_dtrace CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CPP GCC TAS autodepend INCLUDES enable_thread_safety with_tcl with_perl with_python with_gssapi with_krb5 krb_srvtab with_pam with_ldap with_bonjour with_openssl with_ossp_uuid XML2_CONFIG with_libxml with_libxslt with_system_tzdata with_zlib enable_selinux EGREP ELF_SYS LDFLAGS_SL LD with_gnu_ld ld_R_works RANLIB ac_ct_RANLIB STRIP ac_ct_STRIP STRIP_STATIC_L
 IB STRIP_SHARED_LIB TAR LN_S AWK YACC YFLAGS FLEX FLEXFLAGS PERL perl_archlibexp perl_privlibexp perl_useshrplib perl_embed_ldflags PYTHON python_version python_configdir python_includespec python_libdir python_libspec python_additional_libs OSSP_UUID_LIBS HAVE_IPV6 LIBOBJS acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS LDAP_LIBS_FE LDAP_LIBS_BE HAVE_POSIX_SIGNALS MSGFMT MSGMERGE XGETTEXT localedir TCLSH TCL_CONFIG_SH TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIBS TCL_LIB_SPEC TCL_SHARED_BUILD TCL_SHLIB_LD_LIBS NSGMLS JADE have_docbook DOCBOOKSTYLE COLLATEINDEX SGMLSPL vpath_build LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -871,6 +871,7 @@ Optional Features:
   --enable-cassert        enable assertion checks (for debugging)
   --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-largefile     omit support for large files
 
 Optional Packages:
@@ -4619,6 +4620,115 @@ fi;
 
 
 #
+# SELinux support
+#
+
+pgac_args="$pgac_args enable_selinux"
+
+# Check whether --enable-selinux or --disable-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 getpeercon in -lselinux" >&5
+echo $ECHO_N "checking for getpeercon in -lselinux... $ECHO_C" >&6
+if test "${ac_cv_lib_selinux_getpeercon+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 gcc2 internal prototype to avoid an error.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+/* We use char because int might match the return type of a gcc2
+   builtin and then its argument prototype would still apply.  */
+char getpeercon ();
+int
+main ()
+{
+getpeercon ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&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); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  ac_cv_lib_selinux_getpeercon=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ac_cv_lib_selinux_getpeercon=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_getpeercon" >&5
+echo "${ECHO_T}$ac_cv_lib_selinux_getpeercon" >&6
+if test $ac_cv_lib_selinux_getpeercon = 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
 #
 
@@ -26019,6 +26129,7 @@ s, at with_libxml@,$with_libxml,;t t
 s, at with_libxslt@,$with_libxslt,;t t
 s, at with_system_tzdata@,$with_system_tzdata,;t t
 s, at with_zlib@,$with_zlib,;t t
+s, at enable_selinux@,$enable_selinux,;t t
 s, at EGREP@,$EGREP,;t t
 s, at ELF_SYS@,$ELF_SYS,;t t
 s, at LDFLAGS_SL@,$LDFLAGS_SL,;t t
diff -rpNU3 base/configure.in sepgsql-new/configure.in
--- base/configure.in	2009-03-15 17:47:25.000000000 +0900
+++ sepgsql-new/configure.in	2009-03-15 17:58:10.000000000 +0900
@@ -626,6 +626,19 @@ PGAC_ARG_BOOL(with, zlib, yes,
 AC_SUBST(with_zlib)
 
 #
+# SELinux support
+#
+PGAC_ARG_BOOL(enable, selinux, no,
+              [  --enable-selinux        enable to build with SELinux support])
+if test "$enable_selinux" = yes; then
+    AC_CHECK_LIB(selinux, getpeercon,
+                 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 -rpNU3 base/src/Makefile.global.in sepgsql-new/src/Makefile.global.in
--- base/src/Makefile.global.in	2007-11-17 20:15:40.000000000 +0900
+++ sepgsql-new/src/Makefile.global.in	2009-03-13 18:14:33.000000000 +0900
@@ -165,6 +165,7 @@ enable_rpath	= @enable_rpath@
 enable_nls	= @enable_nls@
 enable_debug	= @enable_debug@
 enable_dtrace	= @enable_dtrace@
+enable_selinux	= @enable_selinux@
 enable_thread_safety	= @enable_thread_safety@
 
 python_includespec	= @python_includespec@
diff -rpNU3 base/src/backend/Makefile sepgsql-new/src/backend/Makefile
--- base/src/backend/Makefile	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/backend/Makefile	2009-03-13 18:14:33.000000000 +0900
@@ -16,7 +16,7 @@ include $(top_builddir)/src/Makefile.glo
 
 DIRS = access bootstrap catalog parser commands executor lib libpq \
 	main nodes optimizer port postmaster regex rewrite \
-	storage tcop tsearch utils $(top_builddir)/src/timezone
+	security storage tcop tsearch utils $(top_builddir)/src/timezone
 
 SUBSYSOBJS = $(DIRS:%=%/SUBSYS.o)
 
@@ -32,6 +32,11 @@ LIBS := $(filter-out -lpgport, $(LIBS)) 
 # 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
+
[...9394 lines suppressed...]
+sepgsqlTransToInternalPerms(security_class_t tclass_ex, struct av_decision *avd);
+
+extern const char *
+sepgsqlGetClassString(security_class_t tclass);
+
+extern const char *
+sepgsqlGetPermissionString(security_class_t tclass, access_vector_t av);
+
+extern bool
+sepgsqlCheckObjectPerms(Relation rel, HeapTuple tuple,
+                        access_vector_t required, bool abort);
+
+#else	/* HAVE_SELINUX */
+
+// avc.c
+#define sepgsqlShmemSize()						(0)
+#define sepgsqlStartupWorkerProcess()			(0)
+// checker.c
+#define sepgsqlCheckRTEPerms(a)					do {} while(0)
+#define sepgsqlCheckSelectInto(a)				do {} while(0)
+#define sepgsqlExecScan(a,b,c,d)				(true)
+#define sepgsqlHeapTupleInsert(a,b,c)			(true)
+#define sepgsqlHeapTupleUpdate(a,b,c,d)			(true)
+#define sepgsqlHeapTupleDelete(a,b,c)			(true)
+// core.c
+#define sepgsqlIsEnabled()						(false)
+#define sepgsqlInitialize()						do {} while(0)
+// hooks.c
+#define sepgsqlCheckDatabaseAccess(a)			(true)
+#define sepgsqlCheckDatabaseSuperuser()			(true)
+#define sepgsqlCheckDatabaseInstallModule(a)	do {} while(0)
+#define sepgsqlCheckDatabaseLoadModule(a)		do {} while(0)
+#define sepgsqlCheckTableLock(a)				(true)
+#define sepgsqlCheckTableTruncate(a)			(true)
+#define sepgsqlCheckProcedureExecute(a)			(true)
+#define sepgsqlCheckProcedureEntrypoint(a,b)	do {} while(0)
+#define sepgsqlCheckBlobDrop(a)					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 sepgsqlAllowFunctionInlined(a)			(true)
+// label.c
+#define sepgsqlTupleDescHasSecLabel(a)			(false)
+#define sepgsqlMetaSecurityLabel()				(NULL)
+#define sepgsqlInputGivenSecLabel(a)			(InvalidOid)
+#define sepgsqlInputGivenSecLabelRelation(a)	(NIL)
+#define sepgsqlSecurityLabelTransIn(a)			(a)
+#define sepgsqlSecurityLabelTransOut(a)			(a)
+#define sepgsqlCheckValidSecurityLabel(a)		(false)
+
+#endif	/* HAVE_SELINUX */
+
+extern Datum sepgsql_getcon(PG_FUNCTION_ARGS);
+extern Datum sepgsql_getservcon(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 -rpNU3 base/src/include/storage/fd.h sepgsql-new/src/include/storage/fd.h
--- base/src/include/storage/fd.h	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/include/storage/fd.h	2009-03-13 18:14:33.000000000 +0900
@@ -67,6 +67,7 @@ extern int	FileWrite(File file, char *bu
 extern int	FileSync(File file);
 extern long FileSeek(File file, long offset, int whence);
 extern int	FileTruncate(File file, long 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 -rpNU3 base/src/include/storage/large_object.h sepgsql-new/src/include/storage/large_object.h
--- base/src/include/storage/large_object.h	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/include/storage/large_object.h	2009-03-13 18:14:33.000000000 +0900
@@ -44,6 +44,7 @@ typedef struct LargeObjectDesc
 #define IFS_RDLOCK		(1 << 0)
 #define IFS_WRLOCK		(1 << 1)
 
+	Oid			secid;			/* security id of the largeobject */
 } LargeObjectDesc;
 
 
@@ -79,5 +80,7 @@ extern int	inv_tell(LargeObjectDesc *obj
 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 -rpNU3 base/src/include/storage/lwlock.h sepgsql-new/src/include/storage/lwlock.h
--- base/src/include/storage/lwlock.h	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/include/storage/lwlock.h	2009-03-13 18:14:33.000000000 +0900
@@ -63,6 +63,7 @@ typedef enum LWLockId
 	AutovacuumLock,
 	AutovacuumScheduleLock,
 	SyncScanLock,
+	SepgsqlAvcLock,
 	/* Individual lock IDs end here */
 	FirstBufMappingLock,
 	FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS,
diff -rpNU3 base/src/include/utils/builtins.h sepgsql-new/src/include/utils/builtins.h
--- base/src/include/utils/builtins.h	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/include/utils/builtins.h	2009-03-13 13:09:47.000000000 +0900
@@ -617,6 +617,14 @@ extern Datum varchartypmodout(PG_FUNCTIO
 extern Datum varchar(PG_FUNCTION_ARGS);
 
 /* varlena.c */
+extern text *cstring_to_text(const char *s);
+extern text *cstring_to_text_with_len(const char *s, int len);
+extern char *text_to_cstring(const text *t);
+extern void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len);
+
+#define CStringGetTextDatum(s) PointerGetDatum(cstring_to_text(s))
+#define TextDatumGetCString(d) text_to_cstring((text *) DatumGetPointer(d))
+
 extern Datum textin(PG_FUNCTION_ARGS);
 extern Datum textout(PG_FUNCTION_ARGS);
 extern Datum textrecv(PG_FUNCTION_ARGS);
diff -rpNU3 base/src/include/utils/catcache.h sepgsql-new/src/include/utils/catcache.h
--- base/src/include/utils/catcache.h	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/include/utils/catcache.h	2009-03-13 18:14:33.000000000 +0900
@@ -172,6 +172,7 @@ extern HeapTuple SearchCatCache(CatCache
 			   Datum v1, Datum v2,
 			   Datum v3, Datum v4);
 extern void ReleaseCatCache(HeapTuple tuple);
+extern void InsertCatCache(CatCache *cache, HeapTuple tuple);
 
 extern CatCList *SearchCatCacheList(CatCache *cache, int nkeys,
 				   Datum v1, Datum v2,
diff -rpNU3 base/src/include/utils/errcodes.h sepgsql-new/src/include/utils/errcodes.h
--- base/src/include/utils/errcodes.h	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/include/utils/errcodes.h	2009-03-13 18:14:33.000000000 +0900
@@ -339,6 +339,11 @@
 #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 -rpNU3 base/src/include/utils/syscache.h sepgsql-new/src/include/utils/syscache.h
--- base/src/include/utils/syscache.h	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/include/utils/syscache.h	2009-03-13 18:14:33.000000000 +0900
@@ -64,18 +64,20 @@
 #define RELNAMENSP			33
 #define RELOID				34
 #define RULERELNAME			35
-#define STATRELATT			36
-#define TSCONFIGMAP			37
-#define TSCONFIGNAMENSP		38
-#define TSCONFIGOID			39
-#define TSDICTNAMENSP		40
-#define TSDICTOID			41
-#define TSPARSERNAMENSP		42
-#define TSPARSEROID			43
-#define TSTEMPLATENAMENSP	44
-#define TSTEMPLATEOID		45
-#define TYPENAMENSP			46
-#define TYPEOID				47
+#define SECURITYLABEL		36
+#define SECURITYOID			37
+#define STATRELATT			38
+#define TSCONFIGMAP			39
+#define TSCONFIGNAMENSP		40
+#define TSCONFIGOID			41
+#define TSDICTNAMENSP		42
+#define TSDICTOID			43
+#define TSPARSERNAMENSP		44
+#define TSPARSEROID			45
+#define TSTEMPLATENAMENSP	46
+#define TSTEMPLATEOID		47
+#define TYPENAMENSP			48
+#define TYPEOID				49
 
 extern void InitCatalogCache(void);
 extern void InitCatalogCachePhase2(void);
@@ -84,6 +86,8 @@ extern HeapTuple SearchSysCache(int cach
 			   Datum key1, Datum key2, Datum key3, Datum key4);
 extern void ReleaseSysCache(HeapTuple tuple);
 
+extern void InsertSysCache(Oid relid, HeapTuple tuple);
+
 /* convenience routines */
 extern HeapTuple SearchSysCacheCopy(int cacheId,
 				   Datum key1, Datum key2, Datum key3, Datum key4);

sepostgresql-test-8.3.patch:

--- NEW FILE sepostgresql-test-8.3.patch ---
diff -rpNU3 base/src/test/regress/expected/sanity_check.out sepgsql-new/src/test/regress/expected/sanity_check.out
--- base/src/test/regress/expected/sanity_check.out	2007-11-25 12:49:12.000000000 +0900
+++ sepgsql-new/src/test/regress/expected/sanity_check.out	2009-03-13 18:14:33.000000000 +0900
@@ -111,6 +111,7 @@ SELECT relname, relhasindex
  pg_pltemplate           | t
  pg_proc                 | t
  pg_rewrite              | t
+ pg_security             | t
  pg_shdepend             | t
  pg_shdescription        | t
  pg_statistic            | t
@@ -149,7 +150,7 @@ SELECT relname, relhasindex
  timetz_tbl              | f
  tinterval_tbl           | f
  varchar_tbl             | f
-(138 rows)
+(139 rows)
 
 --
 -- another sanity check: every system catalog that has OIDs should have
diff -rpNU3 base/src/test/sepgsql/Makefile sepgsql-new/src/test/sepgsql/Makefile
--- base/src/test/sepgsql/Makefile	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/Makefile	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,65 @@
+# ----------------------------------------------------
+# Makefile for SE-PostgreSQL testcases
+# ----------------------------------------------------
+PSQL      := $(shell which psql)
+DIFF      := $(shell which diff)
+RUNCON    := $(shell which runcon)
+GETSEBOOL := $(shell which getsebool)
+DBNAME	  := test
+
+TESTCASES = $(wildcard sql/*.sql)
+
+test: init check setup results.diff
+
+init:
+	rm -f results.diff results/*.out results/*.diff
+
+clean: init
+	rm -f launch_psql
+
+launch_psql: launch_psql.c
+	$(CC) $< -o $@ -lselinux
+
+results.diff: $(TESTCASES:sql/%.sql=results/%.diff)
+	@for x in $^; do cat $$x >> $@; done
+	@test -s $@ && echo "HINT: See $@ to confirm errors" || :
+
+results/%.diff: sql/%.sql
+	@./launch_psql $(PSQL) -a $(DBNAME) < $< >& $(@:%.diff=%.out)
+	@$(DIFF) -u $(<:sql/%.sql=expected/%.out)	\
+	            $(<:sql/%.sql=results/%.out) >& $@	\
+		&& echo -n "PASS: " || echo -n "FAIL: "
+	@echo $(notdir $(@:.diff=))
+
+setup: launch_psql
+	@cp -f /dev/null /tmp/sepgsql_test_copy_1
+	@cp -f /dev/null /tmp/sepgsql_test_copy_2
+	@chcon -t postgresql_tmp_t -l s0 /tmp/sepgsql_test_copy_1
+	@chcon -t postgresql_db_t  -l s0 /tmp/sepgsql_test_copy_2
+	@dd if=/dev/zero of=/tmp/sepgsql_test_blob1 bs=1024 count=20 >& /dev/null
+	@dd if=/dev/zero of=/tmp/sepgsql_test_blob2 bs=1024 count=20 >& /dev/null
+	@chcon -t postgresql_tmp_t -l s0 /tmp/sepgsql_test_blob1
+	@chcon -t postgresql_db_t  -l s0 /tmp/sepgsql_test_blob2
+	@chmod 0666 /tmp/sepgsql_test_*
+	@echo "PASS: setup filesystem objects"
+
+check:
+	@test -x $(PSQL) || \
+		(echo "HINT: $(PSQL) is not available"; exit 1)
+	@$(PSQL) -qt -c 'SHOW sepostgresql' -d $(DBNAME) 2>/dev/null | grep -q on || \
+		(echo "HINT: database \"$(DBNAME)\" is not available"; \
+		 echo "HINT: SE-PostgreSQL may not be available on server"; exit 1)
+	@$(GETSEBOOL) allow_user_postgresql_connect | grep -q on || \
+		(echo "HINT: check allow_user_postgresql_connect boolean"; exit 1)
+	@$(GETSEBOOL) sepgsql_regression_test_mode | grep -q on || \
+		(echo "HINT: check sepgsql_regression_test_mode boolean"; \
+		 echo "HINT: check sepostgresql-devel.pp installed"; exit 1)
+	@$(RUNCON) -t sepgsql_test_t -l s0-s0:c0.c15 \
+		$(PSQL) -c 'SELECT sepgsql_getcon()' $(DBNAME) >& /dev/null || \
+		(echo "HINT: /sbin/restorecon -R <prefix> and restart"; \
+		 echo "HINT: user shell should have 's0-s0:c0.c15' range, at least"; \
+		 echo "      semanage enables to set up it"; exit 1)
+	@test -x /etc/init.d/mcstrans && /etc/init.d/mcstrans status >& /dev/null && \
+		(echo "HINT: stop mcstrans daemon"; exit 1) || \
+		(test $$? -eq 3 && exit 0 || exit 1)
+	@echo "PASS: check runtime environment"
diff -rpNU3 base/src/test/sepgsql/expected/basic.out sepgsql-new/src/test/sepgsql/expected/basic.out
--- base/src/test/sepgsql/expected/basic.out	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/expected/basic.out	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,108 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+SET
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION
+RESET client_min_messages;
+RESET
+-- SETUP
+CREATE TABLE t1
+(
+    a   int,
+    b   text
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_ro_table_t:s0',
+    c   bool
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+);
+CREATE TABLE
+INSERT INTO t1 VALUES (1, 'aaa', false), (2, 'bbb', true);
+INSERT 0 2
+CREATE TABLE t2
+(
+    s   int,
+    t   int,
+    u   int
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c0';
+CREATE TABLE
+ALTER TABLE t2 DROP COLUMN t;	-- disturbing factor
+ALTER TABLE
+CREATE TABLE t3
+(
+    x   text
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c1'
+) inherits(t2);
+CREATE TABLE
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+SELECT sepgsql_getcon();
+                  sepgsql_getcon                   
+---------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+(1 row)
+
+SELECT * FROM t1;			-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_secret_table_t:s0 tclass=db_column name=t1.c
+SELECT a, b FROM t1;
+ a |  b  
+---+-----
+ 1 | aaa
+ 2 | bbb
+(2 rows)
+
+SELECT COUNT(*) FROM t1 WHERE c;	-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_secret_table_t:s0 tclass=db_column name=t1.c
+UPDATE t1 SET b = 'ccc';		-- to be denied
+ERROR:  SELinux: denied { update } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_ro_table_t:s0 tclass=db_column name=t1.b
+UPDATE t1 SET a = a + 2;
+UPDATE 2
+INSERT INTO t1 VALUES (5, 'eee', true);	-- to be denied
+ERROR:  SELinux: denied { insert } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_ro_table_t:s0 tclass=db_column name=t1.b
+INSERT INTO t1 VALUES (5);
+INSERT 0 1
+SELECT * FROM t2;
+ s | u 
+---+---
+(0 rows)
+
+SELECT t2 FROM t2;
+ t2 
+----
+(0 rows)
+
+SELECT t3 FROM t3;	-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_table_t:s0:c1 tclass=db_column name=t3.x
+SELECT 1 FROM t3;
+ ?column? 
+----------
+(0 rows)
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c1
+SELECT sepgsql_getcon();
+                  sepgsql_getcon                   
+---------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c1
+(1 row)
+
+SELECT * FROM t2;	-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c1 tcontext=unconfined_u:object_r:sepgsql_table_t:s0:c0 tclass=db_table name=t2
+SELECT t2 FROM t2;	-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c1 tcontext=unconfined_u:object_r:sepgsql_table_t:s0:c0 tclass=db_table name=t2
+SELECT t3 FROM t3;
+ t3 
+----
+(0 rows)
+
diff -rpNU3 base/src/test/sepgsql/expected/copy_stmt.out sepgsql-new/src/test/sepgsql/expected/copy_stmt.out
--- base/src/test/sepgsql/expected/copy_stmt.out	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/expected/copy_stmt.out	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,90 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+SET
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION
+RESET client_min_messages;
+RESET
+-- setup tables
+CREATE TABLE t1
+(
+    a    int,
+    b    text
+);
+CREATE TABLE
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb');
+INSERT 0 2
+CREATE TABLE t2
+(
+    x    int,
+    y    text
+         SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+);
+CREATE TABLE
+SELECT security_context from pg_attribute where attrelid = 't2'::regclass and attname = 'y';
+                security_context                 
+-------------------------------------------------
+ unconfined_u:object_r:sepgsql_secret_table_t:s0
+(1 row)
+
+INSERT INTO t2 VALUES (1, 'xxx'), (2, 'yyy');
+INSERT 0 2
+CREATE TABLE t3	      -- read only table
+(
+    s    int,
+    t    text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_ro_table_t:s0';
+CREATE TABLE
+INSERT INTO t2 VALUES (1, 'sss'), (2, 'ttt');
+INSERT 0 2
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+SELECT sepgsql_getcon();
+                  sepgsql_getcon                   
+---------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+(1 row)
+
+COPY t1 TO stdout;
+1	aaa
+2	bbb
+COPY t1 FROM stdin;
+COPY t1 TO '/tmp/sepgsql_test_copy_1';
+COPY 4
+COPY t1 TO '/tmp/sepgsql_test_copy_2';	-- to be denied
+ERROR:  SELinux: denied { write } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:postgresql_db_t:s0 tclass=file name=/tmp/sepgsql_test_copy_2
+COPY t2 TO stdout;	-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_secret_table_t:s0 tclass=db_column name=t2.y
+COPY t2 FROM stdin;	-- to be denied
+ERROR:  SELinux: denied { insert } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_secret_table_t:s0 tclass=db_column name=t2.y
+COPY t2 (x) TO stdout;
+1
+2
+1
+2
+COPY t3 TO stdout;
+COPY t3 FROM '/tmp/sepgsql_test_copy_1';	-- to be denied
+ERROR:  SELinux: denied { insert } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_ro_table_t:s0 tclass=db_table name=t3
+COPY t1 FROM '/tmp/sepgsql_test_copy_1';
+COPY 4
+COPY t1 TO stdout;
+1	aaa
+2	bbb
+3	ccc
+4	ddd
+1	aaa
+2	bbb
+3	ccc
+4	ddd
diff -rpNU3 base/src/test/sepgsql/expected/enhanced_ddl_stmt.out sepgsql-new/src/test/sepgsql/expected/enhanced_ddl_stmt.out
--- base/src/test/sepgsql/expected/enhanced_ddl_stmt.out	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/expected/enhanced_ddl_stmt.out	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,180 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+SET
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION
+DROP FUNCTION IF EXISTS f2(int) CASCADE;
+DROP FUNCTION
+RESET client_min_messages;
+RESET
+-- CREATE TABLE with SECURITY_LABEL clause
+CREATE TABLE t1 (
+       a int,
+       b text
+);
+CREATE TABLE
+SELECT relname, security_context FROM pg_class WHERE oid = 't1'::regclass;
+ relname |             security_context             
+---------+------------------------------------------
+ t1      | unconfined_u:object_r:sepgsql_table_t:s0
+(1 row)
+
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't1'::regclass and attnum > 0;
+ attname |             security_context             
+---------+------------------------------------------
+ a       | unconfined_u:object_r:sepgsql_table_t:s0
+ b       | unconfined_u:object_r:sepgsql_table_t:s0
+(2 rows)
+
+CREATE TABLE t2 (
+       a int,
+       b text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_ro_table_t:s0';
+CREATE TABLE
+SELECT relname, security_context FROM pg_class WHERE oid = 't2'::regclass;
+ relname |              security_context               
+---------+---------------------------------------------
+ t2      | unconfined_u:object_r:sepgsql_ro_table_t:s0
+(1 row)
+
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't2'::regclass and attnum > 0;
+ attname |              security_context               
+---------+---------------------------------------------
+ a       | unconfined_u:object_r:sepgsql_ro_table_t:s0
+ b       | unconfined_u:object_r:sepgsql_ro_table_t:s0
+(2 rows)
+
+CREATE TABLE t3 (
+       a int,
+       b text SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_fixed_table_t:s0',
+       c bool SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0',
+       d int
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c0';
+CREATE TABLE
+SELECT relname, security_context FROM pg_class WHERE oid = 't3'::regclass;
+ relname |              security_context               
+---------+---------------------------------------------
+ t3      | unconfined_u:object_r:sepgsql_table_t:s0:c0
+(1 row)
+
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't3'::regclass and attnum > 0;
+ attname |                security_context                 
+---------+-------------------------------------------------
+ a       | unconfined_u:object_r:sepgsql_table_t:s0
+ b       | unconfined_u:object_r:sepgsql_fixed_table_t:s0
+ c       | unconfined_u:object_r:sepgsql_secret_table_t:s0
+ d       | unconfined_u:object_r:sepgsql_table_t:s0
+(4 rows)
+
+CREATE TABLE t4 (
+       a int,
+       b text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:invalid_label_t:s0';	-- to be failed
+ERROR:  invalid security label: unconfined_u:object_r:invalid_label_t:s0
+CREATE TABLE t4 (
+       a int,
+       b text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0';	-- to be denied
+ERROR:  SELinux: denied { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15 tcontext=unconfined_u:object_r:sepgsql_proc_t:s0 tclass=db_table name=t4
+-- ALTER TABLE with SECURITY_CONTEXT clause
+ALTER TABLE t2 SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0';
+ALTER TABLE
+ALTER TABLE t2 ADD COLUMN c bool;	-- it inherits table's one
+ALTER TABLE
+SELECT relname, security_context FROM pg_class WHERE oid = 't2'::regclass;
+ relname |                security_context                 
+---------+-------------------------------------------------
+ t2      | unconfined_u:object_r:sepgsql_secret_table_t:s0
+(1 row)
+
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't2'::regclass and attnum > 0;
+ attname |                security_context                 
+---------+-------------------------------------------------
+ a       | unconfined_u:object_r:sepgsql_ro_table_t:s0
+ b       | unconfined_u:object_r:sepgsql_ro_table_t:s0
+ c       | unconfined_u:object_r:sepgsql_secret_table_t:s0
+(3 rows)
+
+ALTER TABLE t3 ALTER b SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0';
+ALTER TABLE
+SELECT relname, security_context FROM pg_class WHERE oid = 't3'::regclass;
+ relname |              security_context               
+---------+---------------------------------------------
+ t3      | unconfined_u:object_r:sepgsql_table_t:s0:c0
+(1 row)
+
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't3'::regclass and attnum > 0;
+ attname |                security_context                 
+---------+-------------------------------------------------
+ a       | unconfined_u:object_r:sepgsql_table_t:s0
+ b       | unconfined_u:object_r:sepgsql_table_t:s0
+ c       | unconfined_u:object_r:sepgsql_secret_table_t:s0
+ d       | unconfined_u:object_r:sepgsql_table_t:s0
+(4 rows)
+
+-- CREATE FUNCTION with SECURITY_CONTEXT clause
+CREATE FUNCTION f1 (int) RETURNS int
+       LANGUAGE 'sql'
+       SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c0'
+       AS 'SELECT $1 * 2';
+CREATE FUNCTION
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f1'::regproc;
+ proname |              security_context              
+---------+--------------------------------------------
+ f1      | unconfined_u:object_r:sepgsql_proc_t:s0:c0
+(1 row)
+
+CREATE FUNCTION f2 (int) RETURNS int
+       LANGUAGE 'sql'
+       SECURITY_CONTEXT = 'unconfined_u:object_r:invalid_label_t:s0'
+       AS 'SELECT $1 + $1';	 -- to be failed
+ERROR:  invalid security label: unconfined_u:object_r:invalid_label_t:s0
+CREATE FUNCTION f2 (int) RETURNS int
+       LANGUAGE 'sql'
+       SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c16'
+       AS 'SELECT $1 + $1';	 -- to be denied
+ERROR:  SELinux: denied { create } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15 tcontext=unconfined_u:object_r:sepgsql_proc_t:s0:c16 tclass=db_procedure name=f2
+CREATE FUNCTION f2 (int) RETURNS int
+       LANGUAGE 'sql'
+       AS 'SELECT $1 + $1';
+CREATE FUNCTION
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f2'::regproc;
+ proname |            security_context             
+---------+-----------------------------------------
+ f2      | unconfined_u:object_r:sepgsql_proc_t:s0
+(1 row)
+
+-- ALTER FUNCTION with SECURITY_CONTEXT clause
+ALTER FUNCTION f1(int)
+      SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c1';
+ALTER FUNCTION
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f1'::regproc;
+ proname |              security_context              
+---------+--------------------------------------------
+ f1      | unconfined_u:object_r:sepgsql_proc_t:s0:c1
+(1 row)
+
+ALTER FUNCTION f2(int)
+      SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c16';	-- to be denied
+ERROR:  SELinux: denied { relabelto } scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15 tcontext=unconfined_u:object_r:sepgsql_proc_t:s0:c16 tclass=db_procedure name=f2
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f2'::regproc;
+ proname |            security_context             
+---------+-----------------------------------------
+ f2      | unconfined_u:object_r:sepgsql_proc_t:s0
+(1 row)
+
diff -rpNU3 base/src/test/sepgsql/expected/join_query.out sepgsql-new/src/test/sepgsql/expected/join_query.out
--- base/src/test/sepgsql/expected/join_query.out	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/expected/join_query.out	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,85 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+SET
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION
+RESET client_min_messages;
+RESET
+-- SETUP
+CREATE TABLE t1
+(
+    a   int,
+    b   text,
+    c   int
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+);
+CREATE TABLE
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+INSERT 0 3
+CREATE TABLE t2
+(
+    x   int,
+    y   text
+);
+CREATE TABLE
+INSERT INTO t2 VALUES (2, 'xxx'), (3, 'yyy'), (4,'zzz');
+INSERT 0 3
+CREATE TABLE t3
+(
+    d   int
+) INHERITS (t1);
+CREATE TABLE
+INSERT INTO t3 VALUES (4, 'ddd'), (5, 'eee');
+INSERT 0 2
+CREATE TABLE t4
+(
+    z   int
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+) INHERITS (t2);
+CREATE TABLE
+INSERT INTO t2 VALUES (1, 'sss'), (5, 'ttt');
+INSERT 0 2
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+SELECT sepgsql_getcon();
+                  sepgsql_getcon                   
+---------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+(1 row)
+
+SELECT * FROM t1 JOIN t2 ON a = x;		-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_secret_table_t:s0 tclass=db_column name=t1.c
+SELECT a, b, y FROM t1 JOIN t2 ON a = x;
+ a |  b  |  y  
+---+-----+-----
+ 1 | aaa | sss
+ 2 | bbb | xxx
+ 3 | ccc | yyy
+ 4 | ddd | zzz
+ 5 | eee | ttt
+(5 rows)
+
+SELECT a, b, y FROM t1 JOIN t2 ON c = x;	-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_secret_table_t:s0 tclass=db_column name=t1.c
+SELECT COUNT(*) FROM t1 JOIN t2 ON a = x;
+ count 
+-------
+     5
+(1 row)
+
+SELECT j FROM (t1 JOIN t2 ON a = x) AS j;	-- to be denied
+ERROR:  SELinux: denied { select } scontext=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0 tcontext=unconfined_u:object_r:sepgsql_secret_table_t:s0 tclass=db_column name=t1.c
diff -rpNU3 base/src/test/sepgsql/expected/large_object.out sepgsql-new/src/test/sepgsql/expected/large_object.out
--- base/src/test/sepgsql/expected/large_object.out	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/expected/large_object.out	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,293 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+SET
+DROP TABLE IF EXISTS lolabel CASCADE;
+DROP TABLE
+DROP FUNCTION IF EXISTS lo_label(oid) CASCADE;
+DROP FUNCTION
+RESET client_min_messages;
+RESET
+CREATE TABLE lolabel(
+       loid	oid,
+       label	text
+);
+CREATE TABLE
+CREATE OR REPLACE FUNCTION lo_label(oid)
+       RETURNS TEXT LANGUAGE 'sql'
+       AS 'SELECT label FROM lolabel WHERE loid = $1';
+CREATE FUNCTION
+INSERT INTO lolabel (SELECT lo_import('/tmp/sepgsql_test_blob1'), 'normal');
+INSERT 0 1
+INSERT INTO lolabel (SELECT lo_import('/tmp/sepgsql_test_blob1'), 'readonly');
+INSERT 0 1
+INSERT INTO lolabel (SELECT lo_import('/tmp/sepgsql_test_blob1'), 'secret');
+INSERT 0 1
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_blob_t:s0')
+       FROM lolabel WHERE label = 'normal';
+ lo_set_security 
+-----------------
+ t
+(1 row)
+
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_ro_blob_t:s0')
+       FROM lolabel WHERE label = 'readonly';
+ lo_set_security 
+-----------------
+ t
+(1 row)
+
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_secret_blob_t:s0')
+       FROM lolabel WHERE label = 'secret';
+ lo_set_security 
+-----------------
+ t
+(1 row)
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0:c0
+SELECT sepgsql_getcon();
+                 sepgsql_getcon                 
+------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_test_t:s0:c0
+(1 row)
+
+SELECT lo_get_security(loid) FROM lolabel;
+              lo_get_security               
+--------------------------------------------
+ system_u:object_r:sepgsql_blob_t:s0
+ system_u:object_r:sepgsql_ro_blob_t:s0
+ system_u:object_r:sepgsql_secret_blob_t:s0
+(3 rows)
+
+SELECT security_context, lo_label(loid) AS label, COUNT(*)
+       FROM pg_largeobject GROUP BY security_context, loid ORDER by label;
+              security_context              |  label   | count 
+--------------------------------------------+----------+-------
+ system_u:object_r:sepgsql_blob_t:s0        | normal   |    10
+ system_u:object_r:sepgsql_ro_blob_t:s0     | readonly |    10
+ system_u:object_r:sepgsql_secret_blob_t:s0 | secret   |    10
+(3 rows)
+
+-- read large object
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'40000'::int) FROM lolabel WHERE label = 'normal';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT loread(0, 32);
+                                                              loread                                                              
+----------------------------------------------------------------------------------------------------------------------------------
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+(1 row)
+
+ROLLBACK;
+ROLLBACK
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'40000'::int) FROM lolabel WHERE label = 'readonly';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT loread(0, 32);
+                                                              loread                                                              
+----------------------------------------------------------------------------------------------------------------------------------
+ \000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000
+(1 row)
+
+ROLLBACK;
+ROLLBACK
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'40000'::int) FROM lolabel WHERE label = 'secret';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT loread(0, 32);           -- to be denied
+ERROR:  SELinux: security policy violation
+ROLLBACK;
+ROLLBACK
+-- write large object
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'normal';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
+ lowrite 
+---------
+      26
+(1 row)
+
+ROLLBACK;
+ROLLBACK
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'readonly';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');        -- to be denied
+ERROR:  SELinux: security policy violation
+ROLLBACK;
+ROLLBACK
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'secret';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');        -- to be denied
+ERROR:  SELinux: security policy violation
+ROLLBACK;
+ROLLBACK
+-- create large object
+BEGIN;
+BEGIN
+INSERT INTO lolabel (SELECT lo_create(6004), 'local');
+INSERT 0 1
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'local';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT lowrite(0, 'abcdefghijklmnopqrstuvwxyz');
+ lowrite 
+---------
+      26
+(1 row)
+
+SELECT lo_close(0);
+ lo_close 
+----------
+        0
+(1 row)
+
+COMMIT;
+COMMIT
+-- getattr/setattr
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'local';
+ lo_open 
+---------
+       0
+(1 row)
+
+SELECT lo_lseek(0, 0, 2);	-- seek to end
+ lo_lseek 
+----------
+       26
+(1 row)
+
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
+ lowrite 
+---------
+      26
+(1 row)
+
+SELECT lo_tell(0);
+ lo_tell 
+---------
+      52
+(1 row)
+
+SELECT lo_lseek(0, 0, 0);	-- seek to head
+ lo_lseek 
+----------
+        0
+(1 row)
+
+SELECT loread(0, 50);
+                       loread                       
+----------------------------------------------------
+ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX
+(1 row)
+
+SELECT lo_close(0);
+ lo_close 
+----------
+        0
+(1 row)
+
+COMMIT;
+COMMIT
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- change security label
+BEGIN;
+BEGIN
+SELECT lo_open(loid, x'40000'::int) FROM lolabel;    -- a seed of trouble
+ lo_open 
+---------
+       0
+       1
+       2
+       3
+(4 rows)
+
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_blob_t:s0:c4')
+	FROM lolabel WHERE label in ('normal', 'readonly');
+ lo_set_security 
+-----------------
+ t
+ t
+(2 rows)
+
+SELECT lo_get_security(loid) FROM lolabel;
+                     lo_get_security                     
+---------------------------------------------------------
+ system_u:object_r:sepgsql_blob_t:s0:c4
+ system_u:object_r:sepgsql_blob_t:s0:c4
+ system_u:object_r:sepgsql_secret_blob_t:s0
+ unconfined_u:object_r:sepgsql_test_sepgsql_blob_t:s0:c0
+(4 rows)
+
+SELECT security_context, lo_label(loid) AS label, count(*)
+	FROM pg_largeobject WHERE loid in (SELECT loid FROM lolabel)
+	GROUP BY security_context, loid ORDER BY label;
+                    security_context                     |  label   | count 
+---------------------------------------------------------+----------+-------
+ unconfined_u:object_r:sepgsql_test_sepgsql_blob_t:s0:c0 | local    |     1
+ system_u:object_r:sepgsql_blob_t:s0:c4                  | normal   |    10
+ system_u:object_r:sepgsql_blob_t:s0:c4                  | readonly |    10
+ system_u:object_r:sepgsql_secret_blob_t:s0              | secret   |    10
+(4 rows)
+
+ROLLBACK;
+ROLLBACK
+-- cleanup
+SELECT lo_unlink(loid) FROM lolabel;
+ lo_unlink 
+-----------
+         1
+         1
+         1
+         1
+(4 rows)
+
diff -rpNU3 base/src/test/sepgsql/expected/row_level.out sepgsql-new/src/test/sepgsql/expected/row_level.out
--- base/src/test/sepgsql/expected/row_level.out	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/expected/row_level.out	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,131 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+SET
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION
+DROP FUNCTION IF EXISTS f2(int) CASCADE;
+DROP FUNCTION
+RESET client_min_messages;
+RESET
+-- test begins here
+CREATE TABLE t1 (
+       a int primary key,
+       b text
+);
+NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "t1_pkey" for table "t1"
+CREATE TABLE
+CREATE TABLE t2 (
+       x int references t1 (a) on update cascade,
+       y text
+);
+CREATE TABLE
+INSERT INTO t1 (security_context, a, b) VALUES
+       ('system_u:object_r:sepgsql_table_t:s0',		1, 'aaa'),
+       ('system_u:object_r:sepgsql_table_t:s0:c0',	2, 'bbb'),
+       ('system_u:object_r:sepgsql_table_t:s0:c1',	3, 'ccc'),
+       ('system_u:object_r:sepgsql_ro_table_t:s0',	4, 'ddd'),
+       ('system_u:object_r:sepgsql_ro_table_t:s0:c0',	5, 'eee'),
+       ('system_u:object_r:sepgsql_ro_table_t:s0:c1',	6, 'fff');
+INSERT 0 6
+INSERT INTO t2 (security_context, x, y) VALUES
+       ('system_u:object_r:sepgsql_table_t:s0:c1',	1, 'xxx'),
+       ('system_u:object_r:sepgsql_table_t:s0:c0',	2, 'yyy'),
+       ('system_u:object_r:sepgsql_table_t:s0',		3, 'zzz');
+INSERT 0 3
+SELECT security_context, * FROM t1;
+              security_context              | a |  b  
+--------------------------------------------+---+-----
+ system_u:object_r:sepgsql_table_t:s0       | 1 | aaa
+ system_u:object_r:sepgsql_table_t:s0:c0    | 2 | bbb
+ system_u:object_r:sepgsql_table_t:s0:c1    | 3 | ccc
+ system_u:object_r:sepgsql_ro_table_t:s0    | 4 | ddd
+ system_u:object_r:sepgsql_ro_table_t:s0:c0 | 5 | eee
+ system_u:object_r:sepgsql_ro_table_t:s0:c1 | 6 | fff
+(6 rows)
+
+SELECT security_context, * FROM t2;
+            security_context             | x |  y  
+-----------------------------------------+---+-----
+ system_u:object_r:sepgsql_table_t:s0:c1 | 1 | xxx
+ system_u:object_r:sepgsql_table_t:s0:c0 | 2 | yyy
+ system_u:object_r:sepgsql_table_t:s0    | 3 | zzz
+(3 rows)
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0:c0
+SELECT sepgsql_getcon();
+                 sepgsql_getcon                 
+------------------------------------------------
+ unconfined_u:unconfined_r:sepgsql_test_t:s0:c0
+(1 row)
+
+SELECT security_context, * FROM t1;
+              security_context              | a |  b  
+--------------------------------------------+---+-----
+ system_u:object_r:sepgsql_table_t:s0       | 1 | aaa
+ system_u:object_r:sepgsql_table_t:s0:c0    | 2 | bbb
+ system_u:object_r:sepgsql_ro_table_t:s0    | 4 | ddd
+ system_u:object_r:sepgsql_ro_table_t:s0:c0 | 5 | eee
+(4 rows)
+
+SELECT security_context, * FROM t2;
+            security_context             | x |  y  
+-----------------------------------------+---+-----
+ system_u:object_r:sepgsql_table_t:s0:c0 | 2 | yyy
+ system_u:object_r:sepgsql_table_t:s0    | 3 | zzz
+(2 rows)
+
+COPY t1 TO stdout;
+1	aaa
+2	bbb
+4	ddd
+5	eee
+COPY t2 (security_context, x, y) TO stdout;
+system_u:object_r:sepgsql_table_t:s0:c0	2	yyy
+system_u:object_r:sepgsql_table_t:s0	3	zzz
+UPDATE t1 SET a = 99 WHERE a = 1 RETURNING *;	-- to be failed
+ERROR:  SELinux: security policy violation
+CONTEXT:  SQL statement "UPDATE ONLY "public"."t2" SET "x" = $1 WHERE $2 OPERATOR(pg_catalog.=) "x""
+UPDATE t1 SET a = 99 WHERE a = 2 RETURNING *;
+ a  |  b  
+----+-----
+ 99 | bbb
+(1 row)
+
+UPDATE 1
+UPDATE t1 SET a = 99 WHERE a = 4 RETURNING *;	-- to be denied
+ a | b 
+---+---
+(0 rows)
+
+UPDATE 0
+INSERT INTO t1 VALUES (3, 'ccc');	-- to be failed
+ERROR:  duplicate key value violates unique constraint "t1_pkey"
+INSERT INTO t1 VALUES (7, 'ggg');
+INSERT 0 1
+INSERT INTO t2 VALUES (3, 'XXX');	-- to be failed
+ERROR:  insert or update on table "t2" violates foreign key constraint "t2_x_fkey"
+DETAIL:  Key (x)=(3) is not present in table "t1".
+INSERT INTO t2 VALUES (4, 'XXX');
+INSERT 0 1
+DELETE FROM t1;		-- to be failed
+ERROR:  SELinux: security policy violation
+CONTEXT:  SQL statement "SELECT 1 FROM ONLY "public"."t2" x WHERE $1 OPERATOR(pg_catalog.=) "x" FOR SHARE OF x"
+DELETE FROM t1 WHERE a not in (SELECT x FROM t2);	-- to be failed
+ERROR:  SELinux: security policy violation
+DELETE FROM t1 WHERE a = 7;
+DELETE 1
diff -rpNU3 base/src/test/sepgsql/expected/security_label.out sepgsql-new/src/test/sepgsql/expected/security_label.out
--- base/src/test/sepgsql/expected/security_label.out	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/expected/security_label.out	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,127 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+SELECT sepgsql_getcon();
+                   sepgsql_getcon                    
+-----------------------------------------------------
+ unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+(1 row)
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+SET
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE
+DROP TABLE IF EXISTS t1 CASCADE;
+DROP TABLE
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION
+DROP FUNCTION IF EXISTS f2(int) CASCADE;
+DROP FUNCTION
+RESET client_min_messages;
+RESET
+-- test begins here
+CREATE TABLE t1 (
+       a     int,
+       b     text
+);
+CREATE TABLE
+CREATE TABLE t2 (
+       x     int,
+       y     text
+);
+CREATE TABLE
+CREATE TABLE t3 (
+       s     int,
+       t     text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_fixed_table_t:s0';
+CREATE TABLE
+INSERT INTO t1 VALUES (1, 'aaa');
+INSERT 0 1
+INSERT INTO t1 (security_context, a, b) VALUES ('unconfined_u:object_r:sepgsql_ro_table_t:s0', 2, 'bbb');
+INSERT 0 1
+INSERT INTO t1 (security_context, a, b) VALUES ('unconfined_u:object_r:sepgsql_table_t:s0:c1', 3, 'ccc');
+INSERT 0 1
+INSERT INTO t1 VALUES (4, 'ddd'), (5, 'eee');
+INSERT 0 2
+INSERT INTO t1 (security_context, a, b) VALUES ('invalid security context', 6, 'fff');	-- to be failed
+ERROR:  invalid security label: invalid security context
+INSERT INTO t1 (security_context, a, b) VALUES ('system_u:object_r:sepgsql_table_t:s0:c20', 6, 'fff');	-- to be denied
+INSERT 0 0
+SELECT security_context, * FROM t1;
+              security_context               | a |  b  
+---------------------------------------------+---+-----
+ unconfined_u:object_r:sepgsql_table_t:s0    | 1 | aaa
+ unconfined_u:object_r:sepgsql_ro_table_t:s0 | 2 | bbb
+ unconfined_u:object_r:sepgsql_table_t:s0:c1 | 3 | ccc
+ unconfined_u:object_r:sepgsql_table_t:s0    | 4 | ddd
+ unconfined_u:object_r:sepgsql_table_t:s0    | 5 | eee
+(5 rows)
+
+INSERT INTO t2 (security_context, x, y)
+       (SELECT sepgsql_set_user(security_context, 'system_u'), a + 5, b || '_cpy' FROM t1);
+INSERT 0 5
+SELECT security_context, * FROM t2;
+            security_context             | x  |    y    
+-----------------------------------------+----+---------
+ system_u:object_r:sepgsql_table_t:s0    |  6 | aaa_cpy
+ system_u:object_r:sepgsql_ro_table_t:s0 |  7 | bbb_cpy
+ system_u:object_r:sepgsql_table_t:s0:c1 |  8 | ccc_cpy
+ system_u:object_r:sepgsql_table_t:s0    |  9 | ddd_cpy
+ system_u:object_r:sepgsql_table_t:s0    | 10 | eee_cpy
+(5 rows)
+
+INSERT INTO t3 VALUES (98, 'xxx');
+INSERT 0 1
+INSERT INTO t3 (security_context, s, t) VALUES ('system_u:object_r:sepgsql_ro_table_t:s0', 99, 'yyy');
+INSERT 0 1
+INSERT INTO t3 (SELECT * FROM t1);
+INSERT 0 5
+INSERT INTO t3 (security_context, s, t) (SELECT security_context, x, y FROM t2);
+INSERT 0 5
+SELECT security_context, * FROM t3;
+                security_context                | s  |    t    
+------------------------------------------------+----+---------
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0 | 98 | xxx
+ system_u:object_r:sepgsql_ro_table_t:s0        | 99 | yyy
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0 |  1 | aaa
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0 |  2 | bbb
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0 |  3 | ccc
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0 |  4 | ddd
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0 |  5 | eee
+ system_u:object_r:sepgsql_table_t:s0           |  6 | aaa_cpy
+ system_u:object_r:sepgsql_ro_table_t:s0        |  7 | bbb_cpy
+ system_u:object_r:sepgsql_table_t:s0:c1        |  8 | ccc_cpy
+ system_u:object_r:sepgsql_table_t:s0           |  9 | ddd_cpy
+ system_u:object_r:sepgsql_table_t:s0           | 10 | eee_cpy
+(12 rows)
+
+SELECT sepgsql_set_range(security_context, 's0:c' || s) AS security_context, * INTO t4 FROM t3;	-- partially denied
+SELECT
+SELECT security_context, * FROM t4;
+                 security_context                  | s  |    t    
+---------------------------------------------------+----+---------
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0:c1 |  1 | aaa
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0:c2 |  2 | bbb
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0:c3 |  3 | ccc
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0:c4 |  4 | ddd
+ unconfined_u:object_r:sepgsql_fixed_table_t:s0:c5 |  5 | eee
+ system_u:object_r:sepgsql_table_t:s0:c6           |  6 | aaa_cpy
+ system_u:object_r:sepgsql_ro_table_t:s0:c7        |  7 | bbb_cpy
+ system_u:object_r:sepgsql_table_t:s0:c8           |  8 | ccc_cpy
+ system_u:object_r:sepgsql_table_t:s0:c9           |  9 | ddd_cpy
+ system_u:object_r:sepgsql_table_t:s0:c10          | 10 | eee_cpy
+(10 rows)
+
+COPY t1 (security_context, a, b) FROM stdin;	-- partially denied
+COPY t1 (security_context, a, b) TO stdout;
+unconfined_u:object_r:sepgsql_table_t:s0	1	aaa
+unconfined_u:object_r:sepgsql_ro_table_t:s0	2	bbb
+unconfined_u:object_r:sepgsql_table_t:s0:c1	3	ccc
+unconfined_u:object_r:sepgsql_table_t:s0	4	ddd
+unconfined_u:object_r:sepgsql_table_t:s0	5	eee
+system_u:object_r:sepgsql_table_t:s0:c2	10	kkk
+system_u:object_r:sepgsql_table_t:s0:c3	11	lll
+system_u:object_r:sepgsql_table_t:s0:c4	13	nnn
diff -rpNU3 base/src/test/sepgsql/launch_psql.c sepgsql-new/src/test/sepgsql/launch_psql.c
--- base/src/test/sepgsql/launch_psql.c	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/launch_psql.c	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,87 @@
+/*
+ * launch_psql.c
+ *
+ * It invokes psql with proper security context.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <selinux/selinux.h>
+
+#define SETEXECCON_CMD		"-- at SECURITY_CONTEXT="
+
+int main(int argc, char *const argv[])
+{
+	char buffer[2048], cmd[512];
+	FILE *filp = NULL;
+	int i, ofs;
+
+	if (argc < 2)
+	{
+		fprintf(stderr, "usage: %s <command> [<options> ...]\n", argv[0]);
+		return 1;
+	}
+
+	for (i=1, ofs=0; argv[i] != NULL; i++)
+		ofs += snprintf(cmd + ofs, sizeof(cmd) - ofs, " %s", argv[i]);
+
+	while (fgets(buffer, sizeof(buffer), stdin) != NULL)
+	{
+		if (strncasecmp(buffer, SETEXECCON_CMD,
+						sizeof(SETEXECCON_CMD) - 1) == 0)
+		{
+			security_context_t context = buffer + sizeof(SETEXECCON_CMD) - 1;
+			char *pos;
+
+			/* set exec security context */
+			pos = strchr(context, '#');
+			if (pos)
+				*pos = '\0';
+			pos = context + strlen(context) - 1;
+			while (isspace(*pos))
+				*pos-- = '\0';
+			if (setexeccon(context) < 0)
+			{
+				fprintf(stderr, "%s: setexeccon('%s') = %s\n",
+						argv[0], context, strerror(errno));
+				return 1;
+			}
+
+			if (filp != NULL)
+			{
+				pclose(filp);
+				filp = NULL;
+			}
+
+			/* Inject a pseudo sepgsql_getcon() to confirm new context */
+			ofs = strlen(buffer);
+			snprintf(buffer + ofs, sizeof(buffer) - ofs,
+					 "\nSELECT sepgsql_getcon();\n");
+		}
+
+		if (filp == NULL)
+		{
+			filp = popen(cmd, "w");
+			if (!filp)
+			{
+				fprintf(stderr, "%s: popen('%s', 'w') = %s\n",
+						argv[0], cmd, strerror(errno));
+				return 1;
+			}
+		}
+
+		if (fwrite(buffer, 1, strlen(buffer), filp) < 0)
+		{
+			fprintf(stderr, "%s: fwrite(...) = %s\n",
+					argv[0], strerror(errno));
+			return 1;
+		}
+	}
+
+	if (filp)
+		pclose(filp);
+
+	return 0;
+}
diff -rpNU3 base/src/test/sepgsql/sql/basic.sql sepgsql-new/src/test/sepgsql/sql/basic.sql
--- base/src/test/sepgsql/sql/basic.sql	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/sql/basic.sql	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,59 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t1 CASCADE;
+
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+
+RESET client_min_messages;
+
+-- SETUP
+
+CREATE TABLE t1
+(
+    a   int,
+    b   text
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_ro_table_t:s0',
+    c   bool
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+);
+INSERT INTO t1 VALUES (1, 'aaa', false), (2, 'bbb', true);
+
+CREATE TABLE t2
+(
+    s   int,
+    t   int,
+    u   int
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c0';
+ALTER TABLE t2 DROP COLUMN t;	-- disturbing factor
+
+CREATE TABLE t3
+(
+    x   text
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c1'
+) inherits(t2);
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+
+SELECT * FROM t1;			-- to be denied
+SELECT a, b FROM t1;
+SELECT COUNT(*) FROM t1 WHERE c;	-- to be denied
+UPDATE t1 SET b = 'ccc';		-- to be denied
+UPDATE t1 SET a = a + 2;
+INSERT INTO t1 VALUES (5, 'eee', true);	-- to be denied
+INSERT INTO t1 VALUES (5);
+
+SELECT * FROM t2;
+SELECT t2 FROM t2;
+SELECT t3 FROM t3;	-- to be denied
+SELECT 1 FROM t3;
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c1
+SELECT * FROM t2;	-- to be denied
+SELECT t2 FROM t2;	-- to be denied
+SELECT t3 FROM t3;
diff -rpNU3 base/src/test/sepgsql/sql/copy_stmt.sql sepgsql-new/src/test/sepgsql/sql/copy_stmt.sql
--- base/src/test/sepgsql/sql/copy_stmt.sql	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/sql/copy_stmt.sql	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,58 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t1 CASCADE;
+
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+
+RESET client_min_messages;
+
+-- setup tables
+
+CREATE TABLE t1
+(
+    a    int,
+    b    text
+);
+
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb');
+
+CREATE TABLE t2
+(
+    x    int,
+    y    text
+         SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+);
+SELECT security_context from pg_attribute where attrelid = 't2'::regclass and attname = 'y';
+INSERT INTO t2 VALUES (1, 'xxx'), (2, 'yyy');
+
+CREATE TABLE t3	      -- read only table
+(
+    s    int,
+    t    text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_ro_table_t:s0';
+INSERT INTO t2 VALUES (1, 'sss'), (2, 'ttt');
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+COPY t1 TO stdout;
+COPY t1 FROM stdin;
+3	ccc
+4	ddd
+\.
+
+COPY t1 TO '/tmp/sepgsql_test_copy_1';
+COPY t1 TO '/tmp/sepgsql_test_copy_2';	-- to be denied
+
+COPY t2 TO stdout;	-- to be denied
+COPY t2 FROM stdin;	-- to be denied
+COPY t2 (x) TO stdout;
+
+COPY t3 TO stdout;
+COPY t3 FROM '/tmp/sepgsql_test_copy_1';	-- to be denied
+
+COPY t1 FROM '/tmp/sepgsql_test_copy_1';
+COPY t1 TO stdout;
diff -rpNU3 base/src/test/sepgsql/sql/enhanced_ddl_stmt.sql sepgsql-new/src/test/sepgsql/sql/enhanced_ddl_stmt.sql
--- base/src/test/sepgsql/sql/enhanced_ddl_stmt.sql	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/sql/enhanced_ddl_stmt.sql	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,89 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t1 CASCADE;
+
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION IF EXISTS f2(int) CASCADE;
+
+RESET client_min_messages;
+
+-- CREATE TABLE with SECURITY_LABEL clause
+CREATE TABLE t1 (
+       a int,
+       b text
+);
+SELECT relname, security_context FROM pg_class WHERE oid = 't1'::regclass;
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't1'::regclass and attnum > 0;
+
+CREATE TABLE t2 (
+       a int,
+       b text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_ro_table_t:s0';
+SELECT relname, security_context FROM pg_class WHERE oid = 't2'::regclass;
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't2'::regclass and attnum > 0;
+
+CREATE TABLE t3 (
+       a int,
+       b text SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_fixed_table_t:s0',
+       c bool SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0',
+       d int
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0:c0';
+SELECT relname, security_context FROM pg_class WHERE oid = 't3'::regclass;
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't3'::regclass and attnum > 0;
+
+CREATE TABLE t4 (
+       a int,
+       b text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:invalid_label_t:s0';	-- to be failed
+
+CREATE TABLE t4 (
+       a int,
+       b text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0';	-- to be denied
+
+-- ALTER TABLE with SECURITY_CONTEXT clause
+ALTER TABLE t2 SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0';
+ALTER TABLE t2 ADD COLUMN c bool;	-- it inherits table's one
+SELECT relname, security_context FROM pg_class WHERE oid = 't2'::regclass;
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't2'::regclass and attnum > 0;
+
+ALTER TABLE t3 ALTER b SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_table_t:s0';
+SELECT relname, security_context FROM pg_class WHERE oid = 't3'::regclass;
+SELECT attname, security_context FROM pg_attribute WHERE attrelid = 't3'::regclass and attnum > 0;
+
+-- CREATE FUNCTION with SECURITY_CONTEXT clause
+CREATE FUNCTION f1 (int) RETURNS int
+       LANGUAGE 'sql'
+       SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c0'
+       AS 'SELECT $1 * 2';
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f1'::regproc;
+
+CREATE FUNCTION f2 (int) RETURNS int
+       LANGUAGE 'sql'
+       SECURITY_CONTEXT = 'unconfined_u:object_r:invalid_label_t:s0'
+       AS 'SELECT $1 + $1';	 -- to be failed
+
+CREATE FUNCTION f2 (int) RETURNS int
+       LANGUAGE 'sql'
+       SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c16'
+       AS 'SELECT $1 + $1';	 -- to be denied
+
+CREATE FUNCTION f2 (int) RETURNS int
+       LANGUAGE 'sql'
+       AS 'SELECT $1 + $1';
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f2'::regproc;
+
+-- ALTER FUNCTION with SECURITY_CONTEXT clause
+ALTER FUNCTION f1(int)
+      SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c1';
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f1'::regproc;
+
+ALTER FUNCTION f2(int)
+      SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_proc_t:s0:c16';	-- to be denied
+SELECT proname, security_context FROM pg_proc WHERE oid = 'f2'::regproc;
diff -rpNU3 base/src/test/sepgsql/sql/join_query.sql sepgsql-new/src/test/sepgsql/sql/join_query.sql
--- base/src/test/sepgsql/sql/join_query.sql	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/sql/join_query.sql	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,50 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t1 CASCADE;
+
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+
+RESET client_min_messages;
+
+-- SETUP
+CREATE TABLE t1
+(
+    a   int,
+    b   text,
+    c   int
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+);
+INSERT INTO t1 VALUES (1, 'aaa'), (2, 'bbb'), (3, 'ccc');
+
+CREATE TABLE t2
+(
+    x   int,
+    y   text
+);
+INSERT INTO t2 VALUES (2, 'xxx'), (3, 'yyy'), (4,'zzz');
+
+CREATE TABLE t3
+(
+    d   int
+) INHERITS (t1);
+INSERT INTO t3 VALUES (4, 'ddd'), (5, 'eee');
+
+CREATE TABLE t4
+(
+    z   int
+        SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_secret_table_t:s0'
+) INHERITS (t2);
+INSERT INTO t2 VALUES (1, 'sss'), (5, 'ttt');
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0-s0:c0
+SELECT * FROM t1 JOIN t2 ON a = x;		-- to be denied
+SELECT a, b, y FROM t1 JOIN t2 ON a = x;
+SELECT a, b, y FROM t1 JOIN t2 ON c = x;	-- to be denied
+SELECT COUNT(*) FROM t1 JOIN t2 ON a = x;
+SELECT j FROM (t1 JOIN t2 ON a = x) AS j;	-- to be denied
diff -rpNU3 base/src/test/sepgsql/sql/large_object.sql sepgsql-new/src/test/sepgsql/sql/large_object.sql
--- base/src/test/sepgsql/sql/large_object.sql	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/sql/large_object.sql	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,103 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+
+DROP TABLE IF EXISTS lolabel CASCADE;
+DROP FUNCTION IF EXISTS lo_label(oid) CASCADE;
+
+RESET client_min_messages;
+
+CREATE TABLE lolabel(
+       loid	oid,
+       label	text
+);
+
+CREATE OR REPLACE FUNCTION lo_label(oid)
+       RETURNS TEXT LANGUAGE 'sql'
+       AS 'SELECT label FROM lolabel WHERE loid = $1';
+
+INSERT INTO lolabel (SELECT lo_import('/tmp/sepgsql_test_blob1'), 'normal');
+INSERT INTO lolabel (SELECT lo_import('/tmp/sepgsql_test_blob1'), 'readonly');
+INSERT INTO lolabel (SELECT lo_import('/tmp/sepgsql_test_blob1'), 'secret');
+
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_blob_t:s0')
+       FROM lolabel WHERE label = 'normal';
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_ro_blob_t:s0')
+       FROM lolabel WHERE label = 'readonly';
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_secret_blob_t:s0')
+       FROM lolabel WHERE label = 'secret';
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0:c0
+
+SELECT lo_get_security(loid) FROM lolabel;
+
+SELECT security_context, lo_label(loid) AS label, COUNT(*)
+       FROM pg_largeobject GROUP BY security_context, loid ORDER by label;
+
+-- read large object
+BEGIN;
+SELECT lo_open(loid, x'40000'::int) FROM lolabel WHERE label = 'normal';
+SELECT loread(0, 32);
+ROLLBACK;
+
+BEGIN;
+SELECT lo_open(loid, x'40000'::int) FROM lolabel WHERE label = 'readonly';
+SELECT loread(0, 32);
+ROLLBACK;
+
+BEGIN;
+SELECT lo_open(loid, x'40000'::int) FROM lolabel WHERE label = 'secret';
+SELECT loread(0, 32);           -- to be denied
+ROLLBACK;
+
+-- write large object
+BEGIN;
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'normal';
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
+ROLLBACK;
+
+BEGIN;
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'readonly';
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');        -- to be denied
+ROLLBACK;
+
+BEGIN;
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'secret';
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');        -- to be denied
+ROLLBACK;
+
+-- create large object
+BEGIN;
+INSERT INTO lolabel (SELECT lo_create(6004), 'local');
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'local';
+SELECT lowrite(0, 'abcdefghijklmnopqrstuvwxyz');
+SELECT lo_close(0);
+COMMIT;
+
+-- getattr/setattr
+BEGIN;
+SELECT lo_open(loid, x'20000'::int) FROM lolabel WHERE label = 'local';
+SELECT lo_lseek(0, 0, 2);	-- seek to end
+SELECT lowrite(0, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
+SELECT lo_tell(0);
+SELECT lo_lseek(0, 0, 0);	-- seek to head
+SELECT loread(0, 50);
+SELECT lo_close(0);
+COMMIT;
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- change security label
+BEGIN;
+SELECT lo_open(loid, x'40000'::int) FROM lolabel;    -- a seed of trouble
+SELECT lo_set_security(loid, 'system_u:object_r:sepgsql_blob_t:s0:c4')
+	FROM lolabel WHERE label in ('normal', 'readonly');
+SELECT lo_get_security(loid) FROM lolabel;
+SELECT security_context, lo_label(loid) AS label, count(*)
+	FROM pg_largeobject WHERE loid in (SELECT loid FROM lolabel)
+	GROUP BY security_context, loid ORDER BY label;
+ROLLBACK;
+
+-- cleanup
+SELECT lo_unlink(loid) FROM lolabel;
diff -rpNU3 base/src/test/sepgsql/sql/row_level.sql sepgsql-new/src/test/sepgsql/sql/row_level.sql
--- base/src/test/sepgsql/sql/row_level.sql	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/sql/row_level.sql	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,61 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t1 CASCADE;
+
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION IF EXISTS f2(int) CASCADE;
+
+RESET client_min_messages;
+
+-- test begins here
+CREATE TABLE t1 (
+       a int primary key,
+       b text
+);
+
+CREATE TABLE t2 (
+       x int references t1 (a) on update cascade,
+       y text
+);
+
+INSERT INTO t1 (security_context, a, b) VALUES
+       ('system_u:object_r:sepgsql_table_t:s0',		1, 'aaa'),
+       ('system_u:object_r:sepgsql_table_t:s0:c0',	2, 'bbb'),
+       ('system_u:object_r:sepgsql_table_t:s0:c1',	3, 'ccc'),
+       ('system_u:object_r:sepgsql_ro_table_t:s0',	4, 'ddd'),
+       ('system_u:object_r:sepgsql_ro_table_t:s0:c0',	5, 'eee'),
+       ('system_u:object_r:sepgsql_ro_table_t:s0:c1',	6, 'fff');
+
+INSERT INTO t2 (security_context, x, y) VALUES
+       ('system_u:object_r:sepgsql_table_t:s0:c1',	1, 'xxx'),
+       ('system_u:object_r:sepgsql_table_t:s0:c0',	2, 'yyy'),
+       ('system_u:object_r:sepgsql_table_t:s0',		3, 'zzz');
+
+SELECT security_context, * FROM t1;
+SELECT security_context, * FROM t2;
+
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:sepgsql_test_t:s0:c0
+SELECT security_context, * FROM t1;
+SELECT security_context, * FROM t2;
+
+COPY t1 TO stdout;
+COPY t2 (security_context, x, y) TO stdout;
+
+UPDATE t1 SET a = 99 WHERE a = 1 RETURNING *;	-- to be failed
+UPDATE t1 SET a = 99 WHERE a = 2 RETURNING *;
+UPDATE t1 SET a = 99 WHERE a = 4 RETURNING *;	-- to be denied
+
+INSERT INTO t1 VALUES (3, 'ccc');	-- to be failed
+INSERT INTO t1 VALUES (7, 'ggg');
+INSERT INTO t2 VALUES (3, 'XXX');	-- to be failed
+INSERT INTO t2 VALUES (4, 'XXX');
+
+DELETE FROM t1;		-- to be failed
+DELETE FROM t1 WHERE a not in (SELECT x FROM t2);	-- to be failed
+DELETE FROM t1 WHERE a = 7;
diff -rpNU3 base/src/test/sepgsql/sql/security_label.sql sepgsql-new/src/test/sepgsql/sql/security_label.sql
--- base/src/test/sepgsql/sql/security_label.sql	1970-01-01 09:00:00.000000000 +0900
+++ sepgsql-new/src/test/sepgsql/sql/security_label.sql	2009-03-15 17:38:39.000000000 +0900
@@ -0,0 +1,60 @@
+-- at SECURITY_CONTEXT=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c15
+
+-- cleanup previous tests
+SET client_min_messages TO 'error';
+
+DROP TABLE IF EXISTS t4 CASCADE;
+DROP TABLE IF EXISTS t3 CASCADE;
+DROP TABLE IF EXISTS t2 CASCADE;
+DROP TABLE IF EXISTS t1 CASCADE;
+
+DROP FUNCTION IF EXISTS f1(int) CASCADE;
+DROP FUNCTION IF EXISTS f2(int) CASCADE;
+
+RESET client_min_messages;
+
+-- test begins here
+CREATE TABLE t1 (
+       a     int,
+       b     text
+);
+
+CREATE TABLE t2 (
+       x     int,
+       y     text
+);
+
+CREATE TABLE t3 (
+       s     int,
+       t     text
+) SECURITY_CONTEXT = 'unconfined_u:object_r:sepgsql_fixed_table_t:s0';
+
+INSERT INTO t1 VALUES (1, 'aaa');
+INSERT INTO t1 (security_context, a, b) VALUES ('unconfined_u:object_r:sepgsql_ro_table_t:s0', 2, 'bbb');
+INSERT INTO t1 (security_context, a, b) VALUES ('unconfined_u:object_r:sepgsql_table_t:s0:c1', 3, 'ccc');
+INSERT INTO t1 VALUES (4, 'ddd'), (5, 'eee');
+INSERT INTO t1 (security_context, a, b) VALUES ('invalid security context', 6, 'fff');	-- to be failed
+INSERT INTO t1 (security_context, a, b) VALUES ('system_u:object_r:sepgsql_table_t:s0:c20', 6, 'fff');	-- to be denied
+SELECT security_context, * FROM t1;
+
+INSERT INTO t2 (security_context, x, y)
+       (SELECT sepgsql_set_user(security_context, 'system_u'), a + 5, b || '_cpy' FROM t1);
+SELECT security_context, * FROM t2;
+
+INSERT INTO t3 VALUES (98, 'xxx');
+INSERT INTO t3 (security_context, s, t) VALUES ('system_u:object_r:sepgsql_ro_table_t:s0', 99, 'yyy');
+INSERT INTO t3 (SELECT * FROM t1);
+INSERT INTO t3 (security_context, s, t) (SELECT security_context, x, y FROM t2);
+SELECT security_context, * FROM t3;
+
+SELECT sepgsql_set_range(security_context, 's0:c' || s) AS security_context, * INTO t4 FROM t3;	-- partially denied
+SELECT security_context, * FROM t4;
+
+COPY t1 (security_context, a, b) FROM stdin;	-- partially denied
+system_u:object_r:sepgsql_table_t:s0:c2	10	kkk
+system_u:object_r:sepgsql_table_t:s0:c3	11	lll
+system_u:object_r:sepgsql_table_t:s0:c20	12	mmm
+system_u:object_r:sepgsql_table_t:s0:c4	13	nnn
+\.
+
+COPY t1 (security_context, a, b) TO stdout;

sepostgresql-utils-8.3.patch:

--- NEW FILE sepostgresql-utils-8.3.patch ---
diff -rpNU3 base/src/bin/initdb/initdb.c sepgsql-new/src/bin/initdb/initdb.c
--- base/src/bin/initdb/initdb.c	2008-11-05 09:57:00.000000000 +0900
+++ sepgsql-new/src/bin/initdb/initdb.c	2009-03-13 18:14:33.000000000 +0900
@@ -94,6 +94,7 @@ static bool debug = false;
 static bool noclean = false;
 static bool show_setting = false;
 static char *xlog_dir = "";
+static bool enable_selinux = false;
 
 
 /* internal vars */
@@ -1212,6 +1213,13 @@ setup_config(void)
 						 "#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);
@@ -2383,6 +2391,7 @@ usage(const char *progname)
 	printf(_("  -U, --username=NAME       database superuser name\n"));
 	printf(_("  -W, --pwprompt            prompt for a password for the new superuser\n"));
 	printf(_("  --pwfile=FILE             read password for the new superuser from file\n"));
+	printf(_("  --enable-selinux          enables SELinux support, if compiled\n"));
 	printf(_("  -?, --help                show this help, then exit\n"));
 	printf(_("  -V, --version             output version information, then exit\n"));
 	printf(_("\nLess commonly used options:\n"));
@@ -2417,6 +2426,7 @@ main(int argc, char *argv[])
 		{"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'},
@@ -2531,6 +2541,9 @@ main(int argc, char *argv[])
 			case 9:
 				pwfilename = xstrdup(optarg);
 				break;
+			case 10:
+				enable_selinux = true;
+				break;
 			case 's':
 				show_setting = true;
 				break;
diff -rpNU3 base/src/bin/pg_dump/pg_dump.c sepgsql-new/src/bin/pg_dump/pg_dump.c
--- base/src/bin/pg_dump/pg_dump.c	2009-02-02 11:47:17.000000000 +0900
+++ sepgsql-new/src/bin/pg_dump/pg_dump.c	2009-03-13 18:14:33.000000000 +0900
@@ -118,6 +118,8 @@ static int	g_numNamespaces;
 /* flag to turn on/off dollar quoting */
 static int	disable_dollar_quoting = 0;
 
+/* flag to turn on/off security context support */
+static int	enable_selinux = 0;
 
 static void help(const char *progname);
 static void expand_schema_name_patterns(SimpleStringList *patterns,
@@ -267,6 +269,7 @@ main(int argc, char **argv)
 		{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
 		{"disable-triggers", no_argument, &disable_triggers, 1},
 		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
+		{"security-context", no_argument, &enable_selinux, 1},
 
 		{NULL, 0, NULL, 0}
 	};
@@ -419,6 +422,8 @@ main(int argc, char **argv)
 					disable_triggers = 1;
 				else if (strcmp(optarg, "use-set-session-authorization") == 0)
 					use_setsessauth = 1;
+				else if (strcmp(optarg, "security-context") == 0)
+					enable_selinux = 1;
 				else
 				{
 					fprintf(stderr,
@@ -549,6 +554,24 @@ main(int argc, char **argv)
 	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 (enable_selinux > 0)
+	{
+		const char *sepostgresql
+			= PQparameterStatus(g_conn, "sepostgresql");
+
+		if (!sepostgresql)
+		{
+			write_msg(NULL, "could not obtain server status.");
+			exit(1);
+		}
+		if (strcmp(sepostgresql, "on") != 0)
+		{
+			write_msg(NULL, "SE-PostgreSQL is not available now.");
+			exit(1);
+		}
+	}
+
 	/* Set the datestyle to ISO to ensure the dump's portability */
 	do_sql_command(g_conn, "SET DATESTYLE = ISO");
 
@@ -771,6 +794,7 @@ help(const char *progname)
 	printf(_("  --use-set-session-authorization\n"
 			 "                              use SESSION AUTHORIZATION commands instead of\n"
 	"                              ALTER OWNER commands to set ownership\n"));
+	printf(_("  --security-context          enable to dump security context of SE-PostgreSQL\n"));
 
 	printf(_("\nConnection options:\n"));
 	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
@@ -1171,7 +1195,8 @@ dumpTableData_insert(Archive *fout, void
 	if (fout->remoteVersion >= 70100)
 	{
 		appendPQExpBuffer(q, "DECLARE _pg_dump_cursor CURSOR FOR "
-						  "SELECT * FROM ONLY %s",
+						  "SELECT %s * FROM ONLY %s",
+						  (enable_selinux > 0 ? "security_context," : ""),
 						  fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
 										 classname));
 	}
@@ -1785,11 +1810,29 @@ dumpBlobComments(Archive *AH, void *arg)
 			Oid			blobOid;
 			char	   *comment;
 
+			blobOid = atooid(PQgetvalue(res, i, 0));
+			if (enable_selinux > 0)
+			{
+				char		query[256];
+				PGresult   *sres;
+
+				snprintf(query, sizeof(query),
+						 "SELECT lo_get_security(%u)", blobOid);
+				sres = PQexec(g_conn, query);
+				if (sres)
+				{
+					if (PQresultStatus(res) == PGRES_TUPLES_OK
+						&& PQntuples(res) == 1)
+						archprintf(AH, "SELECT lo_set_security(%u, '%s');\n",
+								   blobOid, PQgetvalue(sres, 0, 0));
+					PQclear(sres);
+				}
+			}
+
 			/* ignore blobs without comments */
 			if (PQgetisnull(res, i, 1))
 				continue;
 
-			blobOid = atooid(PQgetvalue(res, i, 0));
 			comment = PQgetvalue(res, i, 1);
 
 			printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
@@ -2887,6 +2930,7 @@ getTables(int *numTables)
 	int			i_owning_col;
 	int			i_reltablespace;
 	int			i_reloptions;
+	int			i_relseclabel;
 
 	/* Make sure we are in proper schema */
 	selectSourceSchema("pg_catalog");
@@ -2926,7 +2970,8 @@ getTables(int *numTables)
 						  "d.refobjid as owning_tab, "
 						  "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(c.reloptions, ', ') as reloptions, "
+						  "%s as security_label "
 						  "from pg_class c "
 						  "left join pg_depend d on "
 						  "(c.relkind = '%c' and "
@@ -2936,6 +2981,7 @@ getTables(int *numTables)
 						  "where relkind in ('%c', '%c', '%c', '%c') "
 						  "order by c.oid",
 						  username_subquery,
+						  (enable_selinux > 0 ? "c.security_context" : "NULL"),
 						  RELKIND_SEQUENCE,
 						  RELKIND_RELATION, RELKIND_SEQUENCE,
 						  RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
@@ -2955,7 +3001,8 @@ getTables(int *numTables)
 						  "d.refobjid as owning_tab, "
 						  "d.refobjsubid as owning_col, "
 						  "(SELECT spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) AS reltablespace, "
-						  "NULL as reloptions "
+						  "NULL as reloptions, "
+						  "NULL as security_label "
 						  "from pg_class c "
 						  "left join pg_depend d on "
 						  "(c.relkind = '%c' and "
@@ -2984,7 +3031,8 @@ getTables(int *numTables)
 						  "d.refobjid as owning_tab, "
 						  "d.refobjsubid as owning_col, "
 						  "NULL as reltablespace, "
-						  "NULL as reloptions "
+						  "NULL as reloptions, "
+						  "NULL as security_label, "
 						  "from pg_class c "
 						  "left join pg_depend d on "
 						  "(c.relkind = '%c' and "
@@ -3009,7 +3057,8 @@ getTables(int *numTables)
 						  "NULL::oid as owning_tab, "
 						  "NULL::int4 as owning_col, "
 						  "NULL as reltablespace, "
-						  "NULL as reloptions "
+						  "NULL as reloptions, "
+						  "NULL as security_label, "
 						  "from pg_class "
 						  "where relkind in ('%c', '%c', '%c') "
 						  "order by oid",
@@ -3029,7 +3078,8 @@ getTables(int *numTables)
 						  "NULL::oid as owning_tab, "
 						  "NULL::int4 as owning_col, "
 						  "NULL as reltablespace, "
-						  "NULL as reloptions "
+						  "NULL as reloptions, "
+						  "NULL as security_label "
 						  "from pg_class "
 						  "where relkind in ('%c', '%c', '%c') "
 						  "order by oid",
@@ -3059,7 +3109,8 @@ getTables(int *numTables)
 						  "NULL::oid as owning_tab, "
 						  "NULL::int4 as owning_col, "
 						  "NULL as reltablespace, "
-						  "NULL as reloptions "
+						  "NULL as reloptions, "
+						  "NULL as security_label "
 						  "from pg_class c "
 						  "where relkind in ('%c', '%c') "
 						  "order by oid",
@@ -3102,6 +3153,7 @@ getTables(int *numTables)
 	i_owning_col = PQfnumber(res, "owning_col");
 	i_reltablespace = PQfnumber(res, "reltablespace");
 	i_reloptions = PQfnumber(res, "reloptions");
+	i_relseclabel = PQfnumber(res, "security_label");
 
 	for (i = 0; i < ntups; i++)
 	{
@@ -3132,6 +3184,7 @@ getTables(int *numTables)
 		}
 		tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
 		tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
+		tblinfo[i].relseclabel = strdup(PQgetvalue(res, i, i_relseclabel));
 
 		/* other fields were zeroed above */
 
@@ -4320,6 +4373,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
 	int			i_atthasdef;
 	int			i_attisdropped;
 	int			i_attislocal;
+	int			i_attseclabel;
 	PGresult   *res;
 	int			ntups;
 	bool		hasdefaults;
@@ -4362,12 +4416,14 @@ getTableAttrs(TableInfo *tblinfo, int nu
 			/* need left join here to not fail on dropped columns ... */
 			appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, a.attstattarget, a.attstorage, t.typstorage, "
 				  "a.attnotnull, a.atthasdef, a.attisdropped, a.attislocal, "
-				   "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname "
+				   "pg_catalog.format_type(t.oid,a.atttypmod) as atttypname, "
+							  "%s as security_label "
 			 "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",
+							  (enable_selinux > 0 ? "a.security_context" : "NULL"),
 							  tbinfo->dobj.catId.oid);
 		}
 		else if (g_fout->remoteVersion >= 70100)
@@ -4379,7 +4435,8 @@ getTableAttrs(TableInfo *tblinfo, int nu
 			 */
 			appendPQExpBuffer(q, "SELECT a.attnum, a.attname, a.atttypmod, -1 as attstattarget, a.attstorage, t.typstorage, "
 							  "a.attnotnull, a.atthasdef, false as attisdropped, false as attislocal, "
-							  "format_type(t.oid,a.atttypmod) as atttypname "
+							  "format_type(t.oid,a.atttypmod) as atttypname, "
+							  "NULL as security_label "
 							  "from pg_attribute a left join pg_type t "
 							  "on a.atttypid = t.oid "
 							  "where a.attrelid = '%u'::oid "
@@ -4392,7 +4449,8 @@ getTableAttrs(TableInfo *tblinfo, int nu
 			/* format_type not available before 7.1 */
 			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, -1 as attstattarget, attstorage, attstorage as typstorage, "
 							  "attnotnull, atthasdef, false as attisdropped, false as attislocal, "
-							  "(select typname from pg_type where oid = atttypid) as atttypname "
+							  "(select typname from pg_type where oid = atttypid) as atttypname, "
+							  "NULL as security_label "
 							  "from pg_attribute a "
 							  "where attrelid = '%u'::oid "
 							  "and attnum > 0::int2 "
@@ -4416,6 +4474,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
 		i_atthasdef = PQfnumber(res, "atthasdef");
 		i_attisdropped = PQfnumber(res, "attisdropped");
 		i_attislocal = PQfnumber(res, "attislocal");
+		i_attseclabel = PQfnumber(res, "attseclabel");
 
 		tbinfo->numatts = ntups;
 		tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
@@ -4426,6 +4485,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
 		tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
 		tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
 		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));
@@ -4449,6 +4509,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
 			tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
 			tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
 			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')
@@ -6430,6 +6491,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	char	   *procost;
 	char	   *prorows;
 	char	   *lanname;
+	char	   *proseclabel;
 	char	   *rettypename;
 	int			nallargs;
 	char	  **allargtypes = NULL;
@@ -6459,9 +6521,11 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 						  "proallargtypes, proargmodes, proargnames, "
 						  "provolatile, proisstrict, prosecdef, "
 						  "proconfig, procost, prorows, "
-						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, "
+						  "%s as security_label "
 						  "FROM pg_catalog.pg_proc "
 						  "WHERE oid = '%u'::pg_catalog.oid",
+						  (enable_selinux > 0 ? "security_context" : "NULL"),
 						  finfo->dobj.catId.oid);
 	}
 	else if (g_fout->remoteVersion >= 80100)
@@ -6471,7 +6535,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 						  "proallargtypes, proargmodes, proargnames, "
 						  "provolatile, proisstrict, prosecdef, "
 						  "null as proconfig, 0 as procost, 0 as prorows, "
-						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, "
+						  "NULL as security_label "
 						  "FROM pg_catalog.pg_proc "
 						  "WHERE oid = '%u'::pg_catalog.oid",
 						  finfo->dobj.catId.oid);
@@ -6485,7 +6550,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 						  "proargnames, "
 						  "provolatile, proisstrict, prosecdef, "
 						  "null as proconfig, 0 as procost, 0 as prorows, "
-						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, "
+						  "NULL as security_label "
 						  "FROM pg_catalog.pg_proc "
 						  "WHERE oid = '%u'::pg_catalog.oid",
 						  finfo->dobj.catId.oid);
@@ -6499,7 +6565,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 						  "null as proargnames, "
 						  "provolatile, proisstrict, prosecdef, "
 						  "null as proconfig, 0 as procost, 0 as prorows, "
-						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname, "
+						  "NULL as security_label "
 						  "FROM pg_catalog.pg_proc "
 						  "WHERE oid = '%u'::pg_catalog.oid",
 						  finfo->dobj.catId.oid);
@@ -6515,7 +6582,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 						  "proisstrict, "
 						  "'f'::boolean as prosecdef, "
 						  "null as proconfig, 0 as procost, 0 as prorows, "
-		  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
+		  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname, "
+						  "NULL as security_label "
 						  "FROM pg_proc "
 						  "WHERE oid = '%u'::oid",
 						  finfo->dobj.catId.oid);
@@ -6531,7 +6599,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 						  "'f'::boolean as proisstrict, "
 						  "'f'::boolean as prosecdef, "
 						  "null as proconfig, 0 as procost, 0 as prorows, "
-		  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname "
+		  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname, "
+						  "NULL as security_label "
 						  "FROM pg_proc "
 						  "WHERE oid = '%u'::oid",
 						  finfo->dobj.catId.oid);
@@ -6562,6 +6631,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	procost = PQgetvalue(res, 0, PQfnumber(res, "procost"));
 	prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
 	lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
+	proseclabel = PQgetvalue(res, 0, PQfnumber(res, "security_label"));
 
 	/*
 	 * See backend/commands/define.c for details of how the 'AS' clause is
@@ -6699,6 +6769,9 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 	if (prosecdef[0] == 't')
 		appendPQExpBuffer(q, " SECURITY DEFINER");
 
+	if (proseclabel[0] != '\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
@@ -8780,6 +8853,10 @@ dumpTableSchema(Archive *fout, TableInfo
 				if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
 					appendPQExpBuffer(q, " NOT NULL");
 
+				if (tbinfo->attseclabel[j] != '\0' &&
+					strcmp(tbinfo->attseclabel[j], tbinfo->relseclabel) != 0)
+					appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", tbinfo->attseclabel[j]);
+
 				actual_atts++;
 			}
 		}
@@ -8827,6 +8904,9 @@ dumpTableSchema(Archive *fout, TableInfo
 		if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
 			appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
 
+		if (tbinfo->relseclabel[0] != '\0')
+			appendPQExpBuffer(q, " SECURITY_CONTEXT = '%s'", tbinfo->relseclabel);
+
 		appendPQExpBuffer(q, ";\n");
 
 		/* Loop dumping statistics and storage statements */
@@ -10244,6 +10324,13 @@ fmtCopyColumnList(const TableInfo *ti)
 
 	appendPQExpBuffer(q, "(");
 	needComma = false;
+
+	if (enable_selinux > 0)
+	{
+		appendPQExpBuffer(q, "%s", "security_context");
+		needComma = true;
+	}
+
 	for (i = 0; i < numatts; i++)
 	{
 		if (attisdropped[i])
diff -rpNU3 base/src/bin/pg_dump/pg_dump.h sepgsql-new/src/bin/pg_dump/pg_dump.h
--- base/src/bin/pg_dump/pg_dump.h	2009-02-02 11:47:17.000000000 +0900
+++ sepgsql-new/src/bin/pg_dump/pg_dump.h	2009-03-13 18:14:33.000000000 +0900
@@ -238,6 +238,7 @@ typedef struct _tableInfo
 	char		relkind;
 	char	   *reltablespace;	/* relation tablespace */
 	char	   *reloptions;		/* options specified by WITH (...) */
+	char	   *relseclabel;	/* security context of the relation */
 	bool		hasindex;		/* does it have any indexes? */
 	bool		hasrules;		/* does it have any rules? */
 	bool		hasoids;		/* does it have OIDs? */
@@ -262,6 +263,7 @@ typedef struct _tableInfo
 	char	   *typstorage;		/* type storage scheme */
 	bool	   *attisdropped;	/* true if attr is dropped; don't dump it */
 	bool	   *attislocal;		/* true if attr has local definition */
+	char	  **attseclabel;	/* security context of attribute (column) */
 
 	/*
 	 * Note: we need to store per-attribute notnull, default, and constraint
diff -rpNU3 base/src/bin/pg_dump/pg_dumpall.c sepgsql-new/src/bin/pg_dump/pg_dumpall.c
--- base/src/bin/pg_dump/pg_dumpall.c	2008-01-07 23:51:33.000000000 +0900
+++ sepgsql-new/src/bin/pg_dump/pg_dumpall.c	2009-03-13 18:14:33.000000000 +0900
@@ -67,6 +67,9 @@ static int	disable_triggers = 0;
 static int	use_setsessauth = 0;
 static int	server_version;
 
+/* flag to turn on/off security context support */
+static int	enable_selinux = 0;
+
 static FILE *OPF;
 static char *filename = NULL;
 
@@ -119,6 +122,7 @@ main(int argc, char *argv[])
 		{"disable-dollar-quoting", no_argument, &disable_dollar_quoting, 1},
 		{"disable-triggers", no_argument, &disable_triggers, 1},
 		{"use-set-session-authorization", no_argument, &use_setsessauth, 1},
+		{"security-context", no_argument, &enable_selinux, 1},
 
 		{NULL, 0, NULL, 0}
 	};
@@ -290,6 +294,8 @@ main(int argc, char *argv[])
 					appendPQExpBuffer(pgdumpopts, " --disable-triggers");
 				else if (strcmp(optarg, "use-set-session-authorization") == 0)
 					 /* no-op, still allowed for compatibility */ ;
+				else if (strcmp(optarg, "security-context") == 0)
+					enable_selinux = 1;
 				else
 				{
 					fprintf(stderr,
@@ -316,6 +322,8 @@ main(int argc, char *argv[])
 		appendPQExpBuffer(pgdumpopts, " --disable-triggers");
 	if (use_setsessauth)
 		appendPQExpBuffer(pgdumpopts, " --use-set-session-authorization");
+	if (enable_selinux)
+		appendPQExpBuffer(pgdumpopts, " --security-context");
 
 	if (optind < argc)
 	{
@@ -391,6 +399,24 @@ main(int argc, char *argv[])
 		}
 	}
 
+	/* check availability of SE-PostgreSQL */
+	if (enable_selinux > 0)
+	{
+		const char *sepostgresql
+			= PQparameterStatus(conn, "sepostgresql");
+
+		if (!sepostgresql)
+		{
+			fprintf(stderr, "could not obtain server status.");
+			exit(1);
+		}
+		if (strcmp(sepostgresql, "on") != 0)
+		{
+			fprintf(stderr, "SE-PostgreSQL is not available now.");
+			exit(1);
+		}
+	}
+
 	/*
 	 * Open the output file if required, otherwise use stdout
 	 */
@@ -505,6 +531,7 @@ help(void)
 	printf(_("  --use-set-session-authorization\n"
 			 "                           use SESSION AUTHORIZATION commands instead of\n"
 			 "                           OWNER TO commands\n"));
+	printf(_("  --security-context       enable to dump security context of SE-PostgreSQL\n"));
 
 	printf(_("\nConnection options:\n"));
 	printf(_("  -h, --host=HOSTNAME      database server host or socket directory\n"));
@@ -915,41 +942,46 @@ dumpCreateDB(PGconn *conn)
 	fprintf(OPF, "--\n-- Database creation\n--\n\n");
 
 	if (server_version >= 80100)
-		res = executeQuery(conn,
+		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), "
 						   "datistemplate, datacl, datconnlimit, "
-						   "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
+						   "(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");
+						   "WHERE datallowconn ORDER BY 1",
+						   (enable_selinux > 0 ? "d.security_context" : "NULL"));
 	else if (server_version >= 80000)
-		res = executeQuery(conn,
+		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), "
 						   "datistemplate, datacl, -1 as datconnlimit, "
-						   "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace "
+						   "(SELECT spcname FROM pg_tablespace t WHERE t.oid = d.dattablespace) AS dattablespace, "
+						   "NULL as security_label "
 		   "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,
+		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), "
 						   "datistemplate, datacl, -1 as datconnlimit, "
-						   "'pg_default' AS dattablespace "
+						   "'pg_default' AS dattablespace, "
+						   "NULL as security_label "
 		   "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,
+		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), "
 						   "datistemplate, '' as datacl, -1 as datconnlimit, "
-						   "'pg_default' AS dattablespace "
+						   "'pg_default' AS dattablespace, "
+						   "NULL as security_label "
 						   "FROM pg_database d "
 						   "WHERE datallowconn ORDER BY 1");
 	else
@@ -958,16 +990,18 @@ dumpCreateDB(PGconn *conn)
 		 * 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,
+		appendPQExpBuffer(buf,
 						   "SELECT datname, "
 					"(select usename from pg_shadow where usesysid=datdba), "
 						   "pg_encoding_to_char(d.encoding), "
 						   "'f' as datistemplate, "
 						   "'' as datacl, -1 as datconnlimit, "
-						   "'pg_default' AS dattablespace "
+						   "'pg_default' AS dattablespace, "
+						   "NULL as security_label "
 						   "FROM pg_database d "
 						   "ORDER BY 1");
 	}
+	res = executeQuery(conn, buf->data);
 
 	for (i = 0; i < PQntuples(res); i++)
 	{
@@ -978,6 +1012,7 @@ dumpCreateDB(PGconn *conn)
 		char	   *dbacl = PQgetvalue(res, i, 4);
 		char	   *dbconnlimit = PQgetvalue(res, i, 5);
 		char	   *dbtablespace = PQgetvalue(res, i, 6);
+		char	   *dbseclabel = PQgetvalue(res, i, 7);
 		char	   *fdbname;
 
 		fdbname = strdup(fmtId(dbname));
@@ -1021,6 +1056,9 @@ dumpCreateDB(PGconn *conn)
 				appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
 								  dbconnlimit);
 
+			if (dbseclabel[0] != '\0')
+				appendPQExpBuffer(buf, " SECURITY_CONTEXT = '%s'", dbseclabel);
+
 			appendPQExpBuffer(buf, ";\n");
 
 			if (strcmp(dbistemplate, "t") == 0)


Index: .cvsignore
===================================================================
RCS file: /cvs/pkgs/rpms/sepostgresql/devel/.cvsignore,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- .cvsignore	6 Feb 2009 02:34:41 -0000	1.13
+++ .cvsignore	27 Mar 2009 03:54:13 -0000	1.14
@@ -1 +1 @@
-postgresql-8.3.6.tar.bz2
+postgresql-8.3.7.tar.bz2


Index: sepostgresql.init
===================================================================
RCS file: /cvs/pkgs/rpms/sepostgresql/devel/sepostgresql.init,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -r1.30 -r1.31
--- sepostgresql.init	26 Feb 2009 12:31:05 -0000	1.30
+++ sepostgresql.init	27 Mar 2009 03:54:13 -0000	1.31
@@ -7,9 +7,9 @@
 # pidfile: /var/run/postmaster.pid
 #---------------------------------------------------------------------
 
-PGVERSION="8.3.6"
+PGVERSION="8.3.7"
 PGMAJORVERSION=`echo "$PGVERSION" | sed 's/^\([0-9]*\.[0-9a-z]*\).*$/\1/'`
-SEPGVERSION="2.1634"
+SEPGVERSION="1770"
 
 # source function library
 . /etc/rc.d/init.d/functions


Index: sepostgresql.spec
===================================================================
RCS file: /cvs/pkgs/rpms/sepostgresql/devel/sepostgresql.spec,v
retrieving revision 1.33
retrieving revision 1.34
diff -u -r1.33 -r1.34
--- sepostgresql.spec	26 Feb 2009 12:31:05 -0000	1.33
+++ sepostgresql.spec	27 Mar 2009 03:54:13 -0000	1.34
@@ -7,22 +7,12 @@
 # SE-PostgreSQL status extension
 %define selinux_policy_stores targeted mls
 
-# Check required policy version
-%define fedora9 %(rpm -E '%{dist}' | grep -cE '^\.fc[1-9]$')
-%if %{fedora9}
-%define required_policy_version    3.3.1
-%else
-%define required_policy_version    3.4.2
-%endif
-
-
-
 %{!?ssl:%define ssl 1}
 
 Summary: Security Enhanced PostgreSQL
 Name: sepostgresql
-Version: 8.3.6
-Release: 2.1634%{?sepgsql_extension}%{?dist}
+Version: 8.3.7
+Release: 1770%{?dist}
 License: BSD
 Group: Applications/Databases
 Url: http://code.google.com/p/sepgsql/
@@ -31,16 +21,13 @@
 Source1: sepostgresql.init
 Source2: sepostgresql.8
 Source3: sepostgresql.logrotate
-Patch0: sepostgresql-sepgsql-8.3.6-2.patch
-Patch1: sepostgresql-policy-8.3.6-2.patch
-Patch2: sepostgresql-pg_dump-8.3.6-2.patch
+Patch0: sepostgresql-core-8.3.patch
+Patch1: sepostgresql-utils-8.3.patch
+Patch2: sepostgresql-test-8.3.patch
 Patch3: sepostgresql-fedora-prefix.patch
 BuildRequires: perl glibc-devel bison flex readline-devel zlib-devel >= 1.0.4
 BuildRequires: checkpolicy libselinux-devel >= 2.0.43
-BuildRequires: selinux-policy >= %{required_policy_version}
-%if %{fedora9}
-BuildRequires: selinux-policy-devel
-%endif
+BuildRequires: selinux-policy >= 3.4.2
 %if %{ssl}
 BuildRequires: openssl-devel
 %endif
@@ -50,7 +37,7 @@
 Requires(postun): policycoreutils
 Requires: postgresql-server = %{version}
 Requires: policycoreutils >= 2.0.16 libselinux >= 2.0.43
-Requires: selinux-policy >= %{required_policy_version}
+Requires: selinux-policy >= 3.4.2
 Requires: tzdata logrotate
 
 %description
@@ -78,34 +65,28 @@
 %if %{ssl}
                 --with-openssl                  \
 %endif
-%if %{defined sepgextension}
                 --enable-debug                  \
                 --enable-cassert                \
-%endif
                 --libdir=%{_libdir}/pgsql       \
                 --datadir=%{_datadir}/sepgsql   \
                 --with-system-tzdata=/usr/share/zoneinfo
 
 # parallel build, if possible
 make %{?_smp_mflags}
-%if !%{fedora9}
 touch src/backend/security/sepgsql/policy/sepostgresql-devel.fc
 make -C src/backend/security/sepgsql/policy
-%endif
 
 %install
 rm -rf %{buildroot}
 
 make DESTDIR=%{buildroot} install
 
-%if !%{fedora9}
 for store in %{selinux_policy_stores}
 do
     install -d %{buildroot}%{_datadir}/selinux/${store}
     install -p -m 644 src/backend/security/sepgsql/policy/sepostgresql-devel.pp.${store} \
                %{buildroot}%{_datadir}/selinux/${store}/sepostgresql-devel.pp
 done
-%endif
 
 # avoid to conflict with native postgresql package
 mv %{buildroot}%{_bindir}  %{buildroot}%{_bindir}.orig
@@ -155,7 +136,6 @@
 /sbin/chkconfig --add %{name}
 /sbin/ldconfig
 
-%if !%{fedora9}
 for store in %{selinux_policy_stores}
 do
     # clean up legacy policy module (now it is unnecessary)
@@ -165,7 +145,6 @@
             -i %{_datadir}/selinux/${store}/sepostgresql-devel.pp >& /dev/null || :
     fi
 done
-%endif
 
 # Fix up non-standard file contexts
 /sbin/fixfiles -R %{name} restore || :
@@ -193,7 +172,7 @@
 
 %files
 %defattr(-,root,root,-)
-%doc COPYRIGHT README HISTORY
+%doc COPYRIGHT README
 %{_initrddir}/sepostgresql
 %{_sysconfdir}/logrotate.d/sepostgresql
 %{_bindir}/initdb.sepgsql
@@ -214,14 +193,16 @@
 %{_datadir}/sepgsql/conversion_create.sql
 %{_datadir}/sepgsql/information_schema.sql
 %{_datadir}/sepgsql/sql_features.txt
-%if !%{fedora9}
 %attr(644,root,root) %{_datadir}/selinux/*/sepostgresql-devel.pp
-%endif
 %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 Mar 27 2009 KaiGai Kohei <kaigai at kaigai.gr.jp> - 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 <kaigai at kaigai.gr.jp> - 8.3.6-2.1635
 - bugfix: possible information leak by the order of permission checks
   in row level permission checks.


Index: sources
===================================================================
RCS file: /cvs/pkgs/rpms/sepostgresql/devel/sources,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -r1.10 -r1.11
--- sources	6 Feb 2009 02:34:41 -0000	1.10
+++ sources	27 Mar 2009 03:54:13 -0000	1.11
@@ -1 +1 @@
-4f8c67d802bd03b5b844e268bba7d44a  postgresql-8.3.6.tar.bz2
+7b7e91a2221e55fe1b167e663217a96d  postgresql-8.3.7.tar.bz2


--- sepostgresql-pg_dump-8.3.6-2.patch DELETED ---


--- sepostgresql-policy-8.3.6-2.patch DELETED ---


--- sepostgresql-sepgsql-8.3.6-2.patch DELETED ---




More information about the fedora-extras-commits mailing list