*** a/doc/src/sgml/ref/initdb.sgml
--- b/doc/src/sgml/ref/initdb.sgml
***************
*** 152,157 **** PostgreSQL documentation
--- 152,170 ----
       </varlistentry>
  
       <varlistentry>
+       <term><option>-C</option></term>
+       <term><option>--shared-catalog-security</option></term>
+       <listitem>
+        <para>
+         This option enables the shared catalog tables security, by adding
+         row level security policies on all eligible shared catalog tables.
+         With this option, multi-tenancy in PostgreSQL is supported at 
+         database level.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
        <term><option>-D <replaceable class="parameter">directory</replaceable></option></term>
        <term><option>--pgdata=<replaceable class="parameter">directory</replaceable></option></term>
        <listitem>
*** a/src/backend/commands/tablecmds.c
--- b/src/backend/commands/tablecmds.c
***************
*** 3436,3441 **** ATRewriteCatalogs(List **wqueue, LOCKMODE lockmode)
--- 3436,3450 ----
  	{
  		AlteredTableInfo *tab = (AlteredTableInfo *) lfirst(ltab);
  
+ 		/*
+ 		 * ALTER table on sytem catalog tables is possible only when user specifies
+ 		 * CATALOG SECURITY on system catalog tables. To avoid an error in the 
+ 		 * AlterTableCreateToastTable function for system catalog tables, the system
+ 		 * catalog tables are ignored for the toast table creation.
+ 		 */
+ 		if (!IsUnderPostmaster && IsSharedRelation(tab->relid))
+ 			continue;
+ 
  		if (tab->relkind == RELKIND_RELATION ||
  			tab->relkind == RELKIND_MATVIEW)
  			AlterTableCreateToastTable(tab->relid, (Datum) 0, lockmode);
*** a/src/backend/utils/misc/rls.c
--- b/src/backend/utils/misc/rls.c
***************
*** 58,67 **** check_enable_rls(Oid relid, Oid checkAsUser, bool noError)
  	bool		relforcerowsecurity;
  	Oid			user_id = checkAsUser ? checkAsUser : GetUserId();
  
- 	/* Nothing to do for built-in relations */
- 	if (relid < FirstNormalObjectId)
- 		return RLS_NONE;
- 
  	tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
  	if (!HeapTupleIsValid(tuple))
  		return RLS_NONE;
--- 58,63 ----
*** a/src/bin/initdb/initdb.c
--- b/src/bin/initdb/initdb.c
***************
*** 132,137 **** static bool do_sync = true;
--- 132,138 ----
  static bool sync_only = false;
  static bool show_setting = false;
  static bool data_checksums = false;
+ static bool shared_catalog_security = false;
  static char *xlog_dir = "";
  
  
***************
*** 186,191 **** static char *authwarning = NULL;
--- 187,193 ----
   */
  static const char *boot_options = "-F";
  static const char *backend_options = "--single -F -O -c search_path=pg_catalog -c exit_on_error=true";
+ static const char *catalog_security_options = "--single -F -O -c search_path=pg_catalog -c exit_on_error=true -c allow_system_table_mods=true";
  
  static const char *subdirs[] = {
  	"global",
***************
*** 255,260 **** static void setup_dictionary(void);
--- 257,263 ----
  static void setup_privileges(void);
  static void set_info_version(void);
  static void setup_schema(void);
+ static void setup_shared_catalog_security(void);
  static void load_plpgsql(void);
  static void vacuum_db(void);
  static void make_template0(void);
***************
*** 2252,2257 **** setup_schema(void)
--- 2255,2356 ----
  }
  
  /*
+  * setup shared catalog security by defining policies
+  */
+ static void
+ setup_shared_catalog_security(void)
+ {
+ 	PG_CMD_DECL;
+ 	const char	  **line;
+ 	static const char *pg_shared_catalog_security_setup[] = {
+ 		/* AuthMemRelationId */
+ 		"create policy pg_auth_members_read_own_data on pg_auth_members for select using"
+ 		" (pg_has_role(roleid, 'any') AND pg_has_role(member, 'any'));\n",
+ 
+ 		"alter table pg_auth_members enable row level security;\n",
+ 
+ 		/* AuthIdRelationId */
+ 		"create policy pg_authid_read_own_data on pg_authid for select using"
+ 		" (pg_has_role(oid, 'any'));\n",
+ 
+ 		"alter table pg_authid enable row level security;\n",
+ 
+ 		/* DatabaseRelationId */
+ 		"create policy pg_database_read_own_data on pg_database for select using"
+ 		" ((oid < 16384) OR has_database_privilege(oid,'any'));\n",
+ 
+ 		"alter table pg_database enable row level security;\n",
+ 
+ 		/* DbRoleSettingRelationId */
+ 		"create policy pg_db_role_setting_read_own_data on pg_db_role_setting for select using"
+ 		" (pg_has_role(setrole, 'any') AND has_database_privilege(setdatabase,'any'));\n",
+ 
+ 		"alter table pg_database enable row level security;\n",
+ 
+ 		/* PLTemplateRelationId */
+ 		/*
+ 		 * Currently there is no policy needed for this table, so
+ 		 * leave it as it is.
+ 		 */
+ 
+ 		/* ReplicationOriginRelationId */
+ 		/*
+ 		 * Currently there is no policy needed for this table, so
+ 		 * leave it as it is.
+ 		 */
+ 		 
+ 		/* SharedDependRelationId */
+ 		"create policy pg_shdepend_read_own_data on pg_shdepend for select using"
+ 		" ((classid = 1262 AND has_database_privilege(objid, 'any'))"
+ 		" OR (classid = 1260 AND pg_has_role(objid, 'any'))"
+ 		" OR (classid = 1213 AND has_tablespace_privilege(objid, 'any')));\n",
+ 
+ 		"alter table pg_shdepend enable row level security;\n",
+ 
+ 		/* SharedDescriptionRelationId */
+ 		"create policy pg_shdescription_read_own_data on pg_shdescription for select using"
+ 		" ((classoid = 1262 AND has_database_privilege(objoid, 'any'))"
+ 		" OR (classoid = 1260 AND pg_has_role(objoid, 'any'))"
+ 		" OR (classoid = 1213 AND has_tablespace_privilege(objoid, 'any')));\n",
+ 
+ 		"alter table pg_shdescription enable row level security;\n",
+ 
+ 		/* SharedSecLabelRelationId */
+ 		"create policy pg_shseclabel_read_own_data on pg_shseclabel for select using"
+ 		" ((classoid = 1262 AND has_database_privilege(objoid, 'any'))"
+ 		" OR (classoid = 1260 AND pg_has_role(objoid, 'any'))"
+ 		" OR (classoid = 1213 AND has_tablespace_privilege(objoid, 'any')));\n",
+ 
+ 		"alter table pg_shseclabel enable row level security;\n",
+ 
+ 		/* TableSpaceRelationId */
+ 		"create policy pg_tablespace_read_own_data on pg_tablespace for select using"
+ 		" ((oid < 16384) OR has_tablespace_privilege(oid, 'any'));\n",
+ 
+ 		"alter table pg_tablespace enable row level security;\n",
+ 
+ 		NULL
+ 	};
+ 
+ 	fputs(_("creating shared catalog security policy ... "), stdout);
+ 	fflush(stdout);
+ 
+ 	snprintf(cmd, sizeof(cmd),
+ 		"\"%s\" %s template1 >%s",
+ 		backend_exec, catalog_security_options,
+ 		DEVNULL);
+ 
+ 	PG_CMD_OPEN;
+ 
+ 	for (line = pg_shared_catalog_security_setup; *line != NULL; line++)
+ 		PG_CMD_PUTS(*line);
+ 
+ 	PG_CMD_CLOSE;
+ 
+ 	check_ok();
+ }
+ 
+ /*
   * load PL/pgsql server-side language
   */
  static void
***************
*** 2768,2773 **** usage(const char *progname)
--- 2867,2874 ----
  	printf(_("\nLess commonly used options:\n"));
  	printf(_("  -d, --debug               generate lots of debugging output\n"));
  	printf(_("  -k, --data-checksums      use data page checksums\n"));
+ 	printf(_("  -C, --shared-catalog-security\n"
+ 			"						      use shared catalog security\n"));
  	printf(_("  -L DIRECTORY              where to find the input files\n"));
  	printf(_("  -n, --noclean             do not clean up after errors\n"));
  	printf(_("  -N, --nosync              do not wait for changes to be written safely to disk\n"));
***************
*** 3365,3370 **** initialize_data_directory(void)
--- 3466,3474 ----
  
  	setup_schema();
  
+ 	if (shared_catalog_security)
+ 		setup_shared_catalog_security();
+ 	
  	load_plpgsql();
  
  	vacuum_db();
***************
*** 3405,3410 **** main(int argc, char *argv[])
--- 3509,3515 ----
  		{"sync-only", no_argument, NULL, 'S'},
  		{"xlogdir", required_argument, NULL, 'X'},
  		{"data-checksums", no_argument, NULL, 'k'},
+ 		{"shared-catalog-security", no_argument, NULL, 'C' },
  		{NULL, 0, NULL, 0}
  	};
  
***************
*** 3445,3451 **** main(int argc, char *argv[])
  
  	/* process command-line options */
  
! 	while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:", long_options, &option_index)) != -1)
  	{
  		switch (c)
  		{
--- 3550,3556 ----
  
  	/* process command-line options */
  
! 	while ((c = getopt_long(argc, argv, "dD:E:kCL:nNU:WA:sST:X:", long_options, &option_index)) != -1)
  	{
  		switch (c)
  		{
***************
*** 3497,3502 **** main(int argc, char *argv[])
--- 3602,3610 ----
  			case 'k':
  				data_checksums = true;
  				break;
+ 			case 'C':
+ 				shared_catalog_security = true;
+ 				break;
  			case 'L':
  				share_path = pg_strdup(optarg);
  				break;
