Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rXoxn-00Cp8o-Kd for pgsql-hackers@arkaria.postgresql.org; Wed, 07 Feb 2024 20:56:12 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rXoxm-00DNZ0-JE for pgsql-hackers@arkaria.postgresql.org; Wed, 07 Feb 2024 20:56:10 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rXoxm-00DNYs-8Z for pgsql-hackers@lists.postgresql.org; Wed, 07 Feb 2024 20:56:10 +0000 Received: from mail-io1-xd2e.google.com ([2607:f8b0:4864:20::d2e]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rXoxh-0060j7-Ph for pgsql-hackers@lists.postgresql.org; Wed, 07 Feb 2024 20:56:09 +0000 Received: by mail-io1-xd2e.google.com with SMTP id ca18e2360f4ac-7c40863de70so4554739f.0 for ; Wed, 07 Feb 2024 12:56:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1707339363; x=1707944163; darn=lists.postgresql.org; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=LpDAvLNCZbldtxOYgE9/fdnYIAlXt7UEU7L74a1vZgE=; b=OkwXr5d/Pg40fjB4JhpSfrp/29spl8i/eFOURzSZNNqTfjzcqbJuTfi2Dpsnck75aQ Bw6uCZm12bV2yNvuEMMMyRNJ5o/IRR8USLwRhrxPXUbCx1Z2eZ+grm6IbN24NBuR48+k k44hY83+bBcxhyZkGpw3UCqmFUPN64T3K0x3W2u1n0Vm3a43/ywbKcXBEgHMmLO1044B JQ6TgNE5RFXZjsY4bgKydUAYC4KZSKgFF/f99wq5JE13bxTe1OrCKpy09jNw6vN+msis XwvVEIksGdshYlv+fxI7/g3n4oTQrykX8bAFC4OoswFmEaLOMLV+rzPgTeHeKbqkfeFt EHfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1707339363; x=1707944163; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=LpDAvLNCZbldtxOYgE9/fdnYIAlXt7UEU7L74a1vZgE=; b=CrE2DgSrlZ6MeXIKLtgv7cEk5Msw0dh9pePBU9l45taBt19QZOAnnv2FkRIOqvM1Wu 5QswqEx3TjlwqTSD1Tg7/kgyhbNnzheDqKeDe2L2rMoAALNNGHrPypN2k+aw6nPwP0ap 2X21APtMREMislV1Ym3pKVXnerH1fmFEaqn5zSbtfbXF+S9du28wHaG7nfJN6QOoahRj PtLBk+0jMALF8DnrLc83xkrEkOb6wGs72gFX+0hEEAyKsFR6+l4mZdxz18Urh7ISdf9v cAw9bMnSQa8A3MYfRYg+Nax32T09/SHw12h+GoSdSa84LyS/cJJAzbvzaM4+MUmIOWuA 25Iw== X-Forwarded-Encrypted: i=1; AJvYcCU9pGIZnV8X7zBenIuqOmNJqjxG6DB6bk7k2s5tGno4sK8Q5M99OMlTULCQSowpOSTi9jzgtKqz8FKPjv+8E9qOm0+mpoBlfLllMAQnbW+7E1Dw X-Gm-Message-State: AOJu0YxBFwnp9LZKqIKJaArmytppfTvChTe95KD2eF8e2pPdYsHhVuQH z3tW5AdWEOOoAp1x/v+waJfRaRb3LwPrKerZS1jtctMyWLW4kRy3Gmk17kEw X-Google-Smtp-Source: AGHT+IE4HdPYW+cSZPHzq+RezosBF2UhDBXXjLK0404Kv0yuTRVt3vWQNeELQx1Ptnd8rgeVXHgYug== X-Received: by 2002:a5d:994e:0:b0:7c0:d720:feeb with SMTP id v14-20020a5d994e000000b007c0d720feebmr7751845ios.10.1707339362808; Wed, 07 Feb 2024 12:56:02 -0800 (PST) X-Forwarded-Encrypted: i=1; AJvYcCX6X5sR2ohOQej8U8RdNPMhxkXDugnSzHeXhXrYy2Kng5eTzd+r1Pe4gnGRWPoD+KxpDS7VIupLDRmnMKi/DGUTxfAxXuxV25GYWMMypX/lzsA+uY8W5vWfVra2y+Xnlr4Him7CaQ== Received: from nathanxps13 (162-195-168-172.lightspeed.stlsmo.sbcglobal.net. [162.195.168.172]) by smtp.gmail.com with ESMTPSA id u27-20020a02cbdb000000b00471506af901sm458014jaq.157.2024.02.07.12.56.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 07 Feb 2024 12:56:02 -0800 (PST) Date: Wed, 7 Feb 2024 14:56:00 -0600 From: Nathan Bossart To: Heikki Linnakangas Cc: Mats Kindahl , Tom Lane , pgsql-hackers@lists.postgresql.org Subject: Re: glibc qsort() vulnerability Message-ID: <20240207205600.GA378707@nathanxps13> References: <508821.1707232276@sss.pgh.pa.us> <20240206205305.GB3891538@nathanxps13> <642084.1707252958@sss.pgh.pa.us> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="x+6KMIRAuhnl3hBn" Content-Disposition: inline In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --x+6KMIRAuhnl3hBn Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Wed, Feb 07, 2024 at 08:46:56PM +0200, Heikki Linnakangas wrote: > Doesn't hurt to fix the comparison functions, and +1 on using the same > pattern everywhere. I attached a new version of the patch with some small adjustments. I haven't looked through all in-tree qsort() comparators to see if any others need to be adjusted, but we should definitely do so as part of this thread. Mats, are you able to do this? > However, we use our qsort() with user-defined comparison functions, and we > cannot make any guarantees about what they might do. So we must ensure that > our qsort() doesn't overflow, no matter what the comparison function does. > > Looking at our ST_SORT(), it seems safe to me. Cool. -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --x+6KMIRAuhnl3hBn Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v2-0001-remove-direct-calls-to-pg_qsort.patch" From f5850579e92f201218c3025327b91d820eabd18e Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Wed, 7 Feb 2024 14:29:04 -0600 Subject: [PATCH v2 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 --x+6KMIRAuhnl3hBn Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v2-0002-Ensure-comparison-functions-are-transitive.patch" From f1a046c3c67266187f5861b27c2fad1daa25101c Mon Sep 17 00:00:00 2001 From: Mats Kindahl Date: Tue, 6 Feb 2024 14:53:53 +0100 Subject: [PATCH v2 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 | 6 +++++- src/backend/utils/cache/relcache.c | 12 ++++++++---- src/bin/pg_upgrade/function.c | 20 ++++++++++++++++---- src/bin/psql/crosstabview.c | 9 ++++++++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/backend/access/spgist/spgtextproc.c b/src/backend/access/spgist/spgtextproc.c index b8fd0c2ad8..d0a2b4e6e1 100644 --- a/src/backend/access/spgist/spgtextproc.c +++ b/src/backend/access/spgist/spgtextproc.c @@ -325,7 +325,11 @@ cmpNodePtr(const void *a, const void *b) const spgNodePtr *aa = (const spgNodePtr *) a; const spgNodePtr *bb = (const spgNodePtr *) b; - return aa->c - bb->c; + if (aa->c > bb->c) + return 1; + if (aa->c < bb->c) + return -1; + return 0; } Datum diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index ac106b40e3..dc5a100d82 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -4517,10 +4517,14 @@ 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; - - return ada->adnum - adb->adnum; + AttrNumber ana = ((const AttrDefault *) a)->adnum; + AttrNumber anb = ((const AttrDefault *) b)->adnum; + + if (ana > anb) + return 1; + if (ana < anb) + return -1; + return 0; } /* diff --git a/src/bin/pg_upgrade/function.c b/src/bin/pg_upgrade/function.c index af998f74d3..483ede2ce4 100644 --- a/src/bin/pg_upgrade/function.c +++ b/src/bin/pg_upgrade/function.c @@ -32,14 +32,26 @@ 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; + { + if (slen1 > slen2) + return 1; + if (slen1 < slen2) + return -1; + return 0; + } + if (cmp != 0) return cmp; - else - return ((const LibraryInfo *) p1)->dbnum - - ((const LibraryInfo *) p2)->dbnum; + + if (p1db > p2db) + return 1; + if (p1db < p2db) + return -1; + return 0; } diff --git a/src/bin/psql/crosstabview.c b/src/bin/psql/crosstabview.c index c6116b7238..de6168bd67 100644 --- a/src/bin/psql/crosstabview.c +++ b/src/bin/psql/crosstabview.c @@ -709,5 +709,12 @@ 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; + + if (an > bn) + return 1; + if (an < bn) + return -1; + return 0; } -- 2.25.1 --x+6KMIRAuhnl3hBn--