libpriv/postprocess: also delete semanage lock files

We don't need those in the tree, so let's nuke them. This also fixes
subtle compatibility issues between hardlinks and lock files (see #999).

Closes: #1002
Approved by: cgwalters
This commit is contained in:
Jonathan Lebon 2017-09-19 19:20:09 +00:00 committed by Atomic Bot
parent 25ba196c27
commit f089b8de1f
5 changed files with 113 additions and 30 deletions

View File

@ -1111,6 +1111,86 @@ rpmostree_rootfs_prepare_links (int rootfs_fd,
return TRUE;
}
static gboolean
cleanup_leftover_files (int rootfs_fd,
const char *subpath,
const char *files[],
const char *prefixes[],
GCancellable *cancellable,
GError **error)
{
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
if (!glnx_dirfd_iterator_init_at (rootfs_fd, subpath, TRUE, &dfd_iter, error))
return glnx_prefix_error (error, "Opening %s", subpath);
while (TRUE)
{
struct dirent *dent = NULL;
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
return FALSE;
if (!dent)
break;
if (dent->d_type != DT_REG)
continue;
const char *name = dent->d_name;
const gboolean in_files = (files != NULL && g_strv_contains (files, name));
const gboolean has_prefix =
(prefixes != NULL && rpmostree_str_has_prefix_in_strv (name, (char**)prefixes, -1));
if (!in_files && !has_prefix)
continue;
if (unlinkat (dfd_iter.fd, name, 0) < 0)
return glnx_throw_errno_prefix (error, "Unlinking %s: ", name);
}
return TRUE;
}
static const char *selinux_leftover_files[] = { "semanage.trans.LOCK",
"semanage.read.LOCK", NULL };
static const char *rpmdb_leftover_files[] = { ".dbenv.lock",
".rpm.lock", NULL };
static const char *rpmdb_leftover_prefixes[] = { "__db.", NULL };
static gboolean
cleanup_selinux_lockfiles (int rootfs_fd,
GCancellable *cancellable,
GError **error)
{
struct stat stbuf;
if (!glnx_fstatat_allow_noent (rootfs_fd, "usr/etc/selinux", &stbuf, 0, error))
return FALSE;
if (errno == ENOENT)
return TRUE; /* Note early return */
/* really we only have to do this for the active policy, but let's scan all the dirs */
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
if (!glnx_dirfd_iterator_init_at (rootfs_fd, "usr/etc/selinux", FALSE, &dfd_iter, error))
return glnx_prefix_error (error, "Opening /usr/etc/selinux");
while (TRUE)
{
struct dirent *dent = NULL;
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
return FALSE;
if (!dent)
break;
if (dent->d_type != DT_DIR)
continue;
const char *name = dent->d_name;
if (!cleanup_leftover_files (dfd_iter.fd, name, selinux_leftover_files, NULL,
cancellable, error))
return FALSE;
}
return TRUE;
}
/**
* rpmostree_rootfs_postprocess_common:
*
@ -1129,32 +1209,12 @@ rpmostree_rootfs_postprocess_common (int rootfs_fd,
if (!rename_if_exists (rootfs_fd, "etc", "usr/etc", error))
return FALSE;
g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
if (!glnx_dirfd_iterator_init_at (rootfs_fd, "usr/share/rpm", TRUE, &dfd_iter, error))
return glnx_prefix_error (error, "Opening usr/share/rpm");
if (!cleanup_leftover_files (rootfs_fd, "usr/share/rpm", rpmdb_leftover_files,
rpmdb_leftover_prefixes, cancellable, error))
return FALSE;
while (TRUE)
{
struct dirent *dent = NULL;
const char *name;
if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
return FALSE;
if (!dent)
break;
if (dent->d_type != DT_REG)
continue;
name = dent->d_name;
if (!(g_str_has_prefix (name, "__db.") ||
strcmp (name, ".dbenv.lock") == 0 ||
strcmp (name, ".rpm.lock") == 0))
continue;
if (unlinkat (dfd_iter.fd, name, 0) < 0)
return glnx_throw_errno_prefix (error, "Unlinking %s: ", name);
}
if (!cleanup_selinux_lockfiles (rootfs_fd, cancellable, error))
return FALSE;
if (!rpmostree_passwd_cleanup (rootfs_fd, cancellable, error))
return FALSE;

View File

@ -371,18 +371,27 @@ rpmostree_file_get_path_cached (GFile *file)
}
gboolean
rpmostree_str_has_prefix_in_ptrarray (const char *str,
GPtrArray *prefixes)
rpmostree_str_has_prefix_in_strv (const char *str,
char **prefixes,
int n)
{
for (guint j = 0; j < prefixes->len; j++)
if (n < 0)
n = g_strv_length (prefixes);
for (int i = 0; i < n; i++)
{
const char *prefix = prefixes->pdata[j];
if (g_str_has_prefix (str, prefix))
if (g_str_has_prefix (str, prefixes[i]))
return TRUE;
}
return FALSE;
}
gboolean
rpmostree_str_has_prefix_in_ptrarray (const char *str,
GPtrArray *prefixes)
{
return rpmostree_str_has_prefix_in_strv (str, (char**)prefixes->pdata, prefixes->len);
}
/* Like g_strv_contains() but for ptrarray */
gboolean
rpmostree_str_ptrarray_contains (GPtrArray *strs,

View File

@ -89,6 +89,11 @@ void rpmostree_diff_print (OstreeRepo *repo,
GPtrArray *modified_old,
GPtrArray *modified_new);
gboolean
rpmostree_str_has_prefix_in_strv (const char *str,
char **strv,
int n);
gboolean
rpmostree_str_has_prefix_in_ptrarray (const char *str,
GPtrArray *prefixes);

View File

@ -48,3 +48,8 @@ ostree --repo=${repobuild} ls ${treeref} /tmp > ls.txt
assert_file_has_content ls.txt 'l00777 0 0 0 /tmp -> sysroot/tmp'
echo "ok /tmp"
ostree --repo=${repobuild} ls ${treeref} /usr/share/rpm > ls.txt
assert_not_file_has_content ls.txt '__db' 'lock'
ostree --repo=${repobuild} ls -R ${treeref} /usr/etc/selinux > ls.txt
assert_not_file_has_content ls.txt 'LOCK'
echo "ok no leftover files"

View File

@ -55,6 +55,10 @@ if ! ostree commit --help | grep -q -e --selinux-policy; then
fi
# ✀✀✀ END hack to get --selinux-policy ✀✀✀
# ✀✀✀ BEGIN tmp hack for https://github.com/projectatomic/rpm-ostree/pull/999
rm -vrf vmcheck/usr/etc/selinux/targeted/semanage.*.LOCK
# ✀✀✀ END tmp hack
ostree refs --delete vmcheck || true
ostree commit -b vmcheck --link-checkout-speedup \
--selinux-policy=vmcheck --tree=dir=vmcheck