From aedf4d9fe1cae452e3a8d44e738b5e2e539a781a Mon Sep 17 00:00:00 2001 From: Paul Meyer <49727155+katexochen@users.noreply.github.com> Date: Wed, 28 Aug 2024 11:57:34 +0200 Subject: [PATCH] token: sort paths for reproducible extract There is no defined order in which readdir will return the entries of a directory. In practice, order can depend on inode number or similar. If we run p11-kit on different files systems with similar directory structure but different inode order the output of extract can change. To get a stable and reproducible output, sort the paths returned by readdir before extracting. Co-authored-by: Tom Dohrmann Signed-off-by: Paul Meyer <49727155+katexochen@users.noreply.github.com> --- trust/token.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/trust/token.c b/trust/token.c index 473847dc2..f2c14b342 100644 --- a/trust/token.c +++ b/trust/token.c @@ -252,16 +252,28 @@ loader_load_if_file (p11_token *token, return 0; } +static int +compar_strings (const void *one, + const void *two) +{ + const char **p1 = (const char **)one; + const char **p2 = (const char **)two; + return strcmp (*p1, *p2); +} + + static int loader_load_directory (p11_token *token, const char *directory, p11_dict *present) { p11_dictiter iter; + p11_array *paths; struct dirent *dp; char *path; int total = 0; int ret; + int i; DIR *dir; /* First we load all the modules */ @@ -272,10 +284,22 @@ loader_load_directory (p11_token *token, return 0; } + paths = p11_array_new (NULL); + return_val_if_fail (paths != NULL, -1); + while ((dp = readdir (dir)) != NULL) { path = p11_path_build (directory, dp->d_name, NULL); return_val_if_fail (path != NULL, -1); + + return_val_if_fail (p11_array_push (paths, path), -1); + } + + closedir (dir); + + qsort (paths->elem, paths->num, sizeof (char *), compar_strings); + for (i = 0; i < paths->num; i++) { + path = paths->elem[i]; ret = loader_load_if_file (token, path); if (ret >= 0) { if (ret <= INT_MAX - total) { @@ -291,7 +315,7 @@ loader_load_directory (p11_token *token, free (path); } - closedir (dir); + p11_array_free (paths); /* All other files that were present, not here now */ p11_dict_iterate (present, &iter);