import rpm-4.14.3-18.el8

This commit is contained in:
CentOS Sources 2021-10-06 09:41:49 -04:00 committed by Stepan Oksanichenko
parent 4e08ed886d
commit c81cfcc033
7 changed files with 1466 additions and 92 deletions

View File

@ -1,89 +0,0 @@
From 13b0ebee7cdb1e4d200b3c40d0ec9440f198a1d4 Mon Sep 17 00:00:00 2001
Message-Id: <13b0ebee7cdb1e4d200b3c40d0ec9440f198a1d4.1554886141.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 10 Apr 2019 11:24:44 +0300
Subject: [PATCH] Monkey-patch .decode() method to our strings as a temporary
compat crutch
As a temporary crutch to support faster deployment of the sane
string behavior on python3, monkey-patch a decode method into all
strings we return. This seems to be enough to fix practically all
API users who have already adapted to the long-standing broken API
on Python 3. API users compatible with both Python 2 and 3 never needed
this anyway. Issue a warning with pointer to the relevant bug when the
fake decode() method is used to alert users to the issue.
This is certainly an evil thing to do and will be removed as soon as
the critical users have been fixed to work with the new, corrected
behavior.
---
python/rpm/__init__.py | 3 +++
python/rpmmodule.c | 1 +
python/rpmsystem-py.h | 22 ++++++++++++++++++++--
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/python/rpm/__init__.py b/python/rpm/__init__.py
index 54728bbd4..6d69eda7b 100644
--- a/python/rpm/__init__.py
+++ b/python/rpm/__init__.py
@@ -61,6 +61,9 @@ except ImportError:
# backwards compatibility + give the same class both ways
ts = TransactionSet
+def _fakedecode(self, encoding='utf-8', errors='strict'):
+ warnings.warn("decode() called on unicode string, see https://bugzilla.redhat.com/show_bug.cgi?id=1693751", UnicodeWarning, stacklevel=2)
+ return self
def headerLoad(*args, **kwds):
"""DEPRECATED! Use rpm.hdr() instead."""
diff --git a/python/rpmmodule.c b/python/rpmmodule.c
index 05032edc7..2a76cfbd0 100644
--- a/python/rpmmodule.c
+++ b/python/rpmmodule.c
@@ -28,6 +28,7 @@
*/
PyObject * pyrpmError;
+PyObject * fakedecode = NULL;
static PyObject * archScore(PyObject * self, PyObject * arg)
{
diff --git a/python/rpmsystem-py.h b/python/rpmsystem-py.h
index 25938464a..803da0fc1 100644
--- a/python/rpmsystem-py.h
+++ b/python/rpmsystem-py.h
@@ -19,12 +19,29 @@
#define PyInt_AsSsize_t PyLong_AsSsize_t
#endif
+PyObject * fakedecode;
+
static inline PyObject * utf8FromString(const char *s)
{
/* In Python 3, we return all strings as surrogate-escaped utf-8 */
#if PY_MAJOR_VERSION >= 3
- if (s != NULL)
- return PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
+ if (s != NULL) {
+ PyObject *o = PyUnicode_DecodeUTF8(s, strlen(s), "surrogateescape");
+ /* fish the fake decode function from python side if not done yet */
+ if (fakedecode == NULL) {
+ PyObject *n = PyUnicode_FromString("rpm");
+ PyObject *m = PyImport_Import(n);
+ PyObject *md = PyModule_GetDict(m);
+ fakedecode = PyDict_GetItemString(md, "_fakedecode");
+ Py_DECREF(m);
+ Py_DECREF(n);
+ }
+ if (fakedecode && o) {
+ /* monkey-patch it into the string object as "decode" */
+ PyDict_SetItemString(Py_TYPE(o)->tp_dict, "decode", fakedecode);
+ }
+ return o;
+ }
#else
if (s != NULL)
return PyBytes_FromString(s);
--
2.20.1

View File

@ -0,0 +1,798 @@
From 34790c335fe6e5e1099c9320d7b3134398104120 Mon Sep 17 00:00:00 2001
Message-Id: <34790c335fe6e5e1099c9320d7b3134398104120.1624429665.git.pmatilai@redhat.com>
From: Panu Matilainen <pmatilai@redhat.com>
Date: Wed, 23 Jun 2021 08:24:44 +0300
Subject: [PATCH] Add read-only support for sqlite
Based on latest upstream sqlite backend version, chainsaw write support
out and adjust for the infra differences (which there are more than a
few) and add an error message instead.
---
configure.ac | 23 ++
lib/Makefile.am | 6 +
lib/backend/dbi.c | 14 +
lib/backend/dbi.h | 5 +
lib/backend/sqlite.c | 659 +++++++++++++++++++++++++++++++++++++++++++
macros.in | 1 +
6 files changed, 708 insertions(+)
create mode 100644 lib/backend/sqlite.c
diff --git a/configure.ac b/configure.ac
index 3fcb3ff20..e04aced68 100644
--- a/configure.ac
+++ b/configure.ac
@@ -589,6 +589,29 @@ AS_IF([test "$enable_ndb" = yes],[
])
AM_CONDITIONAL([NDB], [test "$enable_ndb" = yes])
+# Check for SQLITE support
+AC_ARG_ENABLE([sqlite],
+ [AS_HELP_STRING([--enable-sqlite=@<:@yes/no/auto@:>@)],
+ [build with sqlite rpm database format support (default=yes)])],
+ [enable_sqlite="$enableval"],
+ [enable_sqlite=yes])
+
+AS_IF([test "x$enable_sqlite" != "xno"], [
+ PKG_CHECK_MODULES([SQLITE], [sqlite3 >= 3.22.0], [have_sqlite=yes], [have_sqlite=no])
+ AS_IF([test "$enable_sqlite" = "yes"], [
+ if test "$have_sqlite" = "no"; then
+ AC_MSG_ERROR([--enable-sqlite specified, but not available])
+ fi
+ ])
+])
+
+if test "x$have_sqlite" = "xyes"; then
+ AC_DEFINE([WITH_SQLITE], [1], [Define if SQLITE is available])
+ SQLITE_REQUIRES=sqlite
+ AC_SUBST(SQLITE_REQUIRES)
+fi
+AM_CONDITIONAL([SQLITE], [test "x$have_sqlite" = "xyes"])
+
#=================
# Check for LMDB support
AC_ARG_ENABLE([lmdb],
diff --git a/lib/Makefile.am b/lib/Makefile.am
index baf3238ee..8a9fe77bd 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -76,6 +76,12 @@ librpm_la_SOURCES += \
backend/ndb/rpmxdb.h
endif
+if SQLITE
+AM_CPPFLAGS += $(SQLITE_CFLAGS)
+librpm_la_LIBADD += $(SQLITE_LIBS)
+librpm_la_SOURCES += backend/sqlite.c
+endif
+
if LMDB
AM_CPPFLAGS += $(LMDB_CFLAGS)
librpm_la_LIBADD += $(LMDB_LIBS)
diff --git a/lib/backend/dbi.c b/lib/backend/dbi.c
index e99a5f2b2..dc3587f58 100644
--- a/lib/backend/dbi.c
+++ b/lib/backend/dbi.c
@@ -48,6 +48,11 @@ dbDetectBackend(rpmdb rdb)
if (!strcmp(db_backend, "ndb")) {
rdb->db_ops = &ndb_dbops;
} else
+#endif
+#ifdef WITH_SQLITE
+ if (!strcmp(db_backend, "sqlite")) {
+ rdb->db_ops = &sqlite_dbops;
+ } else
#endif
{
rdb->db_ops = &db3_dbops;
@@ -75,6 +80,15 @@ dbDetectBackend(rpmdb rdb)
free(path);
#endif
+#ifdef WITH_SQLITE
+ path = rstrscat(NULL, dbhome, "/rpmdb.sqlite", NULL);
+ if (access(path, F_OK) == 0 && rdb->db_ops != &sqlite_dbops) {
+ rdb->db_ops = &sqlite_dbops;
+ rpmlog(RPMLOG_WARNING, _("Found SQLITE rpmdb.sqlite database while attempting %s backend: using sqlite backend.\n"), db_backend);
+ }
+ free(path);
+#endif
+
path = rstrscat(NULL, dbhome, "/Packages", NULL);
if (access(path, F_OK) == 0 && rdb->db_ops != &db3_dbops) {
rdb->db_ops = &db3_dbops;
diff --git a/lib/backend/dbi.h b/lib/backend/dbi.h
index 02f49c8fd..ff2b4f974 100644
--- a/lib/backend/dbi.h
+++ b/lib/backend/dbi.h
@@ -275,6 +275,11 @@ RPM_GNUC_INTERNAL
extern struct rpmdbOps_s lmdb_dbops;
#endif
+#if defined(WITH_SQLITE)
+RPM_GNUC_INTERNAL
+extern struct rpmdbOps_s sqlite_dbops;
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c
new file mode 100644
index 000000000..3caeba5f0
--- /dev/null
+++ b/lib/backend/sqlite.c
@@ -0,0 +1,659 @@
+#include "system.h"
+
+#include <sqlite3.h>
+#include <fcntl.h>
+
+#include <rpm/rpmlog.h>
+#include <rpm/rpmfileutil.h>
+#include <rpm/rpmmacro.h>
+#include "lib/rpmdb_internal.h"
+
+#include "debug.h"
+
+static const int sleep_ms = 50;
+
+struct dbiCursor_s {
+ sqlite3 *sdb;
+ sqlite3_stmt *stmt;
+ const char *fmt;
+ int flags;
+ rpmTagVal tag;
+ int ctype;
+ struct dbiCursor_s *subc;
+
+ const void *key;
+ unsigned int keylen;
+};
+
+static int sqlexec(sqlite3 *sdb, const char *fmt, ...);
+
+static void rpm_match3(sqlite3_context *sctx, int argc, sqlite3_value **argv)
+{
+ int match = 0;
+ if (argc == 3) {
+ int b1len = sqlite3_value_bytes(argv[0]);
+ int b2len = sqlite3_value_bytes(argv[1]);
+ int n = sqlite3_value_int(argv[2]);
+ if (b1len >= n && b2len >= n) {
+ const char *b1 = sqlite3_value_blob(argv[0]);
+ const char *b2 = sqlite3_value_blob(argv[1]);
+ match = (memcmp(b1, b2, n) == 0);
+ }
+ }
+ sqlite3_result_int(sctx, match);
+}
+
+static void errCb(void *data, int err, const char *msg)
+{
+ rpmdb rdb = data;
+ rpmlog(RPMLOG_WARNING, "%s: %s: %s\n",
+ rdb->db_descr, sqlite3_errstr(err), msg);
+}
+
+static int dbiCursorReset(dbiCursor dbc)
+{
+ if (dbc->stmt) {
+ sqlite3_reset(dbc->stmt);
+ sqlite3_clear_bindings(dbc->stmt);
+ }
+ return 0;
+}
+
+static int dbiCursorResult(dbiCursor dbc)
+{
+ int rc = sqlite3_errcode(dbc->sdb);
+ int err = (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW);
+ if (err) {
+ rpmlog(RPMLOG_ERR, "%s: %d: %s\n", sqlite3_sql(dbc->stmt),
+ sqlite3_errcode(dbc->sdb), sqlite3_errmsg(dbc->sdb));
+ }
+ return err ? RPMRC_FAIL : RPMRC_OK;
+}
+
+static int dbiCursorPrep(dbiCursor dbc, const char *fmt, ...)
+{
+ if (dbc->stmt == NULL) {
+ char *cmd = NULL;
+ va_list ap;
+
+ va_start(ap, fmt);
+ cmd = sqlite3_vmprintf(fmt, ap);
+ va_end(ap);
+
+ sqlite3_prepare_v2(dbc->sdb, cmd, -1, &dbc->stmt, NULL);
+ sqlite3_free(cmd);
+ } else {
+ dbiCursorReset(dbc);
+ }
+
+ return dbiCursorResult(dbc);
+}
+
+static int dbiCursorBindPkg(dbiCursor dbc, unsigned int hnum,
+ void *blob, unsigned int bloblen)
+{
+ int rc = 0;
+
+ if (hnum)
+ rc = sqlite3_bind_int(dbc->stmt, 1, hnum);
+ else
+ rc = sqlite3_bind_null(dbc->stmt, 1);
+
+ if (blob) {
+ if (!rc)
+ rc = sqlite3_bind_blob(dbc->stmt, 2, blob, bloblen, NULL);
+ }
+ return dbiCursorResult(dbc);
+}
+
+static int dbiCursorBindIdx(dbiCursor dbc, const void *key, int keylen,
+ dbiIndexItem rec)
+{
+ int rc;
+ if (dbc->ctype == SQLITE_TEXT) {
+ rc = sqlite3_bind_text(dbc->stmt, 1, key, keylen, NULL);
+ } else {
+ rc = sqlite3_bind_blob(dbc->stmt, 1, key, keylen, NULL);
+ }
+
+ if (rec) {
+ if (!rc)
+ rc = sqlite3_bind_int(dbc->stmt, 2, rec->hdrNum);
+ if (!rc)
+ rc = sqlite3_bind_int(dbc->stmt, 3, rec->tagNum);
+ }
+
+ return dbiCursorResult(dbc);
+}
+
+static int sqlite_init(rpmdb rdb, const char * dbhome)
+{
+ int rc = 0;
+ char *dbfile = NULL;
+
+ if (rdb->db_dbenv == NULL) {
+ dbfile = rpmGenPath(dbhome, "rpmdb.sqlite", NULL);
+ sqlite3 *sdb = NULL;
+ int xx, flags = 0;
+ int retry_open = 1;
+
+ free(rdb->db_descr);
+ rdb->db_descr = xstrdup("sqlite");
+
+ if ((rdb->db_mode & O_ACCMODE) == O_RDONLY)
+ flags |= SQLITE_OPEN_READONLY;
+ else {
+ rpmlog(RPMLOG_ERR,
+ _("unable to open sqlite database %s for writing, sqlite support is read-only\n"), dbfile);
+ rc = RPMRC_FAIL;
+ goto exit;
+ }
+
+ while (retry_open--) {
+ xx = sqlite3_open_v2(dbfile, &sdb, flags, NULL);
+ /* Attempt to create if missing, discarding OPEN_READONLY (!) */
+ if (xx == SQLITE_CANTOPEN && (flags & SQLITE_OPEN_READONLY)) {
+ /* Sqlite allocates resources even on failure to open (!) */
+ sqlite3_close(sdb);
+ flags &= ~SQLITE_OPEN_READONLY;
+ flags |= (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
+ retry_open++;
+ }
+ }
+
+ if (xx != SQLITE_OK) {
+ rpmlog(RPMLOG_ERR, _("Unable to open sqlite database %s: %s\n"),
+ dbfile, sqlite3_errstr(xx));
+ rc = 1;
+ goto exit;
+ }
+
+ sqlite3_create_function(sdb, "match", 3,
+ (SQLITE_UTF8|SQLITE_DETERMINISTIC),
+ NULL, rpm_match3, NULL, NULL);
+
+ sqlite3_busy_timeout(sdb, sleep_ms);
+ sqlite3_config(SQLITE_CONFIG_LOG, errCb, rdb);
+
+ sqlexec(sdb, "PRAGMA secure_delete = OFF");
+ sqlexec(sdb, "PRAGMA case_sensitive_like = ON");
+
+ if (sqlite3_db_readonly(sdb, NULL) == 0) {
+ if (sqlexec(sdb, "PRAGMA journal_mode = WAL") == 0) {
+ int one = 1;
+ /* Annoying but necessary to support non-privileged readers */
+ sqlite3_file_control(sdb, NULL, SQLITE_FCNTL_PERSIST_WAL, &one);
+
+ if (!rpmExpandNumeric("%{?_flush_io}"))
+ sqlexec(sdb, "PRAGMA wal_autocheckpoint = 0");
+ }
+ }
+
+ rdb->db_dbenv = sdb;
+ }
+ rdb->db_opens++;
+
+exit:
+ free(dbfile);
+ return rc;
+}
+
+static int sqlite_fini(rpmdb rdb)
+{
+ int rc = 0;
+ if (rdb) {
+ sqlite3 *sdb = rdb->db_dbenv;
+ if (rdb->db_opens > 1) {
+ rdb->db_opens--;
+ } else {
+ if (sqlite3_db_readonly(sdb, NULL) == 0) {
+ sqlexec(sdb, "PRAGMA optimize");
+ sqlexec(sdb, "PRAGMA wal_checkpoint = TRUNCATE");
+ }
+ rdb->db_dbenv = NULL;
+ int xx = sqlite3_close(sdb);
+ rc = (xx != SQLITE_OK);
+ }
+ }
+
+ return rc;
+}
+
+static int sqlexec(sqlite3 *sdb, const char *fmt, ...)
+{
+ int rc = 0;
+ char *cmd = NULL;
+ char *err = NULL;
+ va_list ap;
+
+ va_start(ap, fmt);
+ cmd = sqlite3_vmprintf(fmt, ap);
+ va_end(ap);
+
+ /* sqlite3_exec() doesn't seeem to honor sqlite3_busy_timeout() */
+ while ((rc = sqlite3_exec(sdb, cmd, NULL, NULL, &err)) == SQLITE_BUSY) {
+ usleep(sleep_ms);
+ }
+
+ if (rc)
+ rpmlog(RPMLOG_ERR, "sqlite failure: %s: %s\n", cmd, err);
+ else
+ rpmlog(RPMLOG_DEBUG, "%s: %d\n", cmd, rc);
+
+ sqlite3_free(cmd);
+
+ return rc ? RPMRC_FAIL : RPMRC_OK;
+}
+
+static int dbiExists(dbiIndex dbi)
+{
+ const char *col = (dbi->dbi_type == DBI_PRIMARY) ? "hnum" : "key";
+ const char *tbl = dbi->dbi_file;
+ int rc = sqlite3_table_column_metadata(dbi->dbi_db, NULL, tbl, col,
+ NULL, NULL, NULL, NULL, NULL);
+ return (rc == 0);
+}
+
+static int init_table(dbiIndex dbi, rpmTagVal tag)
+{
+ int rc = 0;
+
+ if (dbiExists(dbi))
+ return 0;
+
+ if (dbi->dbi_type == DBI_PRIMARY) {
+ rc = sqlexec(dbi->dbi_db,
+ "CREATE TABLE IF NOT EXISTS '%q' ("
+ "hnum INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "blob BLOB NOT NULL"
+ ")",
+ dbi->dbi_file);
+ } else {
+ const char *keytype = (rpmTagGetClass(tag) == RPM_STRING_CLASS) ?
+ "TEXT" : "BLOB";
+ rc = sqlexec(dbi->dbi_db,
+ "CREATE TABLE IF NOT EXISTS '%q' ("
+ "key '%q' NOT NULL, "
+ "hnum INTEGER NOT NULL, "
+ "idx INTEGER NOT NULL, "
+ "FOREIGN KEY (hnum) REFERENCES 'Packages'(hnum)"
+ ")",
+ dbi->dbi_file, keytype);
+ }
+ if (!rc)
+ dbi->dbi_flags |= DBI_CREATED;
+
+ return rc;
+}
+
+static int create_index(sqlite3 *sdb, const char *table, const char *col)
+{
+ return sqlexec(sdb,
+ "CREATE INDEX IF NOT EXISTS '%s_%s_idx' ON '%q'(%s ASC)",
+ table, col, table, col);
+}
+
+static int init_index(dbiIndex dbi, rpmTagVal tag)
+{
+ int rc = 0;
+
+ /* Can't create on readonly database, but things will still work */
+ if (sqlite3_db_readonly(dbi->dbi_db, NULL) == 1)
+ return 0;
+
+ if (dbi->dbi_type == DBI_SECONDARY) {
+ int string = (rpmTagGetClass(tag) == RPM_STRING_CLASS);
+ int array = (rpmTagGetReturnType(tag) == RPM_ARRAY_RETURN_TYPE);
+ if (!rc && string)
+ rc = create_index(dbi->dbi_db, dbi->dbi_file, "key");
+ if (!rc && array)
+ rc = create_index(dbi->dbi_db, dbi->dbi_file, "hnum");
+ }
+ return rc;
+}
+
+static int sqlite_Open(rpmdb rdb, rpmDbiTagVal rpmtag, dbiIndex * dbip, int flags)
+{
+ int rc = sqlite_init(rdb, rpmdbHome(rdb));
+
+ if (!rc) {
+ dbiIndex dbi = dbiNew(rdb, rpmtag);
+ dbi->dbi_db = rdb->db_dbenv;
+
+ rc = init_table(dbi, rpmtag);
+
+ if (!rc && !(rdb->db_flags & RPMDB_FLAG_REBUILD))
+ rc = init_index(dbi, rpmtag);
+
+ if (!rc && dbip)
+ *dbip = dbi;
+ else
+ dbiFree(dbi);
+ }
+
+ return rc;
+}
+
+static int sqlite_Close(dbiIndex dbi, unsigned int flags)
+{
+ rpmdb rdb = dbi->dbi_rpmdb;
+ int rc = 0;
+ if (rdb->db_flags & RPMDB_FLAG_REBUILD)
+ rc = init_index(dbi, rpmTagGetValue(dbi->dbi_file));
+ sqlite_fini(dbi->dbi_rpmdb);
+ dbiFree(dbi);
+ return rc;
+}
+
+static int sqlite_Verify(dbiIndex dbi, unsigned int flags)
+{
+ int errors = -1;
+ int key_errors = -1;
+ sqlite3_stmt *s = NULL;
+ const char *cmd = "PRAGMA integrity_check";
+
+ if (dbi->dbi_type == DBI_SECONDARY)
+ return RPMRC_OK;
+
+ if (sqlite3_prepare_v2(dbi->dbi_db, cmd, -1, &s, NULL) == SQLITE_OK) {
+ errors = 0;
+ while (sqlite3_step(s) == SQLITE_ROW) {
+ const char *txt = (const char *)sqlite3_column_text(s, 0);
+ if (!rstreq(txt, "ok")) {
+ errors++;
+ rpmlog(RPMLOG_ERR, "verify: %s\n", txt);
+ }
+ }
+ sqlite3_finalize(s);
+ } else {
+ rpmlog(RPMLOG_ERR, "%s: %s\n", cmd, sqlite3_errmsg(dbi->dbi_db));
+ }
+
+ /* No point checking higher-level errors if low-level errors exist */
+ if (errors)
+ goto exit;
+
+ cmd = "PRAGMA foreign_key_check";
+ if (sqlite3_prepare_v2(dbi->dbi_db, cmd, -1, &s, NULL) == SQLITE_OK) {
+ key_errors = 0;
+ while (sqlite3_step(s) == SQLITE_ROW) {
+ key_errors++;
+ rpmlog(RPMLOG_ERR, "verify key: %s[%lld]\n",
+ sqlite3_column_text(s, 0),
+ sqlite3_column_int64(s, 1));
+ }
+ sqlite3_finalize(s);
+ } else {
+ rpmlog(RPMLOG_ERR, "%s: %s\n", cmd, sqlite3_errmsg(dbi->dbi_db));
+ }
+
+exit:
+
+ return (errors == 0 && key_errors == 0) ? RPMRC_OK : RPMRC_FAIL;
+}
+
+static void sqlite_SetFSync(rpmdb rdb, int enable)
+{
+ if (rdb->db_dbenv) {
+ sqlexec(rdb->db_dbenv,
+ "PRAGMA synchronous = %s", enable ? "FULL" : "OFF");
+ }
+}
+
+static int sqlite_Ctrl(rpmdb rdb, dbCtrlOp ctrl)
+{
+ int rc = 0;
+
+ switch (ctrl) {
+ case DB_CTRL_LOCK_RW:
+ rc = sqlexec(rdb->db_dbenv, "SAVEPOINT 'rwlock'");
+ break;
+ case DB_CTRL_UNLOCK_RW:
+ rc = sqlexec(rdb->db_dbenv, "RELEASE 'rwlock'");
+ break;
+ default:
+ break;
+ }
+
+ return rc;
+}
+
+static dbiCursor sqlite_CursorInit(dbiIndex dbi, unsigned int flags)
+{
+ dbiCursor dbc = xcalloc(1, sizeof(*dbc));
+ dbc->sdb = dbi->dbi_db;
+ dbc->flags = flags;
+ dbc->tag = rpmTagGetValue(dbi->dbi_file);
+ if (rpmTagGetClass(dbc->tag) == RPM_STRING_CLASS) {
+ dbc->ctype = SQLITE_TEXT;
+ } else {
+ dbc->ctype = SQLITE_BLOB;
+ }
+ if (dbc->flags & DBC_WRITE)
+ sqlexec(dbc->sdb, "SAVEPOINT '%s'", dbi->dbi_file);
+ return dbc;
+}
+
+static dbiCursor sqlite_CursorFree(dbiIndex dbi, dbiCursor dbc)
+{
+ if (dbc) {
+ sqlite3_finalize(dbc->stmt);
+ if (dbc->subc)
+ dbiCursorFree(dbi, dbc->subc);
+ if (dbc->flags & DBC_WRITE)
+ sqlexec(dbc->sdb, "RELEASE '%s'", dbi->dbi_file);
+ free(dbc);
+ }
+ return NULL;
+}
+
+static rpmRC sqlite_pkgdbNew(dbiIndex dbi, dbiCursor dbc, unsigned int *hdrNum)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_pkgdbPut(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char *hdrBlob, unsigned int hdrLen)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_pkgdbDel(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_stepPkg(dbiCursor dbc, unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc = sqlite3_step(dbc->stmt);
+
+ if (rc == SQLITE_ROW) {
+ if (hdrLen)
+ *hdrLen = sqlite3_column_bytes(dbc->stmt, 1);
+ if (hdrBlob)
+ *hdrBlob = (void *) sqlite3_column_blob(dbc->stmt, 1);
+ }
+ return rc;
+}
+
+static rpmRC sqlite_pkgdbByKey(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc = dbiCursorPrep(dbc, "SELECT hnum, blob FROM '%q' WHERE hnum=?",
+ dbi->dbi_file);
+
+ if (!rc)
+ rc = dbiCursorBindPkg(dbc, hdrNum, NULL, 0);
+
+ if (!rc)
+ rc = sqlite_stepPkg(dbc, hdrBlob, hdrLen);
+
+ return dbiCursorResult(dbc);
+}
+
+static rpmRC sqlite_pkgdbIter(dbiIndex dbi, dbiCursor dbc,
+ unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc = RPMRC_OK;
+ if (dbc->stmt == NULL) {
+ rc = dbiCursorPrep(dbc, "SELECT hnum, blob FROM '%q'", dbi->dbi_file);
+ }
+
+ if (!rc)
+ rc = sqlite_stepPkg(dbc, hdrBlob, hdrLen);
+
+ if (rc == SQLITE_DONE) {
+ rc = RPMRC_NOTFOUND;
+ } else {
+ rc = dbiCursorResult(dbc);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_pkgdbGet(dbiIndex dbi, dbiCursor dbc, unsigned int hdrNum, unsigned char **hdrBlob, unsigned int *hdrLen)
+{
+ int rc;
+
+ if (hdrNum) {
+ rc = sqlite_pkgdbByKey(dbi, dbc, hdrNum, hdrBlob, hdrLen);
+ } else {
+ rc = sqlite_pkgdbIter(dbi, dbc, hdrBlob, hdrLen);
+ }
+
+ return rc;
+}
+
+static unsigned int sqlite_pkgdbKey(dbiIndex dbi, dbiCursor dbc)
+{
+ return sqlite3_column_int(dbc->stmt, 0);
+}
+
+static rpmRC sqlite_idxdbByKey(dbiIndex dbi, dbiCursor dbc,
+ const char *keyp, size_t keylen, int searchType,
+ dbiIndexSet *set)
+{
+ int rc = RPMRC_NOTFOUND;
+
+ if (searchType == DBC_PREFIX_SEARCH) {
+ rc = dbiCursorPrep(dbc, "SELECT hnum, idx FROM '%q' "
+ "WHERE MATCH(key,'%q',%d) "
+ "ORDER BY key",
+ dbi->dbi_file, keyp, keylen);
+ } else {
+ rc = dbiCursorPrep(dbc, "SELECT hnum, idx FROM '%q' WHERE key=?",
+ dbi->dbi_file);
+ if (!rc)
+ rc = dbiCursorBindIdx(dbc, keyp, keylen, NULL);
+ }
+
+
+ if (!rc) {
+ while ((rc = sqlite3_step(dbc->stmt)) == SQLITE_ROW) {
+ unsigned int hnum = sqlite3_column_int(dbc->stmt, 0);
+ unsigned int tnum = sqlite3_column_int(dbc->stmt, 1);
+
+ if (*set == NULL)
+ *set = dbiIndexSetNew(5);
+ dbiIndexSetAppendOne(*set, hnum, tnum, 0);
+ }
+ }
+
+ if (rc == SQLITE_DONE) {
+ rc = (*set) ? RPMRC_OK : RPMRC_NOTFOUND;
+ } else {
+ rc = dbiCursorResult(dbc);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_idxdbIter(dbiIndex dbi, dbiCursor dbc, dbiIndexSet *set)
+{
+ int rc = RPMRC_OK;
+
+ if (dbc->stmt == NULL) {
+ rc = dbiCursorPrep(dbc, "SELECT DISTINCT key FROM '%q' ORDER BY key",
+ dbi->dbi_file);
+ if (set)
+ dbc->subc = dbiCursorInit(dbi, 0);
+ }
+
+ if (!rc)
+ rc = sqlite3_step(dbc->stmt);
+
+ if (rc == SQLITE_ROW) {
+ if (dbc->ctype == SQLITE_TEXT) {
+ dbc->key = sqlite3_column_text(dbc->stmt, 0);
+ } else {
+ dbc->key = sqlite3_column_blob(dbc->stmt, 0);
+ }
+ dbc->keylen = sqlite3_column_bytes(dbc->stmt, 0);
+ if (dbc->subc) {
+ rc = sqlite_idxdbByKey(dbi, dbc->subc, dbc->key, dbc->keylen,
+ DBC_NORMAL_SEARCH, set);
+ } else {
+ rc = RPMRC_OK;
+ }
+ } else if (rc == SQLITE_DONE) {
+ rc = RPMRC_NOTFOUND;
+ } else {
+ rc = dbiCursorResult(dbc);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_idxdbGet(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexSet *set, int searchType)
+{
+ int rc;
+ if (keyp) {
+ rc = sqlite_idxdbByKey(dbi, dbc, keyp, keylen, searchType, set);
+ } else {
+ rc = sqlite_idxdbIter(dbi, dbc, set);
+ }
+
+ return rc;
+}
+
+static rpmRC sqlite_idxdbPut(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexItem rec)
+{
+ return RPMRC_FAIL;
+}
+
+static rpmRC sqlite_idxdbDel(dbiIndex dbi, dbiCursor dbc, const char *keyp, size_t keylen, dbiIndexItem rec)
+{
+ return RPMRC_FAIL;
+}
+
+static const void * sqlite_idxdbKey(dbiIndex dbi, dbiCursor dbc, unsigned int *keylen)
+{
+ const void *key = NULL;
+ if (dbc) {
+ key = dbc->key;
+ if (key && keylen)
+ *keylen = dbc->keylen;
+ }
+ return key;
+}
+
+struct rpmdbOps_s sqlite_dbops = {
+ .open = sqlite_Open,
+ .close = sqlite_Close,
+ .verify = sqlite_Verify,
+ .setFSync = sqlite_SetFSync,
+ .ctrl = sqlite_Ctrl,
+
+ .cursorInit = sqlite_CursorInit,
+ .cursorFree = sqlite_CursorFree,
+
+ .pkgdbPut = sqlite_pkgdbPut,
+ .pkgdbDel = sqlite_pkgdbDel,
+ .pkgdbGet = sqlite_pkgdbGet,
+ .pkgdbKey = sqlite_pkgdbKey,
+ .pkgdbNew = sqlite_pkgdbNew,
+
+ .idxdbGet = sqlite_idxdbGet,
+ .idxdbPut = sqlite_idxdbPut,
+ .idxdbDel = sqlite_idxdbDel,
+ .idxdbKey = sqlite_idxdbKey
+};
+
diff --git a/macros.in b/macros.in
index a6069ee4d..9ad3d60ef 100644
--- a/macros.in
+++ b/macros.in
@@ -620,6 +620,7 @@ package or when debugging this package.\
# bdb Berkeley DB
# lmdb Lightning Memory-mapped Database
# ndb new data base format
+# sqlite Sqlite database (read-only in this version!)
#
%_db_backend bdb
--
2.31.1

View File

@ -0,0 +1,100 @@
commit 8f4b3c3cab8922a2022b9e47c71f1ecf906077ef
Author: Demi Marie Obenour <athena@invisiblethingslab.com>
Date: Mon Feb 8 16:05:01 2021 -0500
hdrblobInit() needs bounds checks too
Users can pass untrusted data to hdrblobInit() and it must be robust
against this.
diff --git a/lib/header.c b/lib/header.c
index ea39e679f..ebba9c2b0 100644
--- a/lib/header.c
+++ b/lib/header.c
@@ -11,6 +11,7 @@
#include "system.h"
#include <netdb.h>
#include <errno.h>
+#include <inttypes.h>
#include <rpm/rpmtypes.h>
#include <rpm/rpmstring.h>
#include "lib/header_internal.h"
@@ -1912,6 +1913,25 @@ hdrblob hdrblobFree(hdrblob blob)
return NULL;
}
+static rpmRC hdrblobVerifyLengths(rpmTagVal regionTag, uint32_t il, uint32_t dl,
+ char **emsg) {
+ uint32_t il_max = HEADER_TAGS_MAX;
+ uint32_t dl_max = HEADER_DATA_MAX;
+ if (regionTag == RPMTAG_HEADERSIGNATURES) {
+ il_max = 32;
+ dl_max = 64 * 1024 * 1024;
+ }
+ if (hdrchkRange(il_max, il)) {
+ rasprintf(emsg, _("hdr tags: BAD, no. of tags(%" PRIu32 ") out of range"), il);
+ return RPMRC_FAIL;
+ }
+ if (hdrchkRange(dl_max, dl)) {
+ rasprintf(emsg, _("hdr data: BAD, no. of bytes(%" PRIu32 ") out of range"), dl);
+ return RPMRC_FAIL;
+ }
+ return RPMRC_OK;
+}
+
rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrblob blob, char **emsg)
{
int32_t block[4];
@@ -1924,13 +1944,6 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
size_t nb;
rpmRC rc = RPMRC_FAIL; /* assume failure */
int xx;
- int32_t il_max = HEADER_TAGS_MAX;
- int32_t dl_max = HEADER_DATA_MAX;
-
- if (regionTag == RPMTAG_HEADERSIGNATURES) {
- il_max = 32;
- dl_max = 64 * 1024 * 1024;
- }
memset(block, 0, sizeof(block));
if ((xx = Freadall(fd, bs, blen)) != blen) {
@@ -1943,15 +1956,9 @@ rpmRC hdrblobRead(FD_t fd, int magic, int exact_size, rpmTagVal regionTag, hdrbl
goto exit;
}
il = ntohl(block[2]);
- if (hdrchkRange(il_max, il)) {
- rasprintf(emsg, _("hdr tags: BAD, no. of tags(%d) out of range"), il);
- goto exit;
- }
dl = ntohl(block[3]);
- if (hdrchkRange(dl_max, dl)) {
- rasprintf(emsg, _("hdr data: BAD, no. of bytes(%d) out of range"), dl);
+ if (hdrblobVerifyLengths(regionTag, il, dl, emsg))
goto exit;
- }
nb = (il * sizeof(struct entryInfo_s)) + dl;
uc = sizeof(il) + sizeof(dl) + nb;
@@ -1995,11 +2002,18 @@ rpmRC hdrblobInit(const void *uh, size_t uc,
struct hdrblob_s *blob, char **emsg)
{
rpmRC rc = RPMRC_FAIL;
-
memset(blob, 0, sizeof(*blob));
+ if (uc && uc < 8) {
+ rasprintf(emsg, _("hdr length: BAD"));
+ goto exit;
+ }
+
blob->ei = (int32_t *) uh; /* discards const */
- blob->il = ntohl(blob->ei[0]);
- blob->dl = ntohl(blob->ei[1]);
+ blob->il = ntohl((uint32_t)(blob->ei[0]));
+ blob->dl = ntohl((uint32_t)(blob->ei[1]));
+ if (hdrblobVerifyLengths(regionTag, blob->il, blob->dl, emsg) != RPMRC_OK)
+ goto exit;
+
blob->pe = (entryInfo) &(blob->ei[2]);
blob->pvlen = sizeof(blob->il) + sizeof(blob->dl) +
(blob->il * sizeof(*blob->pe)) + blob->dl;

View File

@ -0,0 +1,327 @@
commit c7d7c5acd0c14d0450016887cba1d86483086794
Author: Michal Domonkos <mdomonko@redhat.com>
Date: Mon Jun 21 10:05:10 2021 +0200
Add quoting to literal curly brackets
These curly brackets are already treated as literals by the shell, so
let's make that explicit for clarity, and silence a ShellCheck warning
at the same time.
More info: https://github.com/koalaman/shellcheck/wiki/SC1083
Found by ShellCheck.
diff -up rpm-4.16.1.3/scripts/check-rpaths-worker.orig rpm-4.16.1.3/scripts/check-rpaths-worker
--- rpm-4.16.1.3/scripts/check-rpaths-worker.orig 2021-06-29 15:34:31.671003589 +0200
+++ rpm-4.16.1.3/scripts/check-rpaths-worker 2021-06-29 15:34:51.993414093 +0200
@@ -120,13 +120,13 @@ for i; do
(/lib64/*|/usr/lib64/*|/usr/X11R6/lib64/*|/usr/local/lib64/*)
badness=0;;
- (\$ORIGIN|\${ORIGINX}|\$ORIGIN/*|\${ORIGINX}/*)
+ (\$ORIGIN|\$\{ORIGINX\}|\$ORIGIN/*|\$\{ORIGINX\}/*)
test $allow_ORIGIN -eq 0 && badness=8 || {
badness=0
new_allow_ORIGIN=1
}
;;
- (/*\$PLATFORM*|/*\${PLATFORM}*|/*\$LIB*|/*\${LIB}*)
+ (/*\$PLATFORM*|/*\$\{PLATFORM\}*|/*\$LIB*|/*\$\{LIB\}*)
badness=0;;
(/lib|/usr/lib|/usr/X11R6/lib)
From d8dc4fd37b1d90cd97de7fcf484d449ec132c9b3 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Wed, 9 Jun 2021 21:31:40 +0200
Subject: [PATCH 1/7] Fix memory leak in sqlexec()
Callers are supposed to free the error strings themselves:
https://www.sqlite.org/capi3ref.html#sqlite3_exec
Found by Coverity.
---
lib/backend/sqlite.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/backend/sqlite.c b/lib/backend/sqlite.c
index 7c2de45aa..dbefeb163 100644
--- a/lib/backend/sqlite.c
+++ b/lib/backend/sqlite.c
@@ -233,6 +233,7 @@ static int sqlexec(sqlite3 *sdb, const char *fmt, ...)
rpmlog(RPMLOG_DEBUG, "%s: %d\n", cmd, rc);
sqlite3_free(cmd);
+ sqlite3_free(err);
return rc ? RPMRC_FAIL : RPMRC_OK;
}
--
2.31.1
From 5baf73feb4951cc3b3f553a4b18d3b3599cbf87c Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 25 Jun 2021 11:21:46 +0200
Subject: [PATCH 2/7] Always free the arg list passed to rpmGlob()
Even though the actual implementation of rpmGlob() does not allocate the
passed arg list (av) if the return code (rc) is non-zero or arg count
(ac) is 0, it's the responsibility of the caller (rpmInstall() here) to
free that memory, so make sure we do that irrespectively of the above
conditions.
Found by Coverity.
---
lib/rpminstall.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/lib/rpminstall.c b/lib/rpminstall.c
index 724126e94..302ec0ba1 100644
--- a/lib/rpminstall.c
+++ b/lib/rpminstall.c
@@ -461,6 +461,7 @@ int rpmInstall(rpmts ts, struct rpmInstallArguments_s * ia, ARGV_t fileArgv)
rpmlog(RPMLOG_ERR, _("File not found by glob: %s\n"), *eiu->fnp);
}
eiu->numFailed++;
+ argvFree(av);
continue;
}
--
2.31.1
From 3c8b01b67ec907afaaffe71691fa41b878578527 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 14 Jun 2021 10:21:25 +0200
Subject: [PATCH 3/7] Fix resource leak in Fts_children()
This function is not used anywhere within our codebase (and neither is
it part of the public API) so it's basically a no-op... Still, rather
than yanking it completely, let's just silence the Coverity error here.
Found by Coverity.
---
misc/fts.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/misc/fts.c b/misc/fts.c
index d3ebb2946..caf27495d 100644
--- a/misc/fts.c
+++ b/misc/fts.c
@@ -585,8 +585,10 @@ Fts_children(FTS * sp, int instr)
if ((fd = __open(".", O_RDONLY, 0)) < 0)
return (NULL);
sp->fts_child = fts_build(sp, instr);
- if (__fchdir(fd))
+ if (__fchdir(fd)) {
+ (void)__close(fd);
return (NULL);
+ }
(void)__close(fd);
return (sp->fts_child);
}
--
2.31.1
From 39b7bf8579e0522cf16347b3a7e332d3b6d742c6 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 14 Jun 2021 12:34:23 +0200
Subject: [PATCH 4/7] Fix memory leak in fts_build()
Turns out this leak is already fixed in glibc's current version of fts.c
(where our copy originates from), so let's just backport that.
Original commit in glibc:
https://sourceware.org/git/?p=glibc.git;\
a=commit;h=db67c2c98b89a5723af44df54f38b779de8d4a65
Found by Coverity.
---
misc/fts.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/misc/fts.c b/misc/fts.c
index caf27495d..f7fce0eaa 100644
--- a/misc/fts.c
+++ b/misc/fts.c
@@ -855,6 +855,7 @@ mem1: saved_errno = errno;
fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
cur->fts_info = FTS_ERR;
SET(FTS_STOP);
+ fts_lfree(head);
return (NULL);
}
@@ -862,6 +863,7 @@ mem1: saved_errno = errno;
if (!nitems) {
if (type == BREAD)
cur->fts_info = FTS_DP;
+ fts_lfree(head);
return (NULL);
}
--
2.31.1
From 9c093c4f092dd6bd1e0c8d2b852a72b74db076c2 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Tue, 15 Jun 2021 13:34:21 +0200
Subject: [PATCH 5/7] Fix memory leak in decodePkts()
Found by Coverity.
---
rpmio/rpmpgp.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
index c59185dce..ee5c81e24 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -1371,9 +1371,13 @@ static pgpArmor decodePkts(uint8_t *b, uint8_t **pkt, size_t *pktlen)
crc = pgpCRC(dec, declen);
if (crcpkt != crc) {
ec = PGPARMOR_ERR_CRC_CHECK;
+ _free(dec);
goto exit;
}
- if (pkt) *pkt = dec;
+ if (pkt)
+ *pkt = dec;
+ else
+ _free(dec);
if (pktlen) *pktlen = declen;
ec = PGPARMOR_PUBKEY; /* XXX ASCII Pubkeys only, please. */
goto exit;
--
2.31.1
From 590b2fc06252567eb7d57197dc361a8b459d62a3 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Mon, 21 Jun 2021 17:51:14 +0200
Subject: [PATCH 6/7] Fix memory leak with multiple %lang-s in one line
We permit two equivalent forms of specifying a list of languages per
file:
%lang(xx,yy,zz) /path/to/file
%lang(xx) %lang(yy) %lang(zz) /path/to/file
The leak was when parsing the second form.
Found by Coverity.
---
build/files.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/build/files.c b/build/files.c
index f8153ad2b..0c8859f6c 100644
--- a/build/files.c
+++ b/build/files.c
@@ -777,6 +777,8 @@ static rpmRC parseForLang(char * buf, FileEntry cur)
if (*pe == ',') pe++; /* skip , if present */
}
+
+ q = _free(q);
}
rc = RPMRC_OK;
--
2.31.1
From b7a1e996326ee29a163d67ceb1e6127fdc251c14 Mon Sep 17 00:00:00 2001
From: Michal Domonkos <mdomonko@redhat.com>
Date: Fri, 25 Jun 2021 15:15:08 +0200
Subject: [PATCH 7/7] Fix memory leaks in Lua rex extension
This covers the following usage:
expr = rex.newPOSIX(<regex>)
expr:match(<string>) # A leak occurred here
expr:gmatch(<string>, <func>) # A leak occurred here
Found by Coverity.
---
luaext/lrexlib.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/luaext/lrexlib.c b/luaext/lrexlib.c
index 09c5a6454..0f29b6371 100644
--- a/luaext/lrexlib.c
+++ b/luaext/lrexlib.c
@@ -80,6 +80,7 @@ static void rex_push_matches(lua_State *L, const char *text, regmatch_t *match,
static int rex_match(lua_State *L)
{
+ int rc = 0;
int res;
#ifdef REG_BASIC
size_t len;
@@ -109,9 +110,10 @@ static int rex_match(lua_State *L)
lua_pushstring(L, "n");
lua_pushnumber(L, ncapt);
lua_rawset(L, -3);
- return 3;
- } else
- return 0;
+ rc = 3;
+ }
+ free(match);
+ return rc;
}
static int rex_gmatch(lua_State *L)
@@ -158,6 +160,7 @@ static int rex_gmatch(lua_State *L)
break;
}
lua_pushnumber(L, nmatch);
+ free(match);
return 1;
}
--
2.31.1
commit 9747a6af016a3458d54fe060777c95e3900b5fa4
Author: Demi Marie Obenour <athena@invisiblethingslab.com>
Date: Tue Mar 2 12:47:29 2021 -0500
Fix a tiny memory leak
Found by fuzzing rpmReadPackageFile() with libfuzzer under ASAN.
diff --git a/lib/headerutil.c b/lib/headerutil.c
index 22e36c74d..fab210ff2 100644
--- a/lib/headerutil.c
+++ b/lib/headerutil.c
@@ -333,8 +333,10 @@ static void providePackageNVR(Header h)
rpmds hds, nvrds;
/* Generate provides for this package name-version-release. */
- if (!(name && pEVR))
+ if (!(name && pEVR)) {
+ free(pEVR);
return;
+ }
/*
* Rpm prior to 3.0.3 does not have versioned provides.
commit cb2ae4bdf2f60876fdc68e3f84938e9c37182fab
Author: Igor Gnatenko <i.gnatenko.brain@gmail.com>
Date: Tue Feb 6 14:50:27 2018 +0100
lua: fix memory leak in Pexec()
Signed-off-by: Igor Gnatenko <i.gnatenko.brain@gmail.com>
diff --git a/luaext/lposix.c b/luaext/lposix.c
index 5d7ad3c87..2730bcff7 100644
--- a/luaext/lposix.c
+++ b/luaext/lposix.c
@@ -348,6 +348,7 @@ static int Pexec(lua_State *L) /** exec(path,[args]) */
for (i=1; i<n; i++) argv[i] = (char*)luaL_checkstring(L, i+1);
argv[i] = NULL;
execvp(path,argv);
+ free(argv);
return pusherror(L, path);
}

View File

@ -0,0 +1,162 @@
commit d6a86b5e69e46cc283b1e06c92343319beb42e21
Author: Panu Matilainen <pmatilai@redhat.com>
Date: Thu Mar 4 13:21:19 2021 +0200
Be much more careful about copying data from the signature header
Only look for known tags, and ensure correct type and size where known
before copying over. Bump the old arbitrary 16k count limit to 16M limit
though, it's not inconceivable that a package could have that many files.
While at it, ensure none of these tags exist in the main header,
which would confuse us greatly.
This is optimized for backporting ease, upstream can remove redundancies
and further improve checking later.
Reported and initial patches by Demi Marie Obenour.
Fixes: RhBug:1935049, RhBug:1933867, RhBug:1935035, RhBug:1934125, ...
Fixes: CVE-2021-3421, CVE-2021-20271
Combined with e2f1f1931c5ccf3ecbe4e1e12cacb1e17a277776 and backported into
4.14.3
diff -up rpm-4.14.3/lib/package.c.orig rpm-4.14.3/lib/package.c
--- rpm-4.14.3/lib/package.c.orig 2021-05-31 12:32:49.970393976 +0200
+++ rpm-4.14.3/lib/package.c 2021-05-31 13:53:58.250673275 +0200
@@ -31,76 +31,72 @@ struct pkgdata_s {
rpmRC rc;
};
+struct taglate_s {
+ rpmTagVal stag;
+ rpmTagVal xtag;
+ rpm_count_t count;
+ int quirk;
+} const xlateTags[] = {
+ { RPMSIGTAG_SIZE, RPMTAG_SIGSIZE, 1, 0 },
+ { RPMSIGTAG_PGP, RPMTAG_SIGPGP, 0, 0 },
+ { RPMSIGTAG_MD5, RPMTAG_SIGMD5, 16, 0 },
+ { RPMSIGTAG_GPG, RPMTAG_SIGGPG, 0, 0 },
+ /* { RPMSIGTAG_PGP5, RPMTAG_SIGPGP5, 0, 0 }, */ /* long obsolete, dont use */
+ { RPMSIGTAG_PAYLOADSIZE, RPMTAG_ARCHIVESIZE, 1, 1 },
+ { RPMSIGTAG_SHA1, RPMTAG_SHA1HEADER, 1, 0 },
+ { RPMSIGTAG_SHA256, RPMTAG_SHA256HEADER, 1, 0 },
+ { RPMSIGTAG_DSA, RPMTAG_DSAHEADER, 0, 0 },
+ { RPMSIGTAG_RSA, RPMTAG_RSAHEADER, 0, 0 },
+ { RPMSIGTAG_LONGSIZE, RPMTAG_LONGSIGSIZE, 1, 0 },
+ { RPMSIGTAG_LONGARCHIVESIZE, RPMTAG_LONGARCHIVESIZE, 1, 0 },
+ { 0 }
+};
+
/** \ingroup header
* Translate and merge legacy signature tags into header.
* @param h header (dest)
* @param sigh signature header (src)
+ * @return failing tag number, 0 on success
*/
static
-void headerMergeLegacySigs(Header h, Header sigh)
+rpmTagVal headerMergeLegacySigs(Header h, Header sigh, char **msg)
{
- HeaderIterator hi;
+ const struct taglate_s *xl;
struct rpmtd_s td;
- hi = headerInitIterator(sigh);
- for (; headerNext(hi, &td); rpmtdFreeData(&td))
- {
- switch (td.tag) {
- /* XXX Translate legacy signature tag values. */
- case RPMSIGTAG_SIZE:
- td.tag = RPMTAG_SIGSIZE;
- break;
- case RPMSIGTAG_PGP:
- td.tag = RPMTAG_SIGPGP;
- break;
- case RPMSIGTAG_MD5:
- td.tag = RPMTAG_SIGMD5;
- break;
- case RPMSIGTAG_GPG:
- td.tag = RPMTAG_SIGGPG;
- break;
- case RPMSIGTAG_PGP5:
- td.tag = RPMTAG_SIGPGP5;
- break;
- case RPMSIGTAG_PAYLOADSIZE:
- td.tag = RPMTAG_ARCHIVESIZE;
- break;
- case RPMSIGTAG_SHA1:
- case RPMSIGTAG_SHA256:
- case RPMSIGTAG_DSA:
- case RPMSIGTAG_RSA:
- default:
- if (!(td.tag >= HEADER_SIGBASE && td.tag < HEADER_TAGBASE))
+ rpmtdReset(&td);
+ for (xl = xlateTags; xl->stag; xl++) {
+ /* There mustn't be one in the main header */
+ if (headerIsEntry(h, xl->xtag)) {
+ /* Some tags may exist in either header, but never both */
+ if (xl->quirk && !headerIsEntry(sigh, xl->stag))
continue;
break;
}
- if (!headerIsEntry(h, td.tag)) {
- switch (td.type) {
- case RPM_NULL_TYPE:
- continue;
+ if (headerGet(sigh, xl->stag, &td, HEADERGET_RAW|HEADERGET_MINMEM)) {
+ /* Translate legacy tags */
+ if (xl->stag != xl->xtag)
+ td.tag = xl->xtag;
+ /* Ensure type and tag size match expectations */
+ if (td.type != rpmTagGetTagType(td.tag))
break;
- case RPM_CHAR_TYPE:
- case RPM_INT8_TYPE:
- case RPM_INT16_TYPE:
- case RPM_INT32_TYPE:
- case RPM_INT64_TYPE:
- if (td.count != 1)
- continue;
+ if (td.count < 1 || td.count > 16*1024*1024)
break;
- case RPM_STRING_TYPE:
- case RPM_BIN_TYPE:
- if (td.count >= 16*1024)
- continue;
+ if (xl->count && td.count != xl->count)
break;
- case RPM_STRING_ARRAY_TYPE:
- case RPM_I18NSTRING_TYPE:
- continue;
+ if (!headerPut(h, &td, HEADERPUT_DEFAULT))
break;
- }
- (void) headerPut(h, &td, HEADERPUT_DEFAULT);
+ rpmtdFreeData(&td);
}
}
- headerFreeIterator(hi);
+ rpmtdFreeData(&td);
+
+ if (xl->stag) {
+ rasprintf(msg, "invalid signature tag %s (%d)",
+ rpmTagGetName(xl->xtag), xl->xtag);
+ }
+
+ return xl->stag;
}
/**
@@ -363,7 +359,8 @@ rpmRC rpmReadPackageFile(rpmts ts, FD_t
goto exit;
/* Append (and remap) signature tags to the metadata. */
- headerMergeLegacySigs(h, sigh);
+ if (headerMergeLegacySigs(h, sigh, &msg))
+ goto exit;
applyRetrofits(h);
/* Bump reference count for return. */

View File

@ -0,0 +1,48 @@
commit cfdb8300f6e3aed0abc41406a3c4737eb1192067
Author: Michal Domonkos <mdomonko@redhat.com>
Date: Sun Jul 11 18:08:26 2021 +0200
Don't brp-strip .ko files
Otherwise SecureBoot signatures may be stripped too.
We used to exclude shared libraries from this strip as they were
supposed to be covered by another brp script (brp-strip-shared), however
it turned out the latter was never really used, so we removed the
exclusion in commit 0ab151ab138fd4fb6d3176fd0270d9cc6f4623f3.
As it turns out, that was a little too ambitious, since we may now
inadvertently strip SecureBoot signatures from kernel modules too,
provided that they're made during the build, prior to the invocation of
brp-strip.
Note that this regression currently does *not* affect the following two
cases on Fedora/RHEL systems with redhat-rpm-config installed:
- in-tree kernel modules; these are built from kernel.spec which
already contains a hack ensuring that module signing only happens
*after* any stripping (see %__modsign_install_post in kernel.spec)
- out-of-tree kernel modules built with debuginfo enabled; this is
because brp-strip is only called when %debug_package is set to
%{nil}
Any other combinations may be affected, depending on the macros and
.spec files used, so let's fix this by effectively "reverting" said
commit for .ko files only.
Fixes: rhbz#1967291
Backported into 4.14.3
diff -up rpm-4.14.3/scripts/brp-strip.orig rpm-4.14.3/scripts/brp-strip
--- rpm-4.14.3/scripts/brp-strip.orig 2021-07-12 17:21:04.446396789 +0200
+++ rpm-4.14.3/scripts/brp-strip 2021-07-12 17:21:20.673633783 +0200
@@ -12,7 +12,7 @@ Darwin*) exit 0 ;;
esac
# Strip ELF binaries
-for f in `find "$RPM_BUILD_ROOT" -type f -exec file {} \; | \
+for f in `find "$RPM_BUILD_ROOT" -type f \! -name "*.ko" -exec file {} \; | \
grep -v "^${RPM_BUILD_ROOT}/\?usr/lib/debug" | \
sed -n -e 's/^\(.*\):[ ]*ELF.*, not stripped.*/\1/p'`; do
$STRIP -g "$f" || :

View File

@ -18,6 +18,8 @@
%bcond_without zstd
# build with lmdb support?
%bcond_with lmdb
# build with readonly sqlite support?
%bcond_without sqlite
%if 0%{?rhel} > 7
# Disable python2 build by default
@ -30,7 +32,7 @@
%global rpmver 4.14.3
#global snapver rc2
%global rel 13
%global rel 18
%global srcver %{version}%{?snapver:-%{snapver}}
%global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x}
@ -103,12 +105,15 @@ Patch150: rpm-4.14.3-add-fapolicyd-rpm-plugin.patch
Patch151: 0001-Unblock-signals-in-forked-scriptlets.patch
Patch152: rpm-4.14.3-fix-ambiguous-diagnostics-on-file-triggers.patch
Patch153: rpm-4.14.3-ELF-files-strip-when-debuginfo-disabled.patch
Patch154: rpm-4.14.3-more-careful-sig-hdr-copy.patch
Patch155: rpm-4.14.3-preserve-kmod-secure-boot-signature.patch
Patch156: rpm-4.14.3-hdrblobInit-add-bounds-check.patch
Patch157: rpm-4.14.3-add-read-only-support-for-sqlite.patch
Patch158: rpm-4.14.3-imp-covscan-fixes.patch
# Python 3 string API sanity
Patch500: 0001-In-Python-3-return-all-our-string-data-as-surrogate-.patch
Patch501: 0001-Return-NULL-string-as-None-from-utf8FromString.patch
# Temporary compat crutch, not upstream
Patch502: 0001-Monkey-patch-.decode-method-to-our-strings-as-a-temp.patch
# Make test-suite work with Python 3
Patch503: 0001-Honor-PYTHON-from-configure-when-running-tests.patch
Patch504: 0002-Use-Python-3-compatible-exception-syntax-in-tests.patch
@ -176,6 +181,9 @@ BuildRequires: lua-devel >= 5.1
BuildRequires: libcap-devel
BuildRequires: libacl-devel
BuildRequires: audit-libs-devel
%if %{with sqlite}
BuildRequires: sqlite-devel
%endif
%if %{with xz}
BuildRequires: xz-devel >= 4.999.8
%endif
@ -458,6 +466,7 @@ done;
%{?with_libimaevm: --with-imaevm} \
%{?with_zstd: --enable-zstd} \
%{?with_lmdb: --enable-lmdb} \
%{?with_sqlite: --enable-sqlite} \
--with-fapolicyd \
--enable-python \
--with-crypto=openssl \
@ -681,6 +690,25 @@ make check || cat tests/rpmtests.log
%doc doc/librpm/html/*
%changelog
* Thu Aug 26 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-18
- Address important covscan issues (#1996665), vol. 2
* Mon Aug 23 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-17
- Address important covscan issues (#1996665)
* Thu Aug 19 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-16
- Add support for read-only sqlite rpmdb (#1938928)
- Drop compat .decode() method from returned Py3 strings (#1840142)
* Thu Jul 15 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-15
- Add out-of-bounds checks to hdrblobInit() (#1929445)
- Fixes CVE-2021-20266
- Fix regression in brp-strip causing kmods to lose SecureBoot sig (#1967291)
* Thu May 27 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-14
- Be more careful about copying data from signature header (#1958477)
- Fixes CVE-2021-20271
* Fri Feb 12 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-13
- Fix minor issues found by COVSCAN in fapolicyd plugin
- Actually honor libarchive bcond at configure time (#1902887)