public inbox for [email protected]
help / color / mirror / Atom feedFrom: Nathan Bossart <[email protected]>
To: Andres Freund <[email protected]>
Cc: Heikki Linnakangas <[email protected]>
Cc: Mats Kindahl <[email protected]>
Cc: Tom Lane <[email protected]>
Cc: [email protected]
Subject: Re: glibc qsort() vulnerability
Date: Wed, 7 Feb 2024 20:45:58 -0600
Message-ID: <20240208024558.GB445153@nathanxps13> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
<20240206205305.GB3891538@nathanxps13>
<[email protected]>
<CA+14425TqyUZ3-O7zYsW6u85yY5diCz-p_TPQ2bZovn-N-fQ9A@mail.gmail.com>
<[email protected]>
<[email protected]>
<20240207222124.GA382832@nathanxps13>
<[email protected]>
<20240208015211.GA445153@nathanxps13>
<[email protected]>
On Wed, Feb 07, 2024 at 06:06:37PM -0800, Andres Freund wrote:
> Another branchless variant is (a > b) - (a < b). It seems to get a similar
> improvement as the overflow-checking version.
Well, that's certainly more elegant. I updated the patch to that approach
for now.
--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com
Attachments:
[text/x-diff] v3-0001-remove-direct-calls-to-pg_qsort.patch (3.6K, ../20240208024558.GB445153@nathanxps13/2-v3-0001-remove-direct-calls-to-pg_qsort.patch)
download | inline diff:
From 8668a0dd83ecbdd356c76416b8398138407ef829 Mon Sep 17 00:00:00 2001
From: Nathan Bossart <[email protected]>
Date: Wed, 7 Feb 2024 14:29:04 -0600
Subject: [PATCH v3 1/2] remove direct calls to pg_qsort()
---
contrib/pg_prewarm/autoprewarm.c | 4 ++--
src/backend/access/brin/brin_minmax_multi.c | 2 +-
src/backend/storage/buffer/bufmgr.c | 4 ++--
src/backend/utils/cache/syscache.c | 10 +++++-----
4 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index 06ee21d496..248b9914a3 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -346,8 +346,8 @@ apw_load_buffers(void)
FreeFile(file);
/* Sort the blocks to be loaded. */
- pg_qsort(blkinfo, num_elements, sizeof(BlockInfoRecord),
- apw_compare_blockinfo);
+ qsort(blkinfo, num_elements, sizeof(BlockInfoRecord),
+ apw_compare_blockinfo);
/* Populate shared memory state. */
apw_state->block_info_handle = dsm_segment_handle(seg);
diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c
index 3ffaad3e42..2c29aa3d4e 100644
--- a/src/backend/access/brin/brin_minmax_multi.c
+++ b/src/backend/access/brin/brin_minmax_multi.c
@@ -1369,7 +1369,7 @@ build_distances(FmgrInfo *distanceFn, Oid colloid,
* Sort the distances in descending order, so that the longest gaps are at
* the front.
*/
- pg_qsort(distances, ndistances, sizeof(DistanceValue), compare_distances);
+ qsort(distances, ndistances, sizeof(DistanceValue), compare_distances);
return distances;
}
diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c
index eb1ec3b86d..07575ef312 100644
--- a/src/backend/storage/buffer/bufmgr.c
+++ b/src/backend/storage/buffer/bufmgr.c
@@ -3915,7 +3915,7 @@ DropRelationsAllBuffers(SMgrRelation *smgr_reln, int nlocators)
/* sort the list of rlocators if necessary */
if (use_bsearch)
- pg_qsort(locators, n, sizeof(RelFileLocator), rlocator_comparator);
+ qsort(locators, n, sizeof(RelFileLocator), rlocator_comparator);
for (i = 0; i < NBuffers; i++)
{
@@ -4269,7 +4269,7 @@ FlushRelationsAllBuffers(SMgrRelation *smgrs, int nrels)
/* sort the list of SMgrRelations if necessary */
if (use_bsearch)
- pg_qsort(srels, nrels, sizeof(SMgrSortArray), rlocator_comparator);
+ qsort(srels, nrels, sizeof(SMgrSortArray), rlocator_comparator);
for (i = 0; i < NBuffers; i++)
{
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index 162855b158..662f930864 100644
--- a/src/backend/utils/cache/syscache.c
+++ b/src/backend/utils/cache/syscache.c
@@ -146,14 +146,14 @@ InitCatalogCache(void)
Assert(SysCacheSupportingRelOidSize <= lengthof(SysCacheSupportingRelOid));
/* Sort and de-dup OID arrays, so we can use binary search. */
- pg_qsort(SysCacheRelationOid, SysCacheRelationOidSize,
- sizeof(Oid), oid_compare);
+ qsort(SysCacheRelationOid, SysCacheRelationOidSize,
+ sizeof(Oid), oid_compare);
SysCacheRelationOidSize =
qunique(SysCacheRelationOid, SysCacheRelationOidSize, sizeof(Oid),
oid_compare);
- pg_qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
- sizeof(Oid), oid_compare);
+ qsort(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
+ sizeof(Oid), oid_compare);
SysCacheSupportingRelOidSize =
qunique(SysCacheSupportingRelOid, SysCacheSupportingRelOidSize,
sizeof(Oid), oid_compare);
@@ -668,7 +668,7 @@ RelationSupportsSysCache(Oid relid)
/*
- * OID comparator for pg_qsort
+ * OID comparator for qsort
*/
static int
oid_compare(const void *a, const void *b)
--
2.25.1
[text/x-diff] v3-0002-Ensure-comparison-functions-are-transitive.patch (3.0K, ../20240208024558.GB445153@nathanxps13/3-v3-0002-Ensure-comparison-functions-are-transitive.patch)
download | inline diff:
From a74708f14d6e862b836b2d5106491a8db3114433 Mon Sep 17 00:00:00 2001
From: Mats Kindahl <[email protected]>
Date: Tue, 6 Feb 2024 14:53:53 +0100
Subject: [PATCH v3 2/2] Ensure comparison functions are transitive
There are a few comparison functions to qsort() that are non-transitive
because they can cause an overflow. Fix these functions to instead use
normal comparisons and return -1, 0, or 1 explicitly.
---
src/backend/access/spgist/spgtextproc.c | 2 +-
src/backend/utils/cache/relcache.c | 9 ++++++---
src/bin/pg_upgrade/function.c | 10 ++++++----
src/bin/psql/crosstabview.c | 5 ++++-
4 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c
index b8fd0c2ad8..e561bde63e 100644
--- a/src/backend/access/spgist/spgtextproc.c
+++ b/src/backend/access/spgist/spgtextproc.c
@@ -325,7 +325,7 @@ cmpNodePtr(const void *a, const void *b)
const spgNodePtr *aa = (const spgNodePtr *) a;
const spgNodePtr *bb = (const spgNodePtr *) b;
- return aa->c - bb->c;
+ return (aa->c > bb->c) - (aa->c < bb->c);
}
Datum
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index ac106b40e3..54682a0e60 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -4517,10 +4517,13 @@ AttrDefaultFetch(Relation relation, int ndef)
static int
AttrDefaultCmp(const void *a, const void *b)
{
- const AttrDefault *ada = (const AttrDefault *) a;
- const AttrDefault *adb = (const AttrDefault *) b;
+ AttrNumber ana = ((const AttrDefault *) a)->adnum;
+ AttrNumber anb = ((const AttrDefault *) b)->adnum;
- return ada->adnum - adb->adnum;
+ /* ensure upcasting approach is transitive */
+ Assert(sizeof(AttrNumber) == 2);
+
+ return (int) ana - (int) anb;
}
/*
diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c
index af998f74d3..b421500bbb 100644
--- a/src/bin/pg_upgrade/function.c
+++ b/src/bin/pg_upgrade/function.c
@@ -32,14 +32,16 @@ library_name_compare(const void *p1, const void *p2)
int slen1 = strlen(str1);
int slen2 = strlen(str2);
int cmp = strcmp(str1, str2);
+ int p1db = ((const LibraryInfo *) p1)->dbnum;
+ int p2db = ((const LibraryInfo *) p2)->dbnum;
if (slen1 != slen2)
- return slen1 - slen2;
+ return (slen1 > slen2) - (slen1 < slen2);
+
if (cmp != 0)
return cmp;
- else
- return ((const LibraryInfo *) p1)->dbnum -
- ((const LibraryInfo *) p2)->dbnum;
+
+ return (p1db > p2db) - (p1db < p2db);
}
diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c
index c6116b7238..7660f0ed4b 100644
--- a/src/bin/psql/crosstabview.c
+++ b/src/bin/psql/crosstabview.c
@@ -709,5 +709,8 @@ pivotFieldCompare(const void *a, const void *b)
static int
rankCompare(const void *a, const void *b)
{
- return *((const int *) a) - *((const int *) b);
+ const int an = *(const int *) a;
+ const int bn = *(const int *) b;
+
+ return (an > bn) - (an < bn);
}
--
2.25.1
view thread (16+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Subject: Re: glibc qsort() vulnerability
In-Reply-To: <20240208024558.GB445153@nathanxps13>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox