import rpm-4.14.3-19.el8
This commit is contained in:
parent
fad1776797
commit
d9811c5e19
@ -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
|
||||
|
798
SOURCES/rpm-4.14.3-add-read-only-support-for-sqlite.patch
Normal file
798
SOURCES/rpm-4.14.3-add-read-only-support-for-sqlite.patch
Normal 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
|
||||
|
100
SOURCES/rpm-4.14.3-hdrblobInit-add-bounds-check.patch
Normal file
100
SOURCES/rpm-4.14.3-hdrblobInit-add-bounds-check.patch
Normal 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;
|
327
SOURCES/rpm-4.14.3-imp-covscan-fixes.patch
Normal file
327
SOURCES/rpm-4.14.3-imp-covscan-fixes.patch
Normal 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);
|
||||
}
|
@ -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 14
|
||||
%global rel 19
|
||||
|
||||
%global srcver %{version}%{?snapver:-%{snapver}}
|
||||
%global srcdir %{?snapver:testing}%{!?snapver:%{name}-%(echo %{version} | cut -d'.' -f1-2).x}
|
||||
@ -104,12 +106,13 @@ 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
|
||||
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
|
||||
@ -177,6 +180,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
|
||||
@ -459,6 +465,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 \
|
||||
@ -682,6 +689,24 @@ make check || cat tests/rpmtests.log
|
||||
%doc doc/librpm/html/*
|
||||
|
||||
%changelog
|
||||
* Wed Oct 06 2021 Michal Domonkos <mdomonko@redhat.com> - 4.14.3-19
|
||||
- Unbreak in-tree kmod strip by reverting brp-strip fix (#1967291)
|
||||
|
||||
* 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
|
||||
|
Loading…
Reference in New Issue
Block a user