Skip to content

Commit

Permalink
libpriv/postprocess: also delete semanage lock files
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jlebon authored and rh-atomic-bot committed Sep 21, 2017
1 parent 25ba196 commit 684c60c
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 30 deletions.
110 changes: 85 additions & 25 deletions src/libpriv/rpmostree-postprocess.c
Original file line number Diff line number Diff line change
Expand Up @@ -1111,51 +1111,111 @@ rpmostree_rootfs_prepare_links (int rootfs_fd,
return TRUE;
}

/**
* rpmostree_rootfs_postprocess_common:
*
* Walk over the root filesystem and perform some core conversions
* from RPM conventions to OSTree conventions. For example:
*
* - Move /etc to /usr/etc
* - Clean up RPM db leftovers
* - Clean /usr/etc/passwd- backup files and such
*/
gboolean
rpmostree_rootfs_postprocess_common (int rootfs_fd,
GCancellable *cancellable,
GError **error)
static gboolean
cleanup_leftover_files (int rootfs_fd,
const char *subpath,
const char *files[],
const char *prefixes[],
GCancellable *cancellable,
GError **error)
{
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 (!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;
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;
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 (!(g_str_has_prefix (name, "__db.") ||
strcmp (name, ".dbenv.lock") == 0 ||
strcmp (name, ".rpm.lock") == 0))
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:
*
* Walk over the root filesystem and perform some core conversions
* from RPM conventions to OSTree conventions. For example:
*
* - Move /etc to /usr/etc
* - Clean up RPM db leftovers
* - Clean /usr/etc/passwd- backup files and such
*/
gboolean
rpmostree_rootfs_postprocess_common (int rootfs_fd,
GCancellable *cancellable,
GError **error)
{
if (!rename_if_exists (rootfs_fd, "etc", "usr/etc", error))
return FALSE;

if (!cleanup_leftover_files (rootfs_fd, "usr/share/rpm", rpmdb_leftover_files,
rpmdb_leftover_prefixes, cancellable, error))
return FALSE;

if (!cleanup_selinux_lockfiles (rootfs_fd, cancellable, error))
return FALSE;

if (!rpmostree_passwd_cleanup (rootfs_fd, cancellable, error))
return FALSE;

Expand Down
19 changes: 14 additions & 5 deletions src/libpriv/rpmostree-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions src/libpriv/rpmostree-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions tests/compose-tests/test-basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
4 changes: 4 additions & 0 deletions tests/vmcheck/overlay.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 684c60c

Please sign in to comment.