Bug#965191: libgdbm6: gdbm_reorganize() breaks later use in same process

2020-07-20 Thread Philipp Marek

DrNick on #kernelnewbies mentioned that on mmap() isn't cleaned up:

698118 14:52:47.634488 mmap(NULL, 16384, PROT_READ|PROT_WRITE, 
MAP_SHARED, 4, 0) = 0x7f0467ea2000


That seems to keep the fd open, and so the lock persists...

So it's a libgdbm error.



Bug#965191: libgdbm6: gdbm_reorganize() breaks later use in same process

2020-07-19 Thread Philipp Marek

Same behaviour with linux-image-amd64=5.7.6-1



Bug#965191: libgdbm6: gdbm_reorganize() breaks later use in same process

2020-07-17 Thread Philipp Marek
Package: libgdbm6
Version: 1.18.1-5
Severity: normal

I think this is a kernel issue, but I'll report against libgdbm6 first to 
have my reasoning checked.

Given this program:

#include 
#include 
int main (int argc, char *args[])
{
GDBM_FILE g;
(void) argc;
(void) args;

g = gdbm_open("/tmp/db", 0, GDBM_NEWDB, 0777, NULL);

gdbm_reorganize(g);
gdbm_close(g);

g = gdbm_open("/tmp/db", 0, GDBM_WRCREAT, 0777, 
NULL);
printf("opened as %p, %d\n", g, errno);
if (g)
gdbm_close(g);
return 0;
}

Building via "gcc a.c -lgdbm" and then stracing shows that the second 
gdbm_open() call returns NULL because flock() says EAGAIN (see attachment).

What happens is this:

DB created and locked
698118 14:52:47.633361 openat(AT_FDCWD, "/tmp/db", O_RDWR|O_CREAT, 0777) = 3
698118 14:52:47.633570 flock(3, LOCK_EX|LOCK_NB) = 0
Tmp file created and locked
698118 14:52:47.634086 openat(AT_FDCWD, "/tmp/db.pRQDFD", 
O_RDWR|O_CREAT|O_EXCL, 0600) = 4
698118 14:52:47.634176 flock(4, LOCK_EX|LOCK_NB) = 0
Tmp file renamed
698118 14:52:47.635073 rename("/tmp/db.pRQDFD", "/tmp/db") = 0
but OLD file gets unlocked
698118 14:52:47.635124 flock(3, LOCK_UN) = 0
both files get close()d
698118 14:52:47.635157 close(3) = 0
698118 14:52:47.635736 close(4) = 0
new file gets opened and fails
698118 14:52:47.635867 openat(AT_FDCWD, "/tmp/db", O_RDWR|O_CREAT, 0777) = 3
698118 14:52:47.635949 flock(3, LOCK_EX|LOCK_NB) = -1 EAGAIN (Die Ressource 
ist zur Zeit nicht verfügbar)


IMO the close(4) should drop the lock on the temporary (now renamed to 
target name) file, so the next flock() should work.
(That's why I believe it's a kernel issue.)

Is my reasoning sound, or should libgdbm unlock the new file as well?


I've got a tmpfs here, but that shouldn't matter:

none on /tmp type tmpfs (rw,relatime,size=4194304k)


Thanks for your patience and help!


-- System Information:
Debian Release: bullseye/sid
  APT prefers testing
  APT policy: (990, 'testing'), (500, 'unstable-debug'), (500, 
'testing-debug'), (500, 'unstable'), (500, 'stable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 5.6.0-2-amd64 (SMP w/8 CPU threads)
Kernel taint flags: TAINT_WARN
Locale: LANG=de_AT.UTF-8, LC_CTYPE=de_AT.UTF-8 (charmap=UTF-8), 
LANGUAGE=de_AT:de
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages libgdbm6 depends on:
ii  libc6  2.30-8

libgdbm6 recommends no packages.

Versions of packages libgdbm6 suggests:
ii  gdbm-l10n  1.18.1-5

-- no debconf information

-- 
698118 14:52:47.631034 execve("./a.out", ["./a.out"], 0x7ffe96712530 /* 68 vars 
*/) = 0
698118 14:52:47.631420 brk(NULL)= 0x5593b18d6000
698118 14:52:47.631493 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (Datei 
oder Verzeichnis nicht gefunden)
698118 14:52:47.631758 openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) 
= 3
698118 14:52:47.631856 fstat(3, {st_mode=S_IFREG|0644, st_size=215581, ...}) = 0
698118 14:52:47.631910 mmap(NULL, 215581, PROT_READ, MAP_PRIVATE, 3, 0) = 
0x7f0467e75000
698118 14:52:47.631957 close(3) = 0
698118 14:52:47.632017 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libgdbm.so.6", 
O_RDONLY|O_CLOEXEC) = 3
698118 14:52:47.632078 read(3, 
"\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\208\0\0\0\0\0\0"..., 832) = 832
698118 14:52:47.632119 fstat(3, {st_mode=S_IFREG|0644, st_size=59416, ...}) = 0
698118 14:52:47.632173 mmap(NULL, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0467e73000
698118 14:52:47.632242 mmap(NULL, 61496, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 
3, 0) = 0x7f0467e63000
698118 14:52:47.632301 mmap(0x7f0467e66000, 32768, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x3000) = 0x7f0467e66000
698118 14:52:47.632360 mmap(0x7f0467e6e000, 12288, PROT_READ, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xb000) = 0x7f0467e6e000
698118 14:52:47.632403 mmap(0x7f0467e71000, 8192, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xd000) = 0x7f0467e71000
698118 14:52:47.632466 close(3) = 0
698118 14:52:47.632505 openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", 
O_RDONLY|O_CLOEXEC) = 3
698118 14:52:47.632558 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0 
o\2\0\0\0\0\0"..., 832) = 832
698118 14:52:47.632607 fstat(3, {st_mode=S_IFREG|0755, st_size=1831600, ...}) = 0
698118 14:52:47.632651 mmap(NULL, 1844568, PROT_READ, 
MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f0467ca
698118 14:52:47.632724 mmap(0x7f0467cc5000, 1351680, PROT_READ|PROT_EXEC, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x25000) = 0x7f0467cc5000
698118 14:52:47.632769 mmap(0x7f0467e0f000, 303104, PROT_READ, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16f000) = 0x7f0467e0f000
698118 14:52:47.632810 mmap(0x7f0467e59000, 24576, PROT_READ|PROT_WRITE,