treefile: Add readonly-executables

Same motivation as
7392259332

I think we should encourage removing the writable bits from
executables.  This has happened to me:
https://thomask.sdf.org/blog/2019/11/09/take-care-editing-bash-scripts.html

And not having the writable bit may help prevent hardlink
corruption with OSTree in some cases.

We can't do this by default, but add a convenient treefile option
for it.

This starts out by just doing this for RPMs, but I'll add
a secondary pass which does it during postprocessing soon too.
This commit is contained in:
Colin Walters 2020-05-06 20:59:39 +00:00 committed by OpenShift Merge Robot
parent 6df03da742
commit 1bd69619eb
6 changed files with 43 additions and 4 deletions

View File

@ -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

View File

@ -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<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
cliwrap: Option<bool>,
#[serde(rename = "readonly-executables")]
#[serde(skip_serializing_if = "Option::is_none")]
readonly_executables: Option<bool>,
// 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() {

View File

@ -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 =

View File

@ -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;
}

View File

@ -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*

View File

@ -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"]]'