- Backport features from 8.4devel tree. It contains several bug fixes,

design simplification and avoidance toward M$ patent.
This commit is contained in:
KaiGai Kohei 2008-07-11 06:40:32 +00:00
commit 18a986d45e
5 changed files with 10794 additions and 8206 deletions

View file

@ -1,13 +1,303 @@
diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
--- pgace/src/bin/pg_dump/pg_dump.c 2008-02-03 01:18:48.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dump.c 2008-02-03 01:26:35.000000000 +0900
@@ -118,6 +118,9 @@ static int g_numNamespaces;
diff -rpNU3 base/src/bin/pg_dump/pg_ace_dump.h sepgsql/src/bin/pg_dump/pg_ace_dump.h
--- base/src/bin/pg_dump/pg_ace_dump.h 1970-01-01 09:00:00.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_ace_dump.h 2008-07-11 14:10:51.000000000 +0900
@@ -0,0 +1,279 @@
+#ifndef PG_ACE_DUMP_H
+#define PG_ACE_DUMP_H
+
+#include "pg_backup.h"
+#include "pg_dump.h"
+
+#define PG_ACE_FEATURE_NOTHING 0
+#define PG_ACE_FEATURE_SELINUX 1
+
+#define SELINUX_SYSATTR_NAME "security_context"
+
+/*
+ * pg_ace_dumpCheckServerFeature
+ *
+ * This hook checks whether the server has required feature, or not.
+ */
+static inline void
+pg_ace_dumpCheckServerFeature(int feature, PGconn *conn)
+{
+ const char *serv_feature;
+
+ if (feature == PG_ACE_FEATURE_NOTHING)
+ return;
+
+ serv_feature = PQparameterStatus(conn, "pgace_security_feature");
+ if (!serv_feature)
+ {
+ fprintf(stderr, "could not get pgace_feature parameter.\n");
+ exit(1);
+ }
+
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ if (strcmp(serv_feature, "selinux") != 0)
+ {
+ fprintf(stderr, "server does not have SELinux feature\n");
+ exit(1);
+ }
+ }
+}
+
+/*
+ * pg_ace_dumpDatabaseXXXX
+ *
+ * These hooks gives a chance to inject a security system column
+ * on dumping pg_database system catalog.
+ * A modified part must have ",d.<security column>" style, and
+ * its result should be printed to buf.
+ */
+static inline const char *
+pg_ace_dumpDatabaseQuery(int feature)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ return (",d." SELINUX_SYSATTR_NAME);
+
+ return "";
+}
+
+static inline void
+pg_ace_dumpDatabasePrint(int feature, PQExpBuffer buf,
+ PGresult *res, int index)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ int i_security = PQfnumber(res, SELINUX_SYSATTR_NAME);
+ char *dbsecurity = PQgetvalue(res, index, i_security);
+
+ if (dbsecurity)
+ appendPQExpBuffer(buf, " SECURITY_CONTEXT = '%s'", dbsecurity);
+ }
+}
+
+/*
+ * pg_ace_dumpClassXXXX
+ *
+ * These hooks give a chance to inject a security system column
+ * on dumping pg_class system catalog. The modified part has to
+ * be formalized to ",c.<security column>" style. The result
+ * should be preserved at TableInfo->relsecurity to print later,
+ * if exist.
+ */
+static inline const char *
+pg_ace_dumpClassQuery(int feature)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ return (",c." SELINUX_SYSATTR_NAME);
+
+ return "";
+}
+
+static inline char *
+pg_ace_dumpClassPreserve(int feature, PGresult *res, int index)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ int attno = PQfnumber(res, SELINUX_SYSATTR_NAME);
+ char *relcontext;
+
+ if (attno < 0)
+ return NULL;
+
+ relcontext = PQgetvalue(res, index, attno);
+
+ return !relcontext ? NULL : strdup(relcontext);
+ }
+
+ return NULL;
+}
+
+static inline void
+pg_ace_dumpClassPrint(int feature, PQExpBuffer buf, TableInfo *tbinfo)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ char *relcontext = tbinfo->relsecurity;
+
+ if (relcontext)
+ appendPQExpBuffer(buf, " SECURITY_CONTEXT = '%s'", relcontext);
+
+ return;
+ }
+}
+
+/*
+ * pg_ace_dumpAttributeXXXX
+ *
+ * These hooks give a chance to inject a security system column
+ * on dumping pg_attribute system catalog. The modified part has
+ * to be formalized to ",a.<security conlumn>" style. The result
+ * should be preserved at TableInfo->attsecurity[index] to print
+ * later, if exist.
+ */
+static inline const char *
+pg_ace_dumpAttributeQuery(int feature)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ return (",a." SELINUX_SYSATTR_NAME);
+
+ return "";
+}
+
+static inline char *
+pg_ace_dumpAttributePreserve(int feature, PGresult *res, int index)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ int attno = PQfnumber(res, SELINUX_SYSATTR_NAME);
+ char *attcontext;
+
+ if (attno < 0)
+ return NULL;
+
+ attcontext = PQgetvalue(res, index, attno);
+
+ return !attcontext ? NULL : strdup(attcontext);
+ }
+
+ return NULL;
+}
+
+static inline void
+pg_ace_dumpAttributePrint(int feature, PQExpBuffer buf,
+ TableInfo *tbinfo, int index)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ char *relcontext = tbinfo->relsecurity;
+ char *attcontext = tbinfo->attsecurity[index];
+
+ if (attcontext)
+ {
+ if (relcontext && strcmp(relcontext, attcontext) == 0)
+ return;
+
+ appendPQExpBuffer(buf, " SECURITY_CONTEXT = '%s'", attcontext);
+ }
+ return;
+ }
+}
+
+/*
+ * pg_ace_dumpProcXXXX
+ *
+ * These hooks give a chance to inject a security system column
+ * on dumping pg_proc system catalog. The modified part has to be
+ * formalized to "<security conlumn>" style. The result should be
+ * printed later, if exist.
+ */
+static inline const char *
+pg_ace_dumpProcQuery(int feature)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ return ("," SELINUX_SYSATTR_NAME);
+
+ return "";
+}
+
+static inline void
+pg_ace_dumpProcPrint(int feature, PQExpBuffer buf,
+ PGresult *res, int index)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ int i_selinux = PQfnumber(res, SELINUX_SYSATTR_NAME);
+ char *prosecurity;
+
+ if (i_selinux < 0)
+ return;
+
+ prosecurity = PQgetvalue(res, index, i_selinux);
+ if (prosecurity)
+ appendPQExpBuffer(buf, " SECURITY_CONTEXT = '%s'", prosecurity);
+ }
+}
+
+/*
+ * pg_ace_dumpTableDataQuery
+ *
+ * This hook gives a chance to inject a security attribute system column
+ * on dumping of user's table.
+ * It must have ",<security column>" style.
+ */
+static inline const char *
+pg_ace_dumpTableDataQuery(int feature)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ return ("," SELINUX_SYSATTR_NAME);
+
+ return "";
+}
+
+/*
+ * pg_ace_dumpCopyColumnList
+ *
+ * This hook gives a chance to inject a security attribute column within
+ * COPY statement. When a column is added, you have to return true. It
+ * enables to set needComma 'true', otherwise 'false'.
+ */
+static inline bool
+pg_ace_dumpCopyColumnList(int feature, PQExpBuffer buf)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ appendPQExpBuffer(buf, SELINUX_SYSATTR_NAME);
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * pg_ace_dumpBlobComments
+ *
+ * This hook gives a chance to inject a query to restore a security
+ * attribute of binary large object.
+ */
+static inline void
+pg_ace_dumpBlobComments(int feature, Archive *AH, PGconn *conn, Oid blobOid)
+{
+ if (feature == PG_ACE_FEATURE_SELINUX)
+ {
+ PGresult *res;
+ char query[256];
+
+ snprintf(query, sizeof(query),
+ "SELECT lo_get_security(%u)", blobOid);
+ res = PQexec(conn, query);
+ if (!res)
+ return;
+
+ if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
+ archprintf(AH, "SELECT lo_set_security(%u, '%s');\n",
+ blobOid, PQgetvalue(res, 0, 0));
+
+ PQclear(res);
+ }
+}
+
+#endif
diff -rpNU3 base/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
--- base/src/bin/pg_dump/pg_dump.c 2008-02-03 01:11:28.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dump.c 2008-07-11 14:10:51.000000000 +0900
@@ -50,6 +50,7 @@ int optreset;
#include "pg_backup_archiver.h"
#include "dumputils.h"
+#include "pg_ace_dump.h"
extern char *optarg;
extern int optind,
@@ -118,6 +119,8 @@ static int g_numNamespaces;
/* flag to turn on/off dollar quoting */
static int disable_dollar_quoting = 0;
+/* flag to tuen on/off SE-PostgreSQL support */
+#define SELINUX_SYSATTR_NAME "security_context"
+static int enable_selinux = 0;
+/* flag to turn on/off security attribute support */
+static int pg_ace_feature = PG_ACE_FEATURE_NOTHING;
static void help(const char *progname);
static void expand_schema_name_patterns(SimpleStringList *patterns,
@ -15,7 +305,7 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
{"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},
+ {"enable-selinux", no_argument, &enable_selinux, 1},
+ {"security-context", no_argument, &pg_ace_feature, PG_ACE_FEATURE_SELINUX},
{NULL, 0, NULL, 0}
};
@ -23,79 +313,45 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
disable_triggers = 1;
else if (strcmp(optarg, "use-set-session-authorization") == 0)
use_setsessauth = 1;
+ else if (strcmp(optarg, "enable-selinux") == 0)
+ enable_selinux = 1;
+ else if (strcmp(optarg, "security-context") == 0)
+ pg_ace_feature = PG_ACE_FEATURE_SELINUX;
else
{
fprintf(stderr,
@@ -549,6 +555,24 @@ main(int argc, char **argv)
@@ -549,6 +555,8 @@ main(int argc, char **argv)
std_strings = PQparameterStatus(g_conn, "standard_conforming_strings");
g_fout->std_strings = (std_strings && strcmp(std_strings, "on") == 0);
+ if (enable_selinux) {
+ /* confirm whther server support SELinux features */
+ const char *tmp = PQparameterStatus(g_conn, "security_sysattr_name");
+
+ if (!tmp) {
+ write_msg(NULL, "could not get security_sysattr_name from libpq\n");
+ exit(1);
+ }
+ if (!!strcmp(SELINUX_SYSATTR_NAME, tmp) != 0) {
+ write_msg(NULL, "server does not have SELinux feature\n");
+ exit(1);
+ }
+ if (g_fout->remoteVersion < 80204) {
+ write_msg(NULL, "server version is too old (%u)\n", g_fout->remoteVersion);
+ exit(1);
+ }
+ }
+ pg_ace_dumpCheckServerFeature(pg_ace_feature, g_conn);
+
/* Set the datestyle to ISO to ensure the dump's portability */
do_sql_command(g_conn, "SET DATESTYLE = ISO");
@@ -771,6 +795,7 @@ help(const char *progname)
@@ -771,6 +779,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(_(" --enable-selinux enable to dump security context in SE-PostgreSQL\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"));
@@ -1160,7 +1185,8 @@ dumpTableData_insert(Archive *fout, void
@@ -1160,7 +1169,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 ? "" : "," SELINUX_SYSATTR_NAME),
+ pg_ace_dumpTableDataQuery(pg_ace_feature),
fmtQualifiedId(tbinfo->dobj.namespace->dobj.name,
classname));
}
@@ -1774,11 +1800,32 @@ dumpBlobComments(Archive *AH, void *arg)
@@ -1774,11 +1784,14 @@ dumpBlobComments(Archive *AH, void *arg)
Oid blobOid;
char *comment;
+ blobOid = atooid(PQgetvalue(res, i, 0));
+
+ /* dump security context of binary large object */
+ if (enable_selinux) {
+ PGresult *__res;
+ char query[512];
+
+ snprintf(query, sizeof(query),
+ "SELECT lo_get_security(%u)", blobOid);
+ __res = PQexec(g_conn, query);
+ check_sql_result(__res, g_conn, query, PGRES_TUPLES_OK);
+
+ if (PQntuples(__res) != 1) {
+ write_msg(NULL, "lo_get_security(%u) returns %d tuples\n",
+ blobOid, PQntuples(__res));
+ exit_nicely();
+ }
+ archprintf(AH, "SELECT lo_set_security(%u, '%s');\n",
+ blobOid, PQgetvalue(__res, 0, 0));
+ PQclear(__res);
+ }
+ pg_ace_dumpBlobComments(pg_ace_feature, AH, g_conn, blobOid);
+
/* ignore blobs without comments */
if (PQgetisnull(res, i, 1))
@ -105,15 +361,7 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
comment = PQgetvalue(res, i, 1);
printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
@@ -2886,6 +2933,7 @@ getTables(int *numTables)
int i_owning_col;
int i_reltablespace;
int i_reloptions;
+ int i_selinux;
/* Make sure we are in proper schema */
selectSourceSchema("pg_catalog");
@@ -2926,6 +2974,7 @@ getTables(int *numTables)
@@ -2926,6 +2939,7 @@ getTables(int *numTables)
"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 "
@ -121,41 +369,23 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
"from pg_class c "
"left join pg_depend d on "
"(c.relkind = '%c' and "
@@ -2935,6 +2984,7 @@ getTables(int *numTables)
@@ -2935,6 +2949,7 @@ getTables(int *numTables)
"where relkind in ('%c', '%c', '%c', '%c') "
"order by c.oid",
username_subquery,
+ (!enable_selinux ? "" : ",c." SELINUX_SYSATTR_NAME),
+ pg_ace_dumpClassQuery(pg_ace_feature),
RELKIND_SEQUENCE,
RELKIND_RELATION, RELKIND_SEQUENCE,
RELKIND_VIEW, RELKIND_COMPOSITE_TYPE);
@@ -3101,6 +3151,7 @@ getTables(int *numTables)
i_owning_col = PQfnumber(res, "owning_col");
i_reltablespace = PQfnumber(res, "reltablespace");
i_reloptions = PQfnumber(res, "reloptions");
+ i_selinux = PQfnumber(res, SELINUX_SYSATTR_NAME);
for (i = 0; i < ntups; i++)
{
@@ -3131,6 +3182,9 @@ getTables(int *numTables)
@@ -3131,6 +3146,7 @@ getTables(int *numTables)
}
tblinfo[i].reltablespace = strdup(PQgetvalue(res, i, i_reltablespace));
tblinfo[i].reloptions = strdup(PQgetvalue(res, i, i_reloptions));
+ tblinfo[i].relsecurity = NULL;
+ if (i_selinux >= 0)
+ tblinfo[i].relsecurity = strdup(PQgetvalue(res, i, i_selinux));
+ tblinfo[i].relsecurity = pg_ace_dumpClassPreserve(pg_ace_feature, res, i);
/* other fields were zeroed above */
@@ -4319,6 +4373,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
int i_atthasdef;
int i_attisdropped;
int i_attislocal;
+ int i_attselinux;
PGresult *res;
int ntups;
bool hasdefaults;
@@ -4362,11 +4417,13 @@ getTableAttrs(TableInfo *tblinfo, int nu
@@ -4362,11 +4378,13 @@ getTableAttrs(TableInfo *tblinfo, int nu
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 "
@ -165,19 +395,11 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
"where a.attrelid = '%u'::pg_catalog.oid "
"and a.attnum > 0::pg_catalog.int2 "
"order by a.attrelid, a.attnum",
+ (!enable_selinux ? "" : ",a." SELINUX_SYSATTR_NAME),
+ pg_ace_dumpAttributeQuery(pg_ace_feature),
tbinfo->dobj.catId.oid);
}
else if (g_fout->remoteVersion >= 70100)
@@ -4415,6 +4472,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
i_atthasdef = PQfnumber(res, "atthasdef");
i_attisdropped = PQfnumber(res, "attisdropped");
i_attislocal = PQfnumber(res, "attislocal");
+ i_attselinux = PQfnumber(res, SELINUX_SYSATTR_NAME);
tbinfo->numatts = ntups;
tbinfo->attnames = (char **) malloc(ntups * sizeof(char *));
@@ -4425,6 +4483,7 @@ getTableAttrs(TableInfo *tblinfo, int nu
@@ -4425,6 +4443,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));
@ -185,97 +407,67 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.c sepgsql/src/bin/pg_dump/pg_dump.c
tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
@@ -4456,6 +4515,11 @@ getTableAttrs(TableInfo *tblinfo, int nu
@@ -4456,6 +4475,8 @@ getTableAttrs(TableInfo *tblinfo, int nu
tbinfo->inhAttrs[j] = false;
tbinfo->inhAttrDef[j] = false;
tbinfo->inhNotNull[j] = false;
+
+ /* security attribute, if defined */
+ tbinfo->attsecurity[j] = NULL;
+ if (i_attselinux >= 0 && !PQgetisnull(res, j, i_attselinux))
+ tbinfo->attsecurity[j] = strdup(PQgetvalue(res, j, i_attselinux));
+ tbinfo->attsecurity[j] = pg_ace_dumpAttributePreserve(pg_ace_feature, res, j);
}
PQclear(res);
@@ -6428,6 +6492,7 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
char *proconfig;
char *procost;
char *prorows;
+ char *proselinux = NULL;
char *lanname;
char *rettypename;
int nallargs;
@@ -6459,8 +6524,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
@@ -6459,8 +6480,10 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
"provolatile, proisstrict, prosecdef, "
"proconfig, procost, prorows, "
"(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname "
+ "%s " /* security context, if required */
"FROM pg_catalog.pg_proc "
"WHERE oid = '%u'::pg_catalog.oid",
+ (!enable_selinux ? "" : "," SELINUX_SYSATTR_NAME),
+ pg_ace_dumpProcQuery(pg_ace_feature),
finfo->dobj.catId.oid);
}
else if (g_fout->remoteVersion >= 80100)
@@ -6562,6 +6629,13 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
prorows = PQgetvalue(res, 0, PQfnumber(res, "prorows"));
lanname = PQgetvalue(res, 0, PQfnumber(res, "lanname"));
+ if (enable_selinux) {
+ int i_selinux = PQfnumber(res, "security_context");
+
+ if (i_selinux >= 0 && !PQgetisnull(res, 0, i_selinux))
+ proselinux = PQgetvalue(res, 0, i_selinux);
+ }
+
/*
* See backend/commands/define.c for details of how the 'AS' clause is
* used.
@@ -6698,6 +6772,9 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
@@ -6698,6 +6721,8 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
if (prosecdef[0] == 't')
appendPQExpBuffer(q, " SECURITY DEFINER");
+ if (proselinux)
+ appendPQExpBuffer(q, " CONTEXT = '%s'", proselinux);
+ pg_ace_dumpProcPrint(pg_ace_feature, q, res, 0);
+
/*
* 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
@@ -8779,6 +8856,9 @@ dumpTableSchema(Archive *fout, TableInfo
@@ -8779,6 +8804,8 @@ dumpTableSchema(Archive *fout, TableInfo
if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
appendPQExpBuffer(q, " NOT NULL");
+ if (enable_selinux && tbinfo->attsecurity[j])
+ appendPQExpBuffer(q, " CONTEXT = '%s'", tbinfo->attsecurity[j]);
+ pg_ace_dumpAttributePrint(pg_ace_feature, q, tbinfo, j);
+
actual_atts++;
}
}
@@ -8826,6 +8906,9 @@ dumpTableSchema(Archive *fout, TableInfo
@@ -8826,6 +8853,8 @@ dumpTableSchema(Archive *fout, TableInfo
if (tbinfo->reloptions && strlen(tbinfo->reloptions) > 0)
appendPQExpBuffer(q, "\nWITH (%s)", tbinfo->reloptions);
+ if (enable_selinux && tbinfo->relsecurity)
+ appendPQExpBuffer(q, " CONTEXT = '%s'", tbinfo->relsecurity);
+ pg_ace_dumpClassPrint(pg_ace_feature, q, tbinfo);
+
appendPQExpBuffer(q, ";\n");
/* Loop dumping statistics and storage statements */
@@ -10243,6 +10326,12 @@ fmtCopyColumnList(const TableInfo *ti)
@@ -10243,6 +10272,10 @@ fmtCopyColumnList(const TableInfo *ti)
appendPQExpBuffer(q, "(");
needComma = false;
+
+ if (enable_selinux) {
+ appendPQExpBuffer(q, SELINUX_SYSATTR_NAME);
+ if (pg_ace_dumpCopyColumnList(pg_ace_feature, q))
+ needComma = true;
+ }
+
for (i = 0; i < numatts; i++)
{
if (attisdropped[i])
diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.h sepgsql/src/bin/pg_dump/pg_dump.h
--- pgace/src/bin/pg_dump/pg_dump.h 2008-01-08 01:39:49.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dump.h 2008-01-10 18:25:12.000000000 +0900
diff -rpNU3 base/src/bin/pg_dump/pg_dump.h sepgsql/src/bin/pg_dump/pg_dump.h
--- base/src/bin/pg_dump/pg_dump.h 2008-01-07 23:51:33.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dump.h 2008-06-15 22:27:55.000000000 +0900
@@ -238,6 +238,7 @@ typedef struct _tableInfo
char relkind;
char *reltablespace; /* relation tablespace */
@ -292,16 +484,23 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dump.h sepgsql/src/bin/pg_dump/pg_dump.h
/*
* Note: we need to store per-attribute notnull, default, and constraint
diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpall.c
--- pgace/src/bin/pg_dump/pg_dumpall.c 2008-01-08 01:39:49.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dumpall.c 2008-01-10 18:25:12.000000000 +0900
@@ -67,6 +67,10 @@ static int disable_triggers = 0;
diff -rpNU3 base/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpall.c
--- base/src/bin/pg_dump/pg_dumpall.c 2008-01-07 23:51:33.000000000 +0900
+++ sepgsql/src/bin/pg_dump/pg_dumpall.c 2008-07-11 14:10:51.000000000 +0900
@@ -27,6 +27,7 @@ int optreset;
#endif
#include "dumputils.h"
+#include "pg_ace_dump.h"
/* version string we expect back from pg_dump */
@@ -67,6 +68,9 @@ static int disable_triggers = 0;
static int use_setsessauth = 0;
static int server_version;
+/* flag to tuen on/off SE-PostgreSQL support */
+#define SELINUX_SYSATTR_NAME "security_context"
+static int enable_selinux = 0;
+/* flag to turn on/off security attribute support */
+static int pg_ace_feature = PG_ACE_FEATURE_NOTHING;
+
static FILE *OPF;
static char *filename = NULL;
@ -310,67 +509,46 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpal
{"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},
+ {"enable-selinux", no_argument, NULL, 1001},
+ {"security-context", no_argument, &pg_ace_feature, PG_ACE_FEATURE_SELINUX},
{NULL, 0, NULL, 0}
};
@@ -290,6 +295,10 @@ main(int argc, char *argv[])
@@ -290,6 +295,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, "enable-selinux") == 0) {
+ appendPQExpBuffer(pgdumpopts, " --enable-selinux");
+ enable_selinux = 1;
+ }
+ else if (strcmp(optarg, "security-context") == 0)
+ pg_ace_feature = PG_ACE_FEATURE_SELINUX;
else
{
fprintf(stderr,
@@ -300,6 +309,11 @@ main(int argc, char *argv[])
}
break;
@@ -316,6 +323,8 @@ main(int argc, char *argv[])
appendPQExpBuffer(pgdumpopts, " --disable-triggers");
if (use_setsessauth)
appendPQExpBuffer(pgdumpopts, " --use-set-session-authorization");
+ if (pg_ace_feature == PG_ACE_FEATURE_SELINUX)
+ appendPQExpBuffer(pgdumpopts, " --security-context");
+ case 1001:
+ appendPQExpBuffer(pgdumpopts, " --enable-selinux");
+ enable_selinux = 1;
+ break;
+
case 0:
break;
@@ -391,6 +405,24 @@ main(int argc, char *argv[])
if (optind < argc)
{
@@ -391,6 +400,8 @@ main(int argc, char *argv[])
}
}
+ if (enable_selinux) {
+ /* confirm whther server support SELinux features */
+ const char *tmp = PQparameterStatus(conn, "security_sysattr_name");
+
+ if (!tmp) {
+ fprintf(stderr, "could not get security_sysattr_name from libpq\n");
+ exit(1);
+ }
+ if (!!strcmp(SELINUX_SYSATTR_NAME, tmp) != 0) {
+ fprintf(stderr, "server does not have SELinux feature\n");
+ exit(1);
+ }
+ if (server_version < 80204) {
+ fprintf(stderr, "server version is too old (%u)\n", server_version);
+ exit(1);
+ }
+ }
+ pg_ace_dumpCheckServerFeature(pg_ace_feature, conn);
+
/*
* Open the output file if required, otherwise use stdout
*/
@@ -505,6 +537,7 @@ help(void)
@@ -505,6 +516,7 @@ help(void)
printf(_(" --use-set-session-authorization\n"
" use SESSION AUTHORIZATION commands instead of\n"
" OWNER TO commands\n"));
+ printf(_(" --enable-selinux enable to dump security attribute\n"));
+ printf(_(" --security-context enables to dump security context of SE-PostgreSQL\n"));
printf(_("\nConnection options:\n"));
printf(_(" -h, --host=HOSTNAME database server host or socket directory\n"));
@@ -915,16 +948,18 @@ dumpCreateDB(PGconn *conn)
@@ -915,16 +927,18 @@ dumpCreateDB(PGconn *conn)
fprintf(OPF, "--\n-- Database creation\n--\n\n");
if (server_version >= 80100)
@ -385,14 +563,14 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpal
"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 ? "" : "d." SELINUX_SYSATTR_NAME));
+ pg_ace_dumpDatabaseQuery(pg_ace_feature));
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), "
@@ -933,7 +968,7 @@ dumpCreateDB(PGconn *conn)
@@ -933,7 +947,7 @@ dumpCreateDB(PGconn *conn)
"FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
"WHERE datallowconn ORDER BY 1");
else if (server_version >= 70300)
@ -401,7 +579,7 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpal
"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), "
@@ -942,7 +977,7 @@ dumpCreateDB(PGconn *conn)
@@ -942,7 +956,7 @@ dumpCreateDB(PGconn *conn)
"FROM pg_database d LEFT JOIN pg_shadow u ON (datdba = usesysid) "
"WHERE datallowconn ORDER BY 1");
else if (server_version >= 70100)
@ -410,7 +588,7 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpal
"SELECT datname, "
"coalesce("
"(select usename from pg_shadow where usesysid=datdba), "
@@ -958,7 +993,7 @@ dumpCreateDB(PGconn *conn)
@@ -958,7 +972,7 @@ 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.
*/
@ -419,7 +597,7 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpal
"SELECT datname, "
"(select usename from pg_shadow where usesysid=datdba), "
"pg_encoding_to_char(d.encoding), "
@@ -968,6 +1003,7 @@ dumpCreateDB(PGconn *conn)
@@ -968,6 +982,7 @@ dumpCreateDB(PGconn *conn)
"FROM pg_database d "
"ORDER BY 1");
}
@ -427,20 +605,11 @@ diff -rpNU3 pgace/src/bin/pg_dump/pg_dumpall.c sepgsql/src/bin/pg_dump/pg_dumpal
for (i = 0; i < PQntuples(res); i++)
{
@@ -978,6 +1014,7 @@ dumpCreateDB(PGconn *conn)
char *dbacl = PQgetvalue(res, i, 4);
char *dbconnlimit = PQgetvalue(res, i, 5);
char *dbtablespace = PQgetvalue(res, i, 6);
+ char *dbsecurity = PQgetvalue(res, i, 7);
char *fdbname;
fdbname = strdup(fmtId(dbname));
@@ -1021,6 +1058,9 @@ dumpCreateDB(PGconn *conn)
@@ -1021,6 +1036,8 @@ dumpCreateDB(PGconn *conn)
appendPQExpBuffer(buf, " CONNECTION LIMIT = %s",
dbconnlimit);
+ if (enable_selinux && dbsecurity)
+ appendPQExpBuffer(buf, " CONTEXT = '%s'", dbsecurity);
+ pg_ace_dumpDatabasePrint(pg_ace_feature, buf, res, i);
+
appendPQExpBuffer(buf, ";\n");

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -9,7 +9,7 @@
PGVERSION="8.3.3"
PGMAJORVERSION=`echo "$PGVERSION" | sed 's/^\([0-9]*\.[0-9a-z]*\).*$/\1/'`
SEPGVERSION="2.869"
SEPGVERSION="2.947"
# source function library
. /etc/rc.d/init.d/functions

View file

@ -4,39 +4,52 @@
# Copyright 2007 KaiGai Kohei <kaigai@kaigai.gr.jp>
# -----------------------------------------------------
# SELinux policy types
%define selinux_variants mls strict targeted
# SE-PostgreSQL status extension
%define selinux_policy_stores targeted mls
# check policy dependency
%define fullset_policy %(rpm -E '%{dist}' | grep -cE '^\.fc[1-9]$')
%if %{fullset_policy}
%define required_policy_version 3.0.6
%define policy_module_name sepostgresql
%else
%define required_policy_version 3.4.2
%define policy_module_name sepostgresql-devel
%endif
%{!?ssl:%define ssl 1}
Summary: Security Enhanced PostgreSQL
Name: sepostgresql
Version: 8.3.3
Release: 2.869%{?sepgsql_extension}%{?dist}
Release: 2.947%{?sepgsql_extension}%{?dist}
License: BSD
Group: Applications/Databases
Url: http://code.google.com/p/sepgsql/
Buildroot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
Source0: ftp://ftp.postgresql.org/pub/source/v%{version}/postgresql-%{version}.tar.bz2
Source1: sepostgresql.init
Source2: sepostgresql.if
Source3: sepostgresql.te
Source4: sepostgresql.fc
Source5: sepostgresql.8
Source6: sepostgresql.logrotate
Patch0: sepostgresql-pgace-8.3.3-2.patch
Patch1: sepostgresql-sepgsql-8.3.3-2.patch
Source2: sepostgresql.8
Source3: sepostgresql.logrotate
Patch0: sepostgresql-sepgsql-8.3.3-2.patch
Patch1: sepostgresql-policy-8.3.3-2.patch
Patch2: sepostgresql-pg_dump-8.3.3-2.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 selinux-policy-devel selinux-policy >= 3.0.6
BuildRequires: checkpolicy libselinux-devel >= 2.0.43 selinux-policy-devel
BuildRequires: selinux-policy >= %{required_policy_version}
%if %{ssl}
BuildRequires: openssl-devel
%endif
Requires(pre): shadow-utils
Requires(post): policycoreutils /sbin/chkconfig
Requires(preun): /sbin/chkconfig /sbin/service
Requires(postun): policycoreutils
Requires: postgresql-server = %{version}
Requires: policycoreutils >= 2.0.16 libselinux >= 2.0.43 selinux-policy >= 3.0.6
Requires: policycoreutils >= 2.0.16 libselinux >= 2.0.43
Requires: selinux-policy >= %{required_policy_version}
Requires: tzdata logrotate
%description
@ -53,23 +66,11 @@ reference monitor to check any SQL query.
%patch1 -p1
%patch2 -p1
%patch3 -p1
mkdir selinux-policy
cp -p %{SOURCE2} %{SOURCE3} %{SOURCE4} selinux-policy
%build
CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS
CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS
# build Binary Policy Module
pushd selinux-policy
for selinuxvariant in %{selinux_variants}
do
make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile
mv %{name}.pp %{name}.pp.${selinuxvariant}
make NAME=${selinuxvariant} -f %{_datadir}/selinux/devel/Makefile clean
done
popd
# build SE-PostgreSQL
%configure --disable-rpath \
--enable-selinux \
@ -78,25 +79,29 @@ popd
--enable-cassert \
%endif
--libdir=%{_libdir}/pgsql \
%if %{ssl}
--with-openssl \
%endif
--datadir=%{_datadir}/sepgsql \
--with-system-tzdata=/usr/share/zoneinfo
# parallel build, if possible
make %{?_smp_mflags}
# to create empty .fc file
touch src/backend/security/sepgsql/policy/%{policy_module_name}.fc
make -C src/backend/security/sepgsql/policy
%install
rm -rf %{buildroot}
pushd selinux-policy
for selinuxvariant in %{selinux_variants}
do
install -d %{buildroot}%{_datadir}/selinux/${selinuxvariant}
install -p -m 644 %{name}.pp.${selinuxvariant} \
%{buildroot}%{_datadir}/selinux/${selinuxvariant}/%{name}.pp
done
popd
make DESTDIR=%{buildroot} install
make DESTDIR=%{buildroot} install
for store in %{selinux_policy_stores}
do
install -d %{buildroot}%{_datadir}/selinux/${store}
install -p -m 644 src/backend/security/sepgsql/policy/%{policy_module_name}.pp.${store} \
%{buildroot}%{_datadir}/selinux/${store}/%{policy_module_name}.pp
done
# avoid to conflict with native postgresql package
mv %{buildroot}%{_bindir} %{buildroot}%{_bindir}.orig
@ -124,13 +129,13 @@ install -d -m 700 %{buildroot}%{_localstatedir}/lib/sepgsql/backups
mkdir -p %{buildroot}%{_initrddir}
install -p -m 755 %{SOURCE1} %{buildroot}%{_initrddir}/sepostgresql
# /etc/logrotate.d/
mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d
install -p -m 644 %{SOURCE6} %{buildroot}%{_sysconfdir}/logrotate.d/sepostgresql
# /usr/share/man/*
mkdir -p %{buildroot}%{_mandir}/man8
install -p -m 644 %{SOURCE5} %{buildroot}%{_mandir}/man8
install -p -m 644 %{SOURCE2} %{buildroot}%{_mandir}/man8
# /etc/logrotate.d/
mkdir -p %{buildroot}%{_sysconfdir}/logrotate.d
install -p -m 644 %{SOURCE3} %{buildroot}%{_sysconfdir}/logrotate.d/sepostgresql
%clean
rm -rf %{buildroot}
@ -146,13 +151,18 @@ exit 0
/sbin/chkconfig --add %{name}
/sbin/ldconfig
for selinuxvariant in %{selinux_variants}
for store in %{selinux_policy_stores}
do
%{_sbindir}/semodule -s ${selinuxvariant} -l >& /dev/null || continue;
%{_sbindir}/semodule -s ${selinuxvariant} -l | egrep -q '^%{name}' && \
%{_sbindir}/semodule -s ${selinuxvariant} -r %{name} >& /dev/null || :
%{_sbindir}/semodule -s ${selinuxvariant} -i %{_datadir}/selinux/${selinuxvariant}/%{name}.pp >& /dev/null || :
%if %{fullset_policy}
%{_sbindir}/semodule -s ${store} -r %{policy_module_name} >& /dev/null || :
%{_sbindir}/semodule -s ${store} \
-i %{_datadir}/selinux/${store}/%{policy_module_name}.pp >& /dev/null || :
%else
if %{_sbindir}/semodule -s ${store} -l | grep -Eq "^%{policy_module_name}"; then
%{_sbindir}/semodule -s ${store} \
-u %{_datadir}/selinux/${store}/%{policy_module_name}.pp >& /dev/null || :
fi
%endif
done
# Fix up non-standard file contexts
@ -171,12 +181,9 @@ if [ $1 -ge 1 ]; then # rpm -U case
/sbin/service %{name} condrestart >/dev/null 2>&1 || :
fi
if [ $1 -eq 0 ]; then # rpm -e case
for selinuxvariant in %{selinux_variants}
for store in %{selinux_policy_stores}
do
%{_sbindir}/semodule -s ${selinuxvariant} -l >& /dev/null || continue;
%{_sbindir}/semodule -s ${selinuxvariant} -l | egrep -q '^%{name}' && \
%{_sbindir}/semodule -s ${selinuxvariant} -r %{name} >& /dev/null || :
%{_sbindir}/semodule -s ${store} -r %{policy_module_name} >& /dev/null || :
done
/sbin/fixfiles -R %{name} restore || :
test -d %{_localstatedir}/lib/sepgsql && /sbin/restorecon -R %{_localstatedir}/lib/sepgsql || :
@ -205,12 +212,19 @@ fi
%{_datadir}/sepgsql/conversion_create.sql
%{_datadir}/sepgsql/information_schema.sql
%{_datadir}/sepgsql/sql_features.txt
%attr(644,root,root) %{_datadir}/selinux/*/sepostgresql.pp
%attr(644,root,root) %{_datadir}/selinux/*/%{policy_module_name}.pp
%attr(700,sepgsql,sepgsql) %dir %{_localstatedir}/lib/sepgsql
%attr(700,sepgsql,sepgsql) %dir %{_localstatedir}/lib/sepgsql/data
%attr(700,sepgsql,sepgsql) %dir %{_localstatedir}/lib/sepgsql/backups
%changelog
* Fri Jul 11 2008 <kaigai@kaigai.gr.jp> - 8.3.3-2.944
- Add OpenSSL support
- backport 8.4devel fixes
* Sun Jun 15 2008 <kaigai@kaigai.gr.jp> - 8.3.3-2.889
- backport 8.4devel features.
* Fri Jun 13 2008 <kaigai@kaigai.gr.jp> - 8.3.3-2.869
- upgrade base PostgreSQL 8.3.1 -> 8.3.3