mirror of
https://github.com/postgres/postgres.git
synced 2025-06-07 11:02:12 +03:00
Require superuser privilege to create base types (but not composites, enums,
or domains). This was already effectively required because you had to own the I/O functions, and the I/O functions pretty much have to be written in C since we don't let PL functions take or return cstring. But given the possible security consequences of a malicious type definition, it seems prudent to enforce superuser requirement directly. Per recent discussion.
This commit is contained in:
parent
c8572986ad
commit
7bd7b2002b
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.76 2008/07/30 19:35:12 tgl Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/ref/create_type.sgml,v 1.77 2008/07/31 16:27:16 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -99,7 +99,13 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
|
|||||||
|
|
||||||
<para>
|
<para>
|
||||||
The third form of <command>CREATE TYPE</command> creates a new base type
|
The third form of <command>CREATE TYPE</command> creates a new base type
|
||||||
(scalar type). The parameters can appear in any order, not only that
|
(scalar type). To create a new base type, you must be a superuser.
|
||||||
|
(This restriction is made because an erroneous type definition could
|
||||||
|
confuse or even crash the server.)
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The parameters can appear in any order, not only that
|
||||||
illustrated above, and most are optional. You must register
|
illustrated above, and most are optional. You must register
|
||||||
two or more functions (using <command>CREATE FUNCTION</command>) before
|
two or more functions (using <command>CREATE FUNCTION</command>) before
|
||||||
defining the type. The support functions
|
defining the type. The support functions
|
||||||
@ -580,8 +586,8 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
|
|||||||
<para>
|
<para>
|
||||||
Because there are no restrictions on use of a data type once it's been
|
Because there are no restrictions on use of a data type once it's been
|
||||||
created, creating a base type is tantamount to granting public execute
|
created, creating a base type is tantamount to granting public execute
|
||||||
permission on the functions mentioned in the type definition. (The creator
|
permission on the functions mentioned in the type definition.
|
||||||
of the type is therefore required to own these functions.) This is usually
|
This is usually
|
||||||
not an issue for the sorts of functions that are useful in a type
|
not an issue for the sorts of functions that are useful in a type
|
||||||
definition. But you might want to think twice before designing a type
|
definition. But you might want to think twice before designing a type
|
||||||
in a way that would require <quote>secret</> information to be used
|
in a way that would require <quote>secret</> information to be used
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.121 2008/07/30 19:35:13 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/commands/typecmds.c,v 1.122 2008/07/31 16:27:16 tgl Exp $
|
||||||
*
|
*
|
||||||
* DESCRIPTION
|
* DESCRIPTION
|
||||||
* The "DefineFoo" routines take the parse tree and pick out the
|
* The "DefineFoo" routines take the parse tree and pick out the
|
||||||
@ -92,14 +92,13 @@ static char *domainAddConstraint(Oid domainOid, Oid domainNamespace,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* DefineType
|
* DefineType
|
||||||
* Registers a new type.
|
* Registers a new base type.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
DefineType(List *names, List *parameters)
|
DefineType(List *names, List *parameters)
|
||||||
{
|
{
|
||||||
char *typeName;
|
char *typeName;
|
||||||
Oid typeNamespace;
|
Oid typeNamespace;
|
||||||
AclResult aclresult;
|
|
||||||
int16 internalLength = -1; /* default: variable-length */
|
int16 internalLength = -1; /* default: variable-length */
|
||||||
Oid elemType = InvalidOid;
|
Oid elemType = InvalidOid;
|
||||||
List *inputName = NIL;
|
List *inputName = NIL;
|
||||||
@ -130,14 +129,33 @@ DefineType(List *names, List *parameters)
|
|||||||
Oid resulttype;
|
Oid resulttype;
|
||||||
Relation pg_type;
|
Relation pg_type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As of Postgres 8.4, we require superuser privilege to create a base
|
||||||
|
* type. This is simple paranoia: there are too many ways to mess up the
|
||||||
|
* system with an incorrect type definition (for instance, representation
|
||||||
|
* parameters that don't match what the C code expects). In practice
|
||||||
|
* it takes superuser privilege to create the I/O functions, and so the
|
||||||
|
* former requirement that you own the I/O functions pretty much forced
|
||||||
|
* superuserness anyway. We're just making doubly sure here.
|
||||||
|
*
|
||||||
|
* XXX re-enable NOT_USED code sections below if you remove this test.
|
||||||
|
*/
|
||||||
|
if (!superuser())
|
||||||
|
ereport(ERROR,
|
||||||
|
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
|
||||||
|
errmsg("must be superuser to create a base type")));
|
||||||
|
|
||||||
/* Convert list of names to a name and namespace */
|
/* Convert list of names to a name and namespace */
|
||||||
typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
|
typeNamespace = QualifiedNameGetCreationNamespace(names, &typeName);
|
||||||
|
|
||||||
|
#ifdef NOT_USED
|
||||||
|
/* XXX this is unnecessary given the superuser check above */
|
||||||
/* Check we have creation rights in target namespace */
|
/* Check we have creation rights in target namespace */
|
||||||
aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
|
aclresult = pg_namespace_aclcheck(typeNamespace, GetUserId(), ACL_CREATE);
|
||||||
if (aclresult != ACLCHECK_OK)
|
if (aclresult != ACLCHECK_OK)
|
||||||
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
|
||||||
get_namespace_name(typeNamespace));
|
get_namespace_name(typeNamespace));
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look to see if type already exists (presumably as a shell; if not,
|
* Look to see if type already exists (presumably as a shell; if not,
|
||||||
@ -398,6 +416,8 @@ DefineType(List *names, List *parameters)
|
|||||||
* don't have a way to make the type go away if the grant option is
|
* don't have a way to make the type go away if the grant option is
|
||||||
* revoked, so ownership seems better.
|
* revoked, so ownership seems better.
|
||||||
*/
|
*/
|
||||||
|
#ifdef NOT_USED
|
||||||
|
/* XXX this is unnecessary given the superuser check above */
|
||||||
if (inputOid && !pg_proc_ownercheck(inputOid, GetUserId()))
|
if (inputOid && !pg_proc_ownercheck(inputOid, GetUserId()))
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
|
||||||
NameListToString(inputName));
|
NameListToString(inputName));
|
||||||
@ -419,6 +439,7 @@ DefineType(List *names, List *parameters)
|
|||||||
if (analyzeOid && !pg_proc_ownercheck(analyzeOid, GetUserId()))
|
if (analyzeOid && !pg_proc_ownercheck(analyzeOid, GetUserId()))
|
||||||
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
|
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
|
||||||
NameListToString(analyzeName));
|
NameListToString(analyzeName));
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Preassign array type OID so we can insert it in pg_type.typarray */
|
/* Preassign array type OID so we can insert it in pg_type.typarray */
|
||||||
pg_type = heap_open(TypeRelationId, AccessShareLock);
|
pg_type = heap_open(TypeRelationId, AccessShareLock);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user