alter-strictness-security-v1.patch
text/plain
Filename: alter-strictness-security-v1.patch
Type: text/plain
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| doc/src/sgml/ref/alter_function.sgml | 0 | 0 |
diff --git a/doc/src/sgml/ref/alter_function.sgml b/doc/src/sgml/ref/alter_function.sgml
index 013b6f8..cfc2a69 100644
*** a/doc/src/sgml/ref/alter_function.sgml
--- b/doc/src/sgml/ref/alter_function.sgml
***************
*** 54,59 **** ALTER FUNCTION <replaceable>name</replaceable> ( [ [ <replaceable class="paramet
--- 54,61 ----
<para>
You must own the function to use <command>ALTER FUNCTION</>.
+ Marking a function <literal>CALLED ON NULL INPUT</> also requires
+ permission to use the function's language when creating new functions.
To change a function's schema, you must also have <literal>CREATE</>
privilege on the new schema.
To alter the owner, you must also be a direct or indirect member of the new
diff --git a/src/backend/commands/functioncindex 13e30f4..b40bcdf 100644
*** a/src/backend/commands/functioncmds.c
--- b/src/backend/commands/functioncmds.c
***************
*** 70,75 **** static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup,
--- 70,107 ----
/*
+ * May the current user create functions of a given language?
+ */
+ static void
+ check_language_usage(HeapTuple languageTuple)
+ {
+ Oid languageOid;
+ Form_pg_language languageStruct;
+
+ languageOid = HeapTupleGetOid(languageTuple);
+ languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
+
+ if (languageStruct->lanpltrusted)
+ {
+ /* if trusted language, need USAGE privilege */
+ AclResult aclresult;
+
+ aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
+ if (aclresult != ACLCHECK_OK)
+ aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
+ NameStr(languageStruct->lanname));
+ }
+ else
+ {
+ /* if untrusted language, must be superuser */
+ if (!superuser())
+ aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
+ NameStr(languageStruct->lanname));
+ }
+ }
+
+
+ /*
* Examine the RETURNS clause of the CREATE FUNCTION statement
* and return information about it as *prorettype_p and *returnsSet.
*
***************
*** 864,890 **** CreateFunction(CreateFunctionStmt *stmt, const char *queryString)
(PLTemplateExists(language) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
languageOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
-
- if (languageStruct->lanpltrusted)
- {
- /* if trusted language, need USAGE privilege */
- AclResult aclresult;
-
- aclresult = pg_language_aclcheck(languageOid, GetUserId(), ACL_USAGE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
- else
- {
- /* if untrusted language, must be superuser */
- if (!superuser())
- aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
-
languageValidator = languageStruct->lanvalidator;
ReleaseSysCache(languageTuple);
--- 896,905 ----
(PLTemplateExists(language) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
+ check_language_usage(languageTuple);
+
languageOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
languageValidator = languageStruct->lanvalidator;
ReleaseSysCache(languageTuple);
***************
*** 1312,1318 **** AlterFunction(AlterFunctionStmt *stmt)
--- 1327,1355 ----
if (volatility_item)
procForm->provolatile = interpret_func_volatility(volatility_item);
if (strict_item)
+ {
+ /*
+ * C-language functions that expect to be declared STRICT often omit
+ * NULL argument checks, crashing if they do receive a NULL. To
+ * protect such functions against less-privileged owners, clearing
+ * proisstrict requires the authority to define a new function of the
+ * same language.
+ */
+ if (!intVal(strict_item->arg))
+ {
+ HeapTuple langTuple;
+
+ langTuple = SearchSysCache1(LANGOID,
+ PointerGetDatum(procForm->prolang));
+ if (!HeapTupleIsValid(langTuple))
+ elog(ERROR, "cache lookup failed for language %u",
+ procForm->prolang);
+ check_language_usage(langTuple);
+ ReleaseSysCache(langTuple);
+ }
+
procForm->proisstrict = intVal(strict_item->arg);
+ }
if (security_def_item)
procForm->prosecdef = intVal(security_def_item->arg);
if (leakproof_item)
***************
*** 1974,2002 **** ExecuteDoStmt(DoStmt *stmt)
(PLTemplateExists(language) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
codeblock->langOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
codeblock->langIsTrusted = languageStruct->lanpltrusted;
- if (languageStruct->lanpltrusted)
- {
- /* if trusted language, need USAGE privilege */
- AclResult aclresult;
-
- aclresult = pg_language_aclcheck(codeblock->langOid, GetUserId(),
- ACL_USAGE);
- if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
- else
- {
- /* if untrusted language, must be superuser */
- if (!superuser())
- aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_LANGUAGE,
- NameStr(languageStruct->lanname));
- }
-
/* get the handler function's OID */
laninline = languageStruct->laninline;
if (!OidIsValid(laninline))
--- 2011,2022 ----
(PLTemplateExists(language) ?
errhint("Use CREATE LANGUAGE to load the language into the database.") : 0)));
+ check_language_usage(languageTuple);
+
codeblock->langOid = HeapTupleGetOid(languageTuple);
languageStruct = (Form_pg_language) GETSTRUCT(languageTuple);
codeblock->langIsTrusted = languageStruct->lanpltrusted;
/* get the handler function's OID */
laninline = languageStruct->laninline;
if (!OidIsValid(laninline))