Skip to content

Commit 9e9d0fd

Browse files
authored
Whitelist of used pg procs (#6765)
1 parent 1fbe7cd commit 9e9d0fd

File tree

12 files changed

+2004
-238
lines changed

12 files changed

+2004
-238
lines changed

ydb/library/yql/parser/pg_catalog/catalog.cpp

Lines changed: 99 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <util/string/cast.h>
88
#include <util/string/split.h>
99
#include <util/system/env.h>
10+
#include <util/system/mutex.h>
11+
#include <util/system/tempfile.h>
1012
#include <library/cpp/resource/resource.h>
1113

1214
namespace NYql::NPg {
@@ -1585,70 +1587,13 @@ const TColumnInfoRaw AllStaticColumnsRaw[] = {
15851587
#include "columns.generated.h"
15861588
};
15871589

1590+
const char* AllowedProcsRaw[] = {
1591+
#include "safe_procs.h"
1592+
#include "used_procs.h"
1593+
};
1594+
15881595
struct TCatalog {
1589-
TCatalog()
1590-
: ProhibitedProcs({
1591-
// revoked from public
1592-
"pg_start_backup",
1593-
"pg_stop_backup",
1594-
"pg_create_restore_point",
1595-
"pg_switch_wal",
1596-
"pg_wal_replay_pause",
1597-
"pg_wal_replay_resume",
1598-
"pg_rotate_logfile",
1599-
"pg_reload_conf",
1600-
"pg_current_logfile",
1601-
"pg_promote",
1602-
"pg_stat_reset",
1603-
"pg_stat_reset_shared",
1604-
"pg_stat_reset_slru",
1605-
"pg_stat_reset_single_table_counters",
1606-
"pg_stat_reset_single_function_counters",
1607-
"pg_stat_reset_replication_slot",
1608-
"lo_import",
1609-
"lo_export",
1610-
"pg_ls_logdir",
1611-
"pg_ls_waldir",
1612-
"pg_ls_archive_statusdir",
1613-
"pg_ls_tmpdir",
1614-
"pg_read_file",
1615-
"pg_read_binary_file",
1616-
"pg_replication_origin_advance",
1617-
"pg_replication_origin_create",
1618-
"pg_replication_origin_drop",
1619-
"pg_replication_origin_oid",
1620-
"pg_replication_origin_progress",
1621-
"pg_replication_origin_session_is_setup",
1622-
"pg_replication_origin_session_progress",
1623-
"pg_replication_origin_session_reset",
1624-
"pg_replication_origin_session_setup",
1625-
"pg_replication_origin_xact_reset",
1626-
"pg_replication_origin_xact_setup",
1627-
"pg_show_replication_origin_status",
1628-
"pg_stat_file",
1629-
"pg_ls_dir",
1630-
// transactions
1631-
"pg_last_committed_xact",
1632-
"pg_current_wal_lsn",
1633-
// large_objects
1634-
"lo_creat",
1635-
"lo_create",
1636-
"lo_import",
1637-
"lo_import_with_oid",
1638-
"lo_export",
1639-
"lo_open",
1640-
"lo_write",
1641-
"lo_read",
1642-
"lo_lseek",
1643-
"lo_lseek64",
1644-
"lo_tell",
1645-
"lo_tell64",
1646-
"lo_truncate",
1647-
"lo_truncate64",
1648-
"lo_close",
1649-
"lo_unlink"
1650-
})
1651-
{
1596+
TCatalog() {
16521597
for (size_t i = 0; i < Y_ARRAY_SIZE(AllStaticTablesRaw); ++i) {
16531598
const auto& raw = AllStaticTablesRaw[i];
16541599
AllStaticTables.push_back(
@@ -1918,6 +1863,73 @@ struct TCatalog {
19181863

19191864
Conversions = ParseConversions(conversionData, ProcByName);
19201865
Languages = ParseLanguages(languagesData);
1866+
1867+
if (auto exportDir = GetEnv("YQL_EXPORT_PG_FUNCTIONS_DIR")) {
1868+
ExportFile.ConstructInPlace(MakeTempName(exportDir.c_str(), "procs"), CreateAlways | RdWr);
1869+
for (const auto& a : Aggregations) {
1870+
const auto& desc = a.second;
1871+
ExportFunction(desc.TransFuncId);
1872+
ExportFunction(desc.FinalFuncId);
1873+
ExportFunction(desc.CombineFuncId);
1874+
ExportFunction(desc.SerializeFuncId);
1875+
ExportFunction(desc.DeserializeFuncId);
1876+
}
1877+
1878+
for (const auto& t : Types) {
1879+
const auto& desc = t.second;
1880+
ExportFunction(desc.InFuncId);
1881+
ExportFunction(desc.OutFuncId);
1882+
ExportFunction(desc.SendFuncId);
1883+
ExportFunction(desc.ReceiveFuncId);
1884+
ExportFunction(desc.TypeModInFuncId);
1885+
ExportFunction(desc.TypeModOutFuncId);
1886+
ExportFunction(desc.TypeSubscriptFuncId);
1887+
ExportFunction(desc.LessProcId);
1888+
ExportFunction(desc.EqualProcId);
1889+
ExportFunction(desc.CompareProcId);
1890+
ExportFunction(desc.HashProcId);
1891+
}
1892+
1893+
for (const auto& o : Operators) {
1894+
const auto& desc = o.second;
1895+
ExportFunction(desc.ProcId);
1896+
}
1897+
1898+
for (const auto& c : Casts) {
1899+
const auto& desc = c.second;
1900+
ExportFunction(desc.FunctionId);
1901+
}
1902+
} else {
1903+
for (size_t i = 0; i < Y_ARRAY_SIZE(AllowedProcsRaw); ++i) {
1904+
const auto& raw = AllowedProcsRaw[i];
1905+
AllowedProcs.insert(raw);
1906+
}
1907+
1908+
for (const auto& t : Types) {
1909+
AllowedProcs.insert(t.second.Name);
1910+
}
1911+
}
1912+
}
1913+
1914+
void ExportFunction(ui32 procOid) const {
1915+
if (!procOid || !ExportFile) {
1916+
return;
1917+
}
1918+
1919+
auto procPtr = Procs.FindPtr(procOid);
1920+
Y_ENSURE(procPtr);
1921+
ExportFunction(procPtr->Name);
1922+
}
1923+
1924+
void ExportFunction(const TString& name) const {
1925+
if (!ExportFile) {
1926+
return;
1927+
}
1928+
1929+
TString line = TStringBuilder() << "\"" << name << "\",\n";
1930+
with_lock(ExportGuard) {
1931+
ExportFile->Write(line.Data(), line.Size());
1932+
}
19211933
}
19221934

19231935
static const TCatalog& Instance() {
@@ -1941,12 +1953,16 @@ struct TCatalog {
19411953
THashMap<std::pair<ui32, ui32>, ui32> CastsByDir;
19421954
THashMap<TString, TVector<ui32>> OperatorsByName;
19431955
THashMap<TString, TVector<ui32>> AggregationsByName;
1944-
THashSet<TString> ProhibitedProcs;
19451956

19461957
TVector<TTableInfo> AllStaticTables;
19471958
TVector<TColumnInfo> AllStaticColumns;
19481959
THashMap<TTableInfoKey, TTableInfo> StaticTables;
19491960
THashMap<TTableInfoKey, TVector<TColumnInfo>> StaticColumns;
1961+
1962+
mutable TMaybe<TFile> ExportFile;
1963+
TMutex ExportGuard;
1964+
1965+
THashSet<TString> AllowedProcs;
19501966
};
19511967

19521968
bool ValidateProcArgs(const TProcDesc& d, const TVector<ui32>& argTypeIds) {
@@ -1961,21 +1977,22 @@ const TProcDesc& LookupProc(ui32 procId, const TVector<ui32>& argTypeIds) {
19611977
throw yexception() << "No such proc: " << procId;
19621978
}
19631979

1980+
if (!catalog.ExportFile && !catalog.AllowedProcs.contains(procPtr->Name)) {
1981+
throw yexception() << "No access to proc: " << procPtr->Name;
1982+
}
1983+
19641984
if (!ValidateProcArgs(*procPtr, argTypeIds)) {
19651985
throw yexception() << "Unable to find an overload for proc with oid " << procId << " with given argument types: " <<
19661986
ArgTypesList(argTypeIds);
19671987
}
19681988

1989+
catalog.ExportFunction(procId);
19691990
return *procPtr;
19701991
}
19711992

19721993
const TProcDesc& LookupProc(const TString& name, const TVector<ui32>& argTypeIds) {
19731994
const auto& catalog = TCatalog::Instance();
19741995
auto lower = to_lower(name);
1975-
if (catalog.ProhibitedProcs.contains(lower)) {
1976-
throw yexception() << "No access to proc: " << name;
1977-
}
1978-
19791996
auto procIdPtr = catalog.ProcByName.FindPtr(lower);
19801997
if (!procIdPtr) {
19811998
throw yexception() << "No such proc: " << name;
@@ -1984,10 +2001,15 @@ const TProcDesc& LookupProc(const TString& name, const TVector<ui32>& argTypeIds
19842001
for (const auto& id : *procIdPtr) {
19852002
const auto& d = catalog.Procs.FindPtr(id);
19862003
Y_ENSURE(d);
2004+
if (!catalog.ExportFile && !catalog.AllowedProcs.contains(d->Name)) {
2005+
throw yexception() << "No access to proc: " << d->Name;
2006+
}
2007+
19872008
if (!ValidateProcArgs(*d, argTypeIds)) {
19882009
continue;
19892010
}
19902011

2012+
catalog.ExportFunction(d->Name);
19912013
return *d;
19922014
}
19932015

@@ -2002,6 +2024,11 @@ const TProcDesc& LookupProc(ui32 procId) {
20022024
throw yexception() << "No such proc: " << procId;
20032025
}
20042026

2027+
if (!catalog.ExportFile && !catalog.AllowedProcs.contains(procPtr->Name)) {
2028+
throw yexception() << "No access to proc: " << procPtr->Name;
2029+
}
2030+
2031+
catalog.ExportFunction(procId);
20052032
return *procPtr;
20062033
}
20072034

@@ -2611,10 +2638,6 @@ bool IsCoercible(ui32 fromTypeId, ui32 toTypeId, ECoercionCode coercionType) {
26112638
std::variant<const TProcDesc*, const TTypeDesc*> LookupProcWithCasts(const TString& name, const TVector<ui32>& argTypeIds) {
26122639
const auto& catalog = TCatalog::Instance();
26132640
auto lower = to_lower(name);
2614-
if (catalog.ProhibitedProcs.contains(lower)) {
2615-
throw yexception() << "No access to proc: " << name;
2616-
}
2617-
26182641
auto procIdPtr = catalog.ProcByName.FindPtr(lower);
26192642
if (!procIdPtr) {
26202643
throw yexception() << "No such proc: " << name;
@@ -2627,6 +2650,10 @@ std::variant<const TProcDesc*, const TTypeDesc*> LookupProcWithCasts(const TStri
26272650
const auto& d = catalog.Procs.FindPtr(id);
26282651
Y_ENSURE(d);
26292652

2653+
if (!catalog.ExportFile && !catalog.AllowedProcs.contains(d->Name)) {
2654+
throw yexception() << "No access to proc: " << d->Name;
2655+
}
2656+
26302657
if (NPrivate::IsExactMatch(d->ArgTypes, d->VariadicType, argTypeIds)) {
26312658
// At most one exact match is possible, so look no further
26322659
// https://www.postgresql.org/docs/14/typeconv-func.html, step 2
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/usr/bin/env bash
2+
set -eux
3+
rm -rf tmp
4+
mkdir -p tmp
5+
yag make --build=relwithdebinfo -tA -C ut -C ../pg_wrapper/ut -C ../pg_wrapper/test -C ../../sql/pg/ut --test-env=YQL_EXPORT_PG_FUNCTIONS_DIR=$(realpath ./tmp)
6+
cat tmp/* | sort | uniq > used_procs.h
7+
rm -rf tmp
8+

0 commit comments

Comments
 (0)