public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Petr Lautrbach <lautrbach@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/fapolicyd] f44: fapolicyd-2.0-2
Date: Mon, 24 Aug 2026 14:46:43 GMT	[thread overview]
Message-ID: <178758280312.1.12520463819164667177.rpms-fapolicyd-78f62eabb7aa@fedoraproject.org> (raw)

            A new commit has been pushed.

            Repo   : rpms/fapolicyd
            Branch : f44
            Commit : 78f62eabb7aa37a50ebf10285dd8e328d777fca2
            Author : Petr Lautrbach <lautrbach@redhat.com>
            Date   : 2026-08-13T11:00:47+02:00
            Stats  : +425/-24 in 5 file(s)
            URL    : https://src.fedoraproject.org/rpms/fapolicyd/c/78f62eabb7aa37a50ebf10285dd8e328d777fca2?branch=f44

            Log:
            fapolicyd-2.0-2

- Allow a couple other non-obvious javascript files into the trust db
https://github.com/linux-application-whitelisting/fapolicyd/issues/432

---
diff --git a/0003-update-changelog.patch b/0003-update-changelog.patch
deleted file mode 100644
index 65c25ae..0000000
--- a/0003-update-changelog.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From ccf618b664230e0f5497345e6a4503e6f2c7bca9 Mon Sep 17 00:00:00 2001
-From: Steve Grubb <ausearch.1@gmail.com>
-Date: Thu, 23 Jul 2026 11:26:13 -0400
-Subject: [PATCH] update changelog
-Content-type: text/plain
-
----
- ChangeLog | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/ChangeLog b/ChangeLog
-index d230c610c956..1c3ea75a1c4e 100644
---- a/ChangeLog
-+++ b/ChangeLog
-@@ -1,4 +1,5 @@
- 2.0.1
-+- Enable large file support on 32-bit builds
- 
- 2.0
- - Add decision_threads configuration to fapolicyd.conf
--- 
-2.55.0
-

diff --git a/0004-Allow-KDE-qml-files-into-the-trust-db.patch b/0004-Allow-KDE-qml-files-into-the-trust-db.patch
new file mode 100644
index 0000000..f9e1ebe
--- /dev/null
+++ b/0004-Allow-KDE-qml-files-into-the-trust-db.patch
@@ -0,0 +1,26 @@
+From a1fb321acd9cce76733a7a623aac62f7e8334599 Mon Sep 17 00:00:00 2001
+From: Steve Grubb <ausearch.1@gmail.com>
+Date: Sat, 8 Aug 2026 10:25:17 -0400
+Subject: [PATCH] Allow KDE qml files into the trust db
+Content-type: text/plain
+
+---
+ init/fapolicyd-filter.conf | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/init/fapolicyd-filter.conf b/init/fapolicyd-filter.conf
+index 1acddfb1ab5c..c2db6f17c1bc 100644
+--- a/init/fapolicyd-filter.conf
++++ b/init/fapolicyd-filter.conf
+@@ -43,6 +43,8 @@
+   + *.stp
+   # Javascript
+   + *.js
++  # QML - KDE's javascript-like language
++  + *.qml
+   # Java archive
+   + *.jar
+   # M4
+-- 
+2.55.0
+

diff --git a/0005-Allow-a-couple-other-non-obvious-javascript-files-in.patch b/0005-Allow-a-couple-other-non-obvious-javascript-files-in.patch
new file mode 100644
index 0000000..b740bde
--- /dev/null
+++ b/0005-Allow-a-couple-other-non-obvious-javascript-files-in.patch
@@ -0,0 +1,30 @@
+From fae1cc6b22f5f6ee16b7768ee9e68579843c1552 Mon Sep 17 00:00:00 2001
+From: Steve Grubb <ausearch.1@gmail.com>
+Date: Sat, 8 Aug 2026 16:41:40 -0400
+Subject: [PATCH] Allow a couple other non-obvious javascript files into the
+ trust db
+Content-type: text/plain
+
+---
+ init/fapolicyd-filter.conf | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/init/fapolicyd-filter.conf b/init/fapolicyd-filter.conf
+index c2db6f17c1bc..7c78d60df48f 100644
+--- a/init/fapolicyd-filter.conf
++++ b/init/fapolicyd-filter.conf
+@@ -45,6 +45,11 @@
+   + *.js
+   # QML - KDE's javascript-like language
+   + *.qml
++  # Polkit Javascript rules
++  + polkit-1/rules.d/*.rules
++  # GNOME Javascript applications without a file extension
++  + gnome-shell/org.gnome.*
++  + org.gnome.Characters/org.gnome.Characters
+   # Java archive
+   + *.jar
+   # M4
+-- 
+2.55.0
+

diff --git a/0006-Fix-32-bit-large-file-digest-truncation.patch b/0006-Fix-32-bit-large-file-digest-truncation.patch
new file mode 100644
index 0000000..6519cef
--- /dev/null
+++ b/0006-Fix-32-bit-large-file-digest-truncation.patch
@@ -0,0 +1,361 @@
+From d44f0cab26acdd2fbb17b96c1ec0d75dbe2af044 Mon Sep 17 00:00:00 2001
+From: Steve Grubb <ausearch.1@gmail.com>
+Date: Tue, 11 Aug 2026 13:20:15 -0400
+Subject: [PATCH] Fix 32-bit large-file digest truncation
+Content-type: text/plain
+
+Large-file builds use a 64-bit off_t on 32-bit systems, but get_hash_from_fd2 accepted the byte count as size_t. Files at or above 4 GiB were therefore hashed modulo 2^32 bytes, allowing trust creation and SHA or IMA fallback verification to agree on a truncated digest.
+
+Carry file sizes as off_t through the hashing API and the Debian MD5 backend. Preserve the mmap path for representable sizes, and use offset-safe pread chunks with incremental EVP hashing when the size exceeds SIZE_MAX.
+
+Add an i686-gated LMDB regression that trusts an unchanged 4 GiB file, mutates its final byte, and requires SHA verification to reject it. The RPM and Debian build/test matrices pass, and a focused ELF32 run confirmed that changing the last byte changes the digest.
+---
+ src/library/file.c            | 112 +++++++++++++++++++++++++++++++---
+ src/library/file.h            |   2 +-
+ src/library/md5-backend.c     |   6 +-
+ src/tests/event_test.c        |   6 +-
+ src/tests/md5_backend_test.c  |   2 +-
+ src/tests/trustdb_lmdb_test.c |  74 ++++++++++++++++++++++
+ 6 files changed, 187 insertions(+), 15 deletions(-)
+
+diff --git a/src/library/file.c b/src/library/file.c
+index e52de152895e..627e18115716 100644
+--- a/src/library/file.c
++++ b/src/library/file.c
+@@ -31,6 +31,7 @@
+ #include <sys/stat.h>
+ #include <string.h>
+ #include <stdlib.h>
++#include <openssl/evp.h>
+ #include <openssl/sha.h>
+ #include <openssl/md5.h>
+ #include <magic.h>
+@@ -1339,15 +1340,105 @@ static const char *degenerate_hash_sha512 =
+ 	"47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e";
+ static const char *degenerate_hash_md5 =
+ 	"d41d8cd98f00b204e9800998ecf8427e";
+-char *get_hash_from_fd2(int fd, size_t size, file_hash_alg_t alg)
++
++/*
++ * get_evp_hash_algorithm - map a file hash algorithm to OpenSSL's EVP API.
++ * @alg: file digest algorithm requested by the caller.
++ * Returns the EVP implementation, or NULL when the algorithm is unavailable.
++ */
++static const EVP_MD *get_evp_hash_algorithm(file_hash_alg_t alg)
++{
++	switch (alg) {
++	case FILE_HASH_ALG_SHA1:
++		return EVP_sha1();
++	case FILE_HASH_ALG_SHA256:
++		return EVP_sha256();
++	case FILE_HASH_ALG_SHA512:
++		return EVP_sha512();
++	case FILE_HASH_ALG_MD5:
++#ifdef USE_DEB
++		return EVP_md5();
++#else
++		return NULL;
++#endif
++	default:
++		return NULL;
++	}
++}
++
++/*
++ * hash_fd_in_chunks - hash a file that cannot fit in one mmap length.
++ * @fd: open descriptor whose contents should be measured.
++ * @size: number of bytes to include in the digest calculation.
++ * @alg: digest algorithm to use for the measurement.
++ *
++ * pread preserves the descriptor offset while off_t keeps every chunk offset
++ * representable on 32-bit large-file builds. Returns an allocated hex digest
++ * on success, or NULL on read, allocation, or digest failure.
++ */
++static char *hash_fd_in_chunks(int fd, off_t size, file_hash_alg_t alg)
++{
++	unsigned char buf[64 * 1024];
++	unsigned char hptr[EVP_MAX_MD_SIZE];
++	const EVP_MD *md = get_evp_hash_algorithm(alg);
++	EVP_MD_CTX *ctx = NULL;
++	off_t offset = 0;
++	unsigned int hash_length = 0;
++	char *digest = NULL;
++
++	if (md == NULL)
++		return NULL;
++
++	ctx = EVP_MD_CTX_new();
++	if (ctx == NULL || EVP_DigestInit_ex(ctx, md, NULL) != 1)
++		goto out;
++
++	while (offset < size) {
++		off_t remaining = size - offset;
++		size_t requested = sizeof(buf);
++		ssize_t len;
++
++		if (remaining < (off_t)requested)
++			requested = (size_t)remaining;
++		do {
++			len = pread(fd, buf, requested, offset);
++		} while (len < 0 && errno == EINTR);
++		if (len <= 0) {
++			if (len == 0)
++				errno = EIO;
++			goto out;
++		}
++		if (EVP_DigestUpdate(ctx, buf, (size_t)len) != 1)
++			goto out;
++		offset += len;
++	}
++
++	if (EVP_DigestFinal_ex(ctx, hptr, &hash_length) != 1 ||
++	    hash_length != file_hash_length(alg))
++		goto out;
++
++	digest = malloc(((size_t)hash_length * 2) + 1);
++	if (digest)
++		bytes2hex(digest, hptr, hash_length);
++out:
++	EVP_MD_CTX_free(ctx);
++	return digest;
++}
++
++char *get_hash_from_fd2(int fd, off_t size, file_hash_alg_t alg)
+ {
+ 	unsigned char *mapped;
+ 	char *digest = NULL;
++	size_t map_size;
+ 	size_t digest_length;
+ 	struct decision_timing_span timing;
+ 
+ 	decision_timing_stage_begin(DECISION_TIMING_STAGE_HASH_SHA,
+ 				    &timing);
++	if (size < 0) {
++		decision_timing_stage_end(&timing);
++		return NULL;
++	}
+ 	if (size == 0) {
+ 		char *degenerate;
+ 
+@@ -1378,34 +1469,41 @@ char *get_hash_from_fd2(int fd, size_t size, file_hash_alg_t alg)
+ 		return NULL;
+ 	}
+ 
+-	mapped = mmap(0, size, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0);
++	if ((uintmax_t)size > SIZE_MAX) {
++		digest = hash_fd_in_chunks(fd, size, alg);
++		decision_timing_stage_end(&timing);
++		return digest;
++	}
++
++	map_size = (size_t)size;
++	mapped = mmap(0, map_size, PROT_READ, MAP_SHARED|MAP_POPULATE, fd, 0);
+ 	if (mapped != MAP_FAILED) {
+ 		unsigned char hptr[SHA512_DIGEST_LENGTH];
+ 		int computed = 0;
+ 
+ 		switch (alg) {
+ 		case FILE_HASH_ALG_SHA1:
+-			SHA1(mapped, size, hptr);
++			SHA1(mapped, map_size, hptr);
+ 			computed = 1;
+ 			break;
+ 		case FILE_HASH_ALG_SHA256:
+-			SHA256(mapped, size, hptr);
++			SHA256(mapped, map_size, hptr);
+ 			computed = 1;
+ 			break;
+ 		case FILE_HASH_ALG_SHA512:
+-			SHA512(mapped, size, hptr);
++			SHA512(mapped, map_size, hptr);
+ 			computed = 1;
+ 			break;
+ 		case FILE_HASH_ALG_MD5:
+ #ifdef USE_DEB
+-			MD5(mapped, size, hptr);
++			MD5(mapped, map_size, hptr);
+ 			computed = 1;
+ #endif
+ 			break;
+ 		default:
+ 			break;
+ 		}
+-		munmap(mapped, size);
++		munmap(mapped, map_size);
+ 
+ 		if (computed) {
+ 			digest = malloc((digest_length * 2) + 1);
+diff --git a/src/library/file.h b/src/library/file.h
+index 167cd93587b0..a818062ee7ec 100644
+--- a/src/library/file.h
++++ b/src/library/file.h
+@@ -106,7 +106,7 @@ char *get_file_type_from_fd(int fd, const struct file_info *i, const char *path,
+ 	__attr_access ((__write_only__, 5, 4)) __attr_fd_arg_read (1);
+ char *bytes2hex(char *final, const unsigned char *buf, unsigned int size)
+ 	 __attr_access ((__read_only__, 2, 3));
+-char *get_hash_from_fd2(int fd, size_t size, file_hash_alg_t alg)
++char *get_hash_from_fd2(int fd, off_t size, file_hash_alg_t alg)
+ 	__attr_dealloc_free __attr_fd_arg_read (1);
+ int get_ima_hash(int fd, file_hash_alg_t *alg, char *sha)
+ 	__attr_fd_arg (1);
+diff --git a/src/library/md5-backend.c b/src/library/md5-backend.c
+index 836606d353c1..d68a39e0414d 100644
+--- a/src/library/md5-backend.c
++++ b/src/library/md5-backend.c
+@@ -103,17 +103,17 @@ md5_backend_result_t add_file_to_backend_by_md5(const char *path,
+ 		return MD5_BACKEND_SKIPPED;
+ 	}
+ 
+-	size_t file_size = path_stat.st_size;
++	off_t file_size = path_stat.st_size;
+ 	trustdb_size_t stored_size;
+ 
+-	if (trustdb_size_from_unsigned(file_size, &stored_size)) {
++	if (trustdb_size_from_signed((intmax_t)file_size, &stored_size)) {
+ 		close(fd);
+ 		msg(LOG_ERR, "File size for %s exceeds trust DB format", path);
+ 		return MD5_BACKEND_FATAL;
+ 	}
+ 
+ 	#ifdef DEBUG
+-	msg(LOG_DEBUG, "\tFile size: %zu", file_size);
++	msg(LOG_DEBUG, "\tFile size: %jd", (intmax_t)file_size);
+ 	#endif
+ 
+ 	char *md5_digest = get_hash_from_fd2(fd, file_size,
+diff --git a/src/tests/event_test.c b/src/tests/event_test.c
+index 34c33a9b3a68..9fc174a23095 100644
+--- a/src/tests/event_test.c
++++ b/src/tests/event_test.c
+@@ -65,7 +65,7 @@ int check_trust_database(const char *exe, const char *digest, int mode);
+ char *get_device_from_stat(unsigned int device, size_t blen, char *buf);
+ char *get_file_type_from_fd(int fd, const struct file_info *i, const char *path,
+ 			     size_t blen, char *buf);
+-char *get_hash_from_fd2(int fd, size_t size, file_hash_alg_t alg);
++char *get_hash_from_fd2(int fd, off_t size, file_hash_alg_t alg);
+ 
+ struct stub_proc_record {
+ 	pid_t pid;
+@@ -442,12 +442,12 @@ char *get_file_type_from_fd(int fd, const struct file_info *i, const char *path,
+ /*
+  * Produce a fake digest string so new_event() can populate hash attributes.
+  */
+-char *get_hash_from_fd2(int fd, size_t size, file_hash_alg_t alg)
++char *get_hash_from_fd2(int fd, off_t size, file_hash_alg_t alg)
+ {
+ 	char *out = malloc(64);
+ 	if (out == NULL)
+ 		return NULL;
+-	snprintf(out, 64, "hash-%d-%zu-%d", fd, (size_t)size, (int)alg);
++	snprintf(out, 64, "hash-%d-%jd-%d", fd, (intmax_t)size, (int)alg);
+ 	return out;
+ }
+ 
+diff --git a/src/tests/md5_backend_test.c b/src/tests/md5_backend_test.c
+index 4c7b4e1aec5e..3f4290cae0ef 100644
+--- a/src/tests/md5_backend_test.c
++++ b/src/tests/md5_backend_test.c
+@@ -115,7 +115,7 @@ static char *md5_for_file(const char *path)
+ 	if (fstat(fd, &sb) < 0)
+ 		error(1, errno, "fstat failed");
+ 
+-	hash = get_hash_from_fd2(fd, (size_t)sb.st_size, FILE_HASH_ALG_MD5);
++	hash = get_hash_from_fd2(fd, sb.st_size, FILE_HASH_ALG_MD5);
+ 	if (close(fd) < 0)
+ 		error(1, errno, "close failed");
+ 	if (hash == NULL)
+diff --git a/src/tests/trustdb_lmdb_test.c b/src/tests/trustdb_lmdb_test.c
+index 5e54589cc6d1..f935d482aca5 100644
+--- a/src/tests/trustdb_lmdb_test.c
++++ b/src/tests/trustdb_lmdb_test.c
+@@ -691,6 +691,76 @@ static int test_lmdb_large_size_import(void)
+ 	return 0;
+ }
+ 
++/*
++ * test_lmdb_large_file_sha256_recompute - cover content past size_t on i686.
++ *
++ * Large-file builds have a 64-bit off_t even when size_t remains 32 bits. A
++ * byte at the end of an exact 4 GiB file must therefore affect both the trust
++ * record digest and the runtime SHA recomputation used to validate it. The
++ * IMA fallback uses the same hashing helper when its xattr digest is stale.
++ *
++ * Returns 0 on success or when the host ABI cannot expose the truncation.
++ */
++static int test_lmdb_large_file_sha256_recompute(void)
++{
++	const off_t large_size = (off_t)UINT64_C(4294967296);
++	const char original_tail = 'A';
++	const char changed_tail = 'B';
++	conf_t cfg;
++	char dir[128];
++	char path[128];
++	char payload[512];
++	struct file_info *info = NULL;
++	char *hash = NULL;
++	long entries = 0;
++	int fd = -1;
++	int rc;
++
++	if (sizeof(size_t) >= sizeof(off_t))
++		return 0;
++
++	fd = create_test_file(path, sizeof(path), "");
++	CHECK(fd != -1, 277, "[ERROR:277] failed to create large SHA file");
++	CHECK(ftruncate(fd, large_size) == 0, 278,
++	      "[ERROR:278] failed to size large SHA file");
++	CHECK(pwrite(fd, &original_tail, 1, large_size - 1) == 1, 279,
++	      "[ERROR:279] failed to write large SHA file tail");
++	CHECK(describe_test_file(fd, &info, &hash) == 0, 280,
++	      "[ERROR:280] failed to hash large SHA file");
++
++	rc = with_temp_db(dir, sizeof(dir), &cfg);
++	CHECK(rc == 0, 281, "[ERROR:281] failed to open large SHA LMDB");
++	cfg.integrity = IN_SHA256;
++	rc = decision_config_publish(&cfg);
++	CHECK(rc == 0, 282,
++	      "[ERROR:282] failed to publish SHA integrity config");
++
++	snprintf(payload, sizeof(payload), "%s " DATA_FORMAT "\n", path,
++		 SRC_FILE_DB, (trustdb_size_t)info->size, hash);
++	rc = import_records(payload, &entries);
++	CHECK(rc == 0 && entries == 1, 283,
++	      "[ERROR:283] large SHA record import failed");
++	CHECK(check_trust_database(path, info, fd) == 1, 284,
++	      "[ERROR:284] unchanged large SHA file was not trusted");
++
++	CHECK(pwrite(fd, &changed_tail, 1, large_size - 1) == 1, 285,
++	      "[ERROR:285] failed to change large SHA file tail");
++	CHECK(check_trust_database(path, info, fd) == 0, 286,
++	      "[ERROR:286] changed large SHA file remained trusted");
++
++	decision_config_destroy();
++	database_close_for_tests();
++	database_set_location(NULL, NULL);
++	CHECK(remove_lmdb_files(dir) == 0, 287,
++	      "[ERROR:287] large SHA LMDB cleanup failed");
++	free(hash);
++	free(info);
++	CHECK(close(fd) == 0, 288, "[ERROR:288] large SHA file close failed");
++	CHECK(unlink(path) == 0, 289,
++	      "[ERROR:289] large SHA file cleanup failed");
++	return 0;
++}
++
+ static int test_lmdb_short_path_round_trip(void)
+ {
+ 	conf_t cfg;
+@@ -1976,6 +2046,10 @@ int main(void)
+ 	if (rc)
+ 		return rc;
+ 
++	rc = test_lmdb_large_file_sha256_recompute();
++	if (rc)
++		return rc;
++
+ 	rc = test_lmdb_short_path_round_trip();
+ 	if (rc)
+ 		return rc;
+-- 
+2.55.0
+

diff --git a/fapolicyd.spec b/fapolicyd.spec
index 69f331c..4b8f9df 100644
--- a/fapolicyd.spec
+++ b/fapolicyd.spec
@@ -5,7 +5,7 @@
 Summary: Application Whitelisting Daemon
 Name: fapolicyd
 Version: 2.0
-Release: 1%{?dist}
+Release: 2%{?dist}
 License: GPL-3.0-or-later
 URL: https://github.com/linux-application-whitelisting/fapolicyd
 Source0: https://github.com/linux-application-whitelisting/fapolicyd/releases/download/v%{version}/fapolicyd-%{version}.tar.gz
@@ -24,6 +24,9 @@ Source20: https://github.com/troydhanson/uthash/archive/refs/tags/v2.3.0.tar.gz#
 # $ for j in [0-9]*.patch; do printf "Patch: %s\n" $j; done
 # Patch list start
 Patch: 0002-Fix-large-file-support-on-32-bit-builds.patch
+Patch: 0004-Allow-KDE-qml-files-into-the-trust-db.patch
+Patch: 0005-Allow-a-couple-other-non-obvious-javascript-files-in.patch
+Patch: 0006-Fix-32-bit-large-file-digest-truncation.patch
 # Patch: 0003-update-changelog.patch
 # Patch list end
 
@@ -231,6 +234,10 @@ fi
 %selinux_relabel_post -s %{selinuxtype}
 
 %changelog
+* Thu Aug 13 2026 Petr Lautrbach <lautrbach@redhat.com> - 2.0-2
+- Allow a couple other non-obvious javascript files into the trust db
+  https://github.com/linux-application-whitelisting/fapolicyd/issues/432
+
 * Thu Jul 23 2026 Petr Lautrbach <lautrbach@redhat.com> - 2.0-1
 - fapolicyd-2.0
   https://github.com/linux-application-whitelisting/fapolicyd/releases/tag/v2.0

                 reply	other threads:[~2026-08-24 14:46 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178758280312.1.12520463819164667177.rpms-fapolicyd-78f62eabb7aa@fedoraproject.org \
    --to=lautrbach@redhat.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox