glnx_shutil_mkdir_p_at assert()s when a component of the path to be created is a broken symlink
Running the following program:
static void
test_mkdir_p_broken_symlink (void)
{
_GLNX_TEST_DECLARE_ERROR(local_error, error);
glnx_autofd int dfd = -1;
if (!glnx_ensure_dir (AT_FDCWD, "test", 0755, error))
return;
if (!glnx_opendirat (AT_FDCWD, "test", FALSE, &dfd, error))
return;
if (symlinkat ("nosuchtarget", dfd, "link") < 0)
return (void) glnx_throw_errno_prefix (error, "symlinkat");
/* This should fail with ENOENT or something like that; it shouldn't assert(). */
glnx_shutil_mkdir_p_at (dfd, "link/baz", 0755, NULL, error);
g_assert_error (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND);
g_clear_error (&local_error);
}
Fails with the following internal assertion failure:
ERROR:../glnx-shutil.c:155:mkdir_p_at_internal: assertion failed: (!did_recurse)
(gdb) bt full
#0 0x00007ffff7b468bb in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
set =
{__val = {0, 93824992252968, 93824992330752, 140737351440396, 0, 140737350986041, 140737488345976, 140737350986629, 0, 0, 140737351494435, 0, 140737488346080, 140737349461549, 2048, 1}}
pid = <optimized out>
tid = <optimized out>
#1 0x00007ffff7b31535 in __GI_abort () at abort.c:79
save_stage = 1
act =
{__sigaction_handler = {sa_handler = 0x7ffff7d7581b, sa_sigaction = 0x7ffff7d7581b}, sa_mask = {__val = {140733193388033, 0, 80, 93824992304640, 4841117864268589824, 0, 140737351687550, 140737351494925, 93825305411584, 93824992304640, 0, 0, 4841117864268589824, 93824992252968, 93824992304640, 81}}, sa_flags = -136380928, sa_restorer = 0x7fffffffdd10}
sigs = {__val = {32, 0 <repeats 15 times>}}
#2 0x00007ffff7cebdc3 in () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#3 0x00007ffff7d46baa in g_assertion_message_expr () at /lib/x86_64-linux-gnu/libglib-2.0.so.0
#4 0x0000555555557e16 in mkdir_p_at_internal (dfd=3, path=0x7fffffffdde0 "link/baz", mode=493, cancellable=0x0, error=0x7fffffffdef0)
at ../glnx-shutil.c:155
lastslash = 0x7fffffffdde4 "/baz"
did_recurse = 1
__FUNCTION__ = "mkdir_p_at_internal"
#5 0x0000555555557fcb in glnx_shutil_mkdir_p_at
(dfd=3, path=0x5555555590cb "link/baz", mode=493, cancellable=0x0, error=0x7fffffffdef0) at ../glnx-shutil.c:227
stbuf =
{st_dev = 2500, st_ino = 4841117864268589824, st_nlink = 140737350792944, st_mode = 1431749904, st_uid = 21845, st_gid = 4294960427, __pad0 = 32767, st_rdev = 93824992252010, st_size = 93824992326704, st_blksize = 140737354129808, st_blocks = 13, st_atim = {tv_sec = 93824992242372, tv_nsec = 93824992252010}, st_mtim = {tv_sec = -429496729600, tv_nsec = 93824992326704}, st_ctim = {tv_sec = 3106124509208976, tv_nsec = 140737488346832}, __glibc_reserved = {93824992242420, 140737488346864, 140737488346860}}
buf = 0x7fffffffdde0 "link/baz"
#6 0x00005555555567d4 in test_mkdir_p_broken_symlink () at ../tests/test-libglnx-shutil.c:65
local_error = 0x0
error = 0x7fffffffdef0
dfd = 3
__FUNCTION__ = "test_mkdir_p_broken_symlink"
I found this while working in a container where root's homedir, /root
, is a broken symlink; Flatpak tried to ensure "/root/.local" exists and hit this assertion. This is clearly a very obscure case!