1 | /* Test ldconfig does not segfault when aux-cache is corrupted (Bug 18093). |
2 | Copyright (C) 2019-2022 Free Software Foundation, Inc. |
3 | This file is part of the GNU C Library. |
4 | |
5 | The GNU C Library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public License as |
7 | published by the Free Software Foundation; either version 2.1 of the |
8 | License, or (at your option) any later version. |
9 | |
10 | The GNU C Library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Lesser General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Lesser General Public |
16 | License along with the GNU C Library; see the file COPYING.LIB. If |
17 | not, see <https://www.gnu.org/licenses/>. */ |
18 | |
19 | /* This test does the following: |
20 | Run ldconfig to create the caches. |
21 | Corrupt the caches. |
22 | Run ldconfig again. |
23 | At each step we verify that ldconfig does not crash. */ |
24 | |
25 | #include <stdio.h> |
26 | #include <stdlib.h> |
27 | #include <string.h> |
28 | #include <unistd.h> |
29 | #include <errno.h> |
30 | #include <sys/wait.h> |
31 | #include <ftw.h> |
32 | #include <stdint.h> |
33 | |
34 | #include <support/capture_subprocess.h> |
35 | #include <support/check.h> |
36 | #include <support/support.h> |
37 | #include <support/xunistd.h> |
38 | |
39 | #include <dirent.h> |
40 | |
41 | static int |
42 | display_info (const char *fpath, const struct stat *sb, |
43 | int tflag, struct FTW *ftwbuf) |
44 | { |
45 | printf (format: "info: %-3s %2d %7jd %-40s %d %s\n" , |
46 | (tflag == FTW_D) ? "d" : (tflag == FTW_DNR) ? "dnr" : |
47 | (tflag == FTW_DP) ? "dp" : (tflag == FTW_F) ? "f" : |
48 | (tflag == FTW_NS) ? "ns" : (tflag == FTW_SL) ? "sl" : |
49 | (tflag == FTW_SLN) ? "sln" : "???" , |
50 | ftwbuf->level, (intmax_t) sb->st_size, |
51 | fpath, ftwbuf->base, fpath + ftwbuf->base); |
52 | /* To tell nftw to continue. */ |
53 | return 0; |
54 | } |
55 | |
56 | static void |
57 | execv_wrapper (void *args) |
58 | { |
59 | char **argv = args; |
60 | |
61 | execv (path: argv[0], argv: argv); |
62 | FAIL_EXIT1 ("execv: %m" ); |
63 | } |
64 | |
65 | /* Run ldconfig with a corrupt aux-cache, in particular we test for size |
66 | truncation that might happen if a previous ldconfig run failed or if |
67 | there were storage or power issues while we were writing the file. |
68 | We want ldconfig not to crash, and it should be able to do so by |
69 | computing the expected size of the file (bug 18093). */ |
70 | static int |
71 | do_test (void) |
72 | { |
73 | char *prog = xasprintf (format: "%s/ldconfig" , support_install_rootsbindir); |
74 | char *args[] = { prog, NULL }; |
75 | const char *path = "/var/cache/ldconfig/aux-cache" ; |
76 | struct stat64 fs; |
77 | long int size, new_size, i; |
78 | |
79 | /* Create the needed directories. */ |
80 | xmkdirp ("/var/cache/ldconfig" , 0777); |
81 | |
82 | /* Run ldconfig first to generate the aux-cache. */ |
83 | struct support_capture_subprocess result; |
84 | result = support_capture_subprocess (callback: execv_wrapper, closure: args); |
85 | support_capture_subprocess_check (&result, context: "execv" , status_or_signal: 0, allowed: sc_allow_none); |
86 | support_capture_subprocess_free (&result); |
87 | |
88 | xstat (path, &fs); |
89 | |
90 | size = fs.st_size; |
91 | /* Run 3 tests, each truncating aux-cache shorter and shorter. */ |
92 | for (i = 3; i > 0; i--) |
93 | { |
94 | new_size = size * i / 4; |
95 | if (truncate (file: path, length: new_size)) |
96 | FAIL_EXIT1 ("truncation failed: %m" ); |
97 | if (nftw (dir: path, func: display_info, descriptors: 1000, flag: 0) == -1) |
98 | FAIL_EXIT1 ("nftw failed." ); |
99 | |
100 | /* Verify that ldconfig can run with a truncated |
101 | aux-cache and doesn't crash. */ |
102 | struct support_capture_subprocess result; |
103 | result = support_capture_subprocess (callback: execv_wrapper, closure: args); |
104 | support_capture_subprocess_check (&result, context: "execv" , status_or_signal: 0, allowed: sc_allow_none); |
105 | support_capture_subprocess_free (&result); |
106 | } |
107 | |
108 | free (ptr: prog); |
109 | return 0; |
110 | } |
111 | |
112 | #include <support/test-driver.c> |
113 | |