postprocess: Use names (not ids) in synthesized tmpfiles.d files

Related to: https://github.com/projectatomic/rpm-ostree/issues/49

We want to support "name binding" per client system, rather than
having a hardcoded mapping in our tree.  Currently if e.g. a new
daemon is added as a dependency (or as part of e.g. systemd) it's
easy to silently miss it.

This is prep for doing that binding client side consistently, which is what we
do with package layering.

Closes: #1077
Approved by: jlebon
This commit is contained in:
Colin Walters 2017-10-27 12:56:05 -04:00 committed by Atomic Bot
parent 669031f63b
commit d6218e0e16
5 changed files with 122 additions and 5 deletions

View File

@ -1140,3 +1140,97 @@ rpmostree_passwd_complete_rpm_layering (int rootfs_dfd,
*/
return TRUE;
}
struct RpmOstreePasswdDB
{
GHashTable *users;
GHashTable *groups;
};
static gboolean
add_passwd_to_hash (int rootfs_dfd, const char *path,
GHashTable *users, GError **error)
{
g_autoptr(FILE) src_stream = open_file_stream_read_at (rootfs_dfd, path, error);
if (!src_stream)
return FALSE;
while (TRUE)
{
errno = 0;
struct passwd *pw = fgetpwent (src_stream);
if (!pw)
{
if (errno != 0 && errno != ENOENT)
return glnx_throw_errno_prefix (error, "fgetpwent");
break;
}
g_hash_table_insert (users, GUINT_TO_POINTER (pw->pw_uid), g_strdup (pw->pw_name));
}
return TRUE;
}
static gboolean
add_groups_to_hash (int rootfs_dfd, const char *path,
GHashTable *groups, GError **error)
{
g_autoptr(FILE) src_stream = open_file_stream_read_at (rootfs_dfd, path, error);
if (!src_stream)
return FALSE;
while (TRUE)
{
errno = 0;
struct group *gr = fgetgrent (src_stream);
if (!gr)
{
if (errno != 0 && errno != ENOENT)
return glnx_throw_errno_prefix (error, "fgetgrent");
break;
}
g_hash_table_insert (groups, GUINT_TO_POINTER (gr->gr_gid), g_strdup (gr->gr_name));
}
return TRUE;
}
RpmOstreePasswdDB *
rpmostree_passwddb_open (int rootfs, GCancellable *cancellable, GError **error)
{
g_autoptr(RpmOstreePasswdDB) ret = g_new0 (RpmOstreePasswdDB, 1);
ret->users = g_hash_table_new_full (NULL, NULL, NULL, g_free);
ret->groups = g_hash_table_new_full (NULL, NULL, NULL, g_free);
if (!add_passwd_to_hash (rootfs, "usr/etc/passwd", ret->users, error))
return NULL;
if (!add_passwd_to_hash (rootfs, "usr/lib/passwd", ret->users, error))
return NULL;
if (!add_groups_to_hash (rootfs, "usr/etc/group", ret->groups, error))
return NULL;
if (!add_groups_to_hash (rootfs, "usr/lib/group", ret->groups, error))
return NULL;
return g_steal_pointer (&ret);
}
const char *
rpmostree_passwddb_lookup_user (RpmOstreePasswdDB *db, uid_t uid)
{
return g_hash_table_lookup (db->users, GUINT_TO_POINTER (uid));
}
const char *
rpmostree_passwddb_lookup_group (RpmOstreePasswdDB *db, gid_t gid)
{
return g_hash_table_lookup (db->groups, GUINT_TO_POINTER (gid));
}
void
rpmostree_passwddb_free (RpmOstreePasswdDB *db)
{
g_hash_table_unref (db->users);
g_hash_table_unref (db->groups);
g_free (db);
}

View File

@ -63,6 +63,16 @@ rpmostree_generate_passwd_from_previous (OstreeRepo *repo,
GCancellable *cancellable,
GError **error);
typedef struct RpmOstreePasswdDB RpmOstreePasswdDB;
RpmOstreePasswdDB *
rpmostree_passwddb_open (int rootfs, GCancellable *cancellable, GError **error);
const char *
rpmostree_passwddb_lookup_user (RpmOstreePasswdDB *db, uid_t uid);
const char *
rpmostree_passwddb_lookup_group (RpmOstreePasswdDB *db, gid_t gid);
void
rpmostree_passwddb_free (RpmOstreePasswdDB *db);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(RpmOstreePasswdDB, rpmostree_passwddb_free)
gboolean
rpmostree_passwd_cleanup (int rootfs_dfd, GCancellable *cancellable, GError **error);

View File

@ -428,6 +428,7 @@ process_kernel_and_initramfs (int rootfs_dfd,
static gboolean
convert_var_to_tmpfiles_d_recurse (GOutputStream *tmpfiles_out,
int dfd,
RpmOstreePasswdDB *pwdb,
GString *prefix,
GCancellable *cancellable,
GError **error)
@ -478,13 +479,19 @@ convert_var_to_tmpfiles_d_recurse (GOutputStream *tmpfiles_out,
return FALSE;
g_string_append_printf (tmpfiles_d_buf, " 0%02o", stbuf.st_mode & ~S_IFMT);
g_string_append_printf (tmpfiles_d_buf, " %d %d - -", stbuf.st_uid, stbuf.st_gid);
const char *user = rpmostree_passwddb_lookup_user (pwdb, stbuf.st_uid);
if (!user)
return glnx_throw (error, "Failed to find user '%u' for %s", stbuf.st_uid, dent->d_name);
const char *group = rpmostree_passwddb_lookup_group (pwdb, stbuf.st_gid);
if (!group)
return glnx_throw (error, "Failed to find group '%u' for %s", stbuf.st_gid, dent->d_name);
g_string_append_printf (tmpfiles_d_buf, " %s %s - -", user, group);
/* Push prefix */
g_string_append_c (prefix, '/');
g_string_append (prefix, dent->d_name);
if (!convert_var_to_tmpfiles_d_recurse (tmpfiles_out, dfd, prefix,
if (!convert_var_to_tmpfiles_d_recurse (tmpfiles_out, dfd, pwdb, prefix,
cancellable, error))
return FALSE;
@ -525,6 +532,10 @@ convert_var_to_tmpfiles_d (int rootfs_dfd,
GCancellable *cancellable,
GError **error)
{
g_autoptr(RpmOstreePasswdDB) pwdb = rpmostree_passwddb_open (rootfs_dfd, cancellable, error);
if (!pwdb)
return FALSE;
glnx_autofd int var_dfd = -1;
/* List of files that are known to possibly exist, but in practice
* things work fine if we simply ignore them. Don't add something
@ -573,7 +584,7 @@ convert_var_to_tmpfiles_d (int rootfs_dfd,
return FALSE;
g_autoptr(GString) prefix = g_string_new ("/var");
if (!convert_var_to_tmpfiles_d_recurse (tmpfiles_out, rootfs_dfd, prefix, cancellable, error))
if (!convert_var_to_tmpfiles_d_recurse (tmpfiles_out, rootfs_dfd, pwdb, prefix, cancellable, error))
return FALSE;
if (!g_output_stream_close (tmpfiles_out, cancellable, error))

View File

@ -57,5 +57,7 @@ echo "ok no leftover files"
ostree --repo=${repobuild} cat ${treeref} /usr/lib/tmpfiles.d/rpm-ostree-1-autovar.conf > autovar.txt
# Picked this one at random as an example of something that won't likely be
# converted to tmpfiles.d upstream. But if it is, we can change this test.
assert_file_has_content_literal autovar.txt 'd /var/cache 0755 0 0 - -'
assert_file_has_content_literal autovar.txt 'd /var/cache 0755 root root - -'
# And this one has a non-root uid
assert_file_has_content_literal autovar.txt 'd /var/log/chrony 0755 chrony chrony - -'
echo "ok autovar"

View File

@ -3,7 +3,7 @@
"repos": ["fedora"],
"packages": ["kernel", "nss-altfiles", "systemd", "ostree", "selinux-policy-targeted"],
"packages": ["kernel", "nss-altfiles", "systemd", "ostree", "selinux-policy-targeted", "chrony"],
"packages-aarch64": ["grub2-efi", "ostree-grub2",
"efibootmgr", "shim"],