diff --git a/docs/manual/treefile.md b/docs/manual/treefile.md index 3850ecba..6ea5f2e4 100644 --- a/docs/manual/treefile.md +++ b/docs/manual/treefile.md @@ -100,6 +100,11 @@ It supports the following parameters: The default is `false` out of conservatism; you likely want to enable this. + * `readonly-executables`: boolean, optional. Defaults to `false` (for backcompat). + If enabled, rpm-ostree will remove the write bit from all executables. + + The default is `false` out of conservatism; you likely want to enable this. + * `remove-files`: Array of files to delete from the generated tree. * `remove-from-packages`: Array, optional: Delete from specified packages diff --git a/rust/src/treefile.rs b/rust/src/treefile.rs index a971fb7b..3ccd5af4 100644 --- a/rust/src/treefile.rs +++ b/rust/src/treefile.rs @@ -297,6 +297,7 @@ fn treefile_merge(dest: &mut TreeComposeConfig, src: &mut TreeComposeConfig) { container, recommends, cliwrap, + readonly_executables, documentation, boot_location, tmp_is_dir, @@ -691,6 +692,9 @@ struct TreeComposeConfig { initramfs_args: Option>, #[serde(skip_serializing_if = "Option::is_none")] cliwrap: Option, + #[serde(rename = "readonly-executables")] + #[serde(skip_serializing_if = "Option::is_none")] + readonly_executables: Option, // Tree layout options #[serde(skip_serializing_if = "Option::is_none")] @@ -1379,6 +1383,12 @@ mod ffi { tf.parsed.cliwrap.unwrap_or(false) } + #[no_mangle] + pub extern "C" fn ror_treefile_get_readonly_executables(tf: *mut Treefile) -> bool { + let tf = ref_from_raw_ptr(tf); + tf.parsed.readonly_executables.unwrap_or(false) + } + #[no_mangle] pub extern "C" fn ror_treefile_free(tf: *mut Treefile) { if tf.is_null() { diff --git a/src/libpriv/rpmostree-core.c b/src/libpriv/rpmostree-core.c index 9a06e843..e1428077 100644 --- a/src/libpriv/rpmostree-core.c +++ b/src/libpriv/rpmostree-core.c @@ -2541,6 +2541,9 @@ start_async_import_one_package (RpmOstreeContext *self, DnfPackage *pkg, flags |= RPMOSTREE_IMPORTER_FLAGS_NODOCS; } + if (self->treefile_rs && ror_treefile_get_readonly_executables (self->treefile_rs)) + flags |= RPMOSTREE_IMPORTER_FLAGS_RO_EXECUTABLES; + /* TODO - tweak the unpacker flags for containers */ OstreeRepo *ostreerepo = get_pkgcache_repo (self); g_autoptr(RpmOstreeImporter) unpacker = diff --git a/src/libpriv/rpmostree-importer.c b/src/libpriv/rpmostree-importer.c index 31fa2daf..aa0bb474 100644 --- a/src/libpriv/rpmostree-importer.c +++ b/src/libpriv/rpmostree-importer.c @@ -719,6 +719,18 @@ compose_filter_cb (OstreeRepo *repo, ensure_directories_user_writable (file_info); + /* See similar code in `ostree commit` - https://github.com/ostreedev/ostree/pull/2091/commits/7392259332e00c33ed45b904deabde08f4da3e3c */ + if ((self->flags & RPMOSTREE_IMPORTER_FLAGS_RO_EXECUTABLES) > 0 && + g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) + { + guint32 mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode"); + if (mode & (S_IXUSR | S_IXGRP | S_IXOTH)) + { + mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); + g_file_info_set_attribute_uint32 (file_info, "unix::mode", mode); + } + } + return OSTREE_REPO_COMMIT_FILTER_ALLOW; } diff --git a/src/libpriv/rpmostree-importer.h b/src/libpriv/rpmostree-importer.h index f8f74a5a..4fdbf187 100644 --- a/src/libpriv/rpmostree-importer.h +++ b/src/libpriv/rpmostree-importer.h @@ -40,10 +40,12 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (RpmOstreeImporter, g_object_unref) * RpmOstreeImporterFlags: * @RPMOSTREE_IMPORTER_FLAGS_SKIP_EXTRANEOUS: Skip files/directories outside of supported ostree-compliant paths rather than erroring out * @RPMOSTREE_IMPORTER_FLAGS_NODOCS: Skip documentation files + * @RPMOSTREE_IMPORTER_FLAGS_RO_EXECUTABLES: Make executable files readonly */ typedef enum { RPMOSTREE_IMPORTER_FLAGS_SKIP_EXTRANEOUS = (1 << 0), RPMOSTREE_IMPORTER_FLAGS_NODOCS = (1 << 1), + RPMOSTREE_IMPORTER_FLAGS_RO_EXECUTABLES = (1 << 2), } RpmOstreeImporterFlags; RpmOstreeImporter* diff --git a/tests/compose/test-misc-tweaks.sh b/tests/compose/test-misc-tweaks.sh index e0ff73c0..43a001f0 100755 --- a/tests/compose/test-misc-tweaks.sh +++ b/tests/compose/test-misc-tweaks.sh @@ -20,12 +20,14 @@ treefile_append "packages" '["foobar"]' cat > config/documentation.yaml <<'EOF' documentation: true EOF -cat > config/recommends.yaml <<'EOF' +cat > config/other.yaml <<'EOF' recommends: true +readonly-executables: true EOF -treefile_append "include" '["documentation.yaml", "recommends.yaml"]' -treefile_del 'recommends' -treefile_del 'documentation' +treefile_append "include" '["documentation.yaml", "other.yaml"]' +for x in 'recommends' 'documentation' 'readonly-executables'; do + treefile_del "$x" +done # Test blacklists treefile_append "exclude-packages" '["somenonexistent-package", "gnome-shell"]' @@ -169,6 +171,11 @@ ostree --repo=${repo} cat ${treeref} /usr/bin/ls > ls.txt assert_file_has_content ls.txt '^sweet new ls binary$' echo "ok layers" +# Test readonly-executables +ostree --repo=${repo} ls ${treeref} /usr/bin/bash > ls.txt +assert_file_has_content ls.txt '^-00555 .*/usr/bin/bash$' +echo "ok readonly-executables" + # Check that add-files with bad paths are rejected treefile_append "add-files" '[["foo.txt", "/var/lib/foo.txt"]]'