Skip to content

Commit

Permalink
postprocess: Use names (not ids) in synthesized tmpfiles.d files
Browse files Browse the repository at this point in the history
Related to: coreos#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.
  • Loading branch information
cgwalters committed Oct 27, 2017
1 parent 669031f commit d3a52f8
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 5 deletions.
94 changes: 94 additions & 0 deletions src/libpriv/rpmostree-passwd-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
10 changes: 10 additions & 0 deletions src/libpriv/rpmostree-passwd-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
17 changes: 14 additions & 3 deletions src/libpriv/rpmostree-postprocess.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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))
Expand Down
4 changes: 3 additions & 1 deletion tests/compose-tests/test-basic.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
2 changes: 1 addition & 1 deletion tests/composedata/fedora-base.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
Expand Down

0 comments on commit d3a52f8

Please sign in to comment.