After upgrading glibc from 2.40.9000-37.fc43 to glibc-2.41.9000-1.fc43.x86_64, I experience a failure in fclose() after fread()ing from a character device: $ cat test.c #include <stdio.h> #define handle_error(msg) { perror(msg); return (1); } int main(void) { char buf[1]; FILE *file; if (!(file = fopen("/dev/zero", "rb"))) handle_error("fopen"); if (fread(buf, sizeof(buf[0]), 1, file) < 1) handle_error("fread"); if (fclose(file)) handle_error("fclose"); return(0); } $ gcc -Wall -pedantic -O0 -g test.c $ ./a.out fclose: Invalid argument If I replace /dev/zero with /dev/urandom, it also fails. If I replace the file name with an existing regular file, e.g. /etc/hosts, it passes. If I comment out the fread() call, it also passes. Either I miss something obvious, or there is some bug in glibc. It happens also with the latest glibc-2.41.9000-8.fc43.x86_64. First I suspected kernel, but syscalls looks all right: $ strace -v -- ./a.out execve("./a.out", ["./a.out"], ["SHELL=/bin/bash", "HISTCONTROL=ignoredups", "HISTSIZE=1000", "HOSTNAME=fedora-43", "GPG_TTY=/dev/pts/3", "PWD=/tmp", "LOGNAME=test", "COBBLER_SERVER=lab.rhts.englab.b"..., "HOME=/home/test", "LANG=en_US.UTF-8", "LS_COLORS=rs=0:di=01;34:ln=01;36"..., "TERM=screen.xterm-256color", "LESSOPEN=||/usr/bin/lesspipe.sh "..., "USER=test", "SHLVL=1", "PS1=\\u@\\h:\\w $ ", "DEBUGINFOD_URLS=https://debuginf"..., "DEBUGINFOD_IMA_CERT_PATH=/etc/ke"..., "PATH=/usr/local/bin:/usr/bin:/ho"..., "MAIL=/var/spool/mail/test", "OLDPWD=/home/test/fedora/csnappy"..., "_=/usr/bin/strace"]) = 0 brk(NULL) = 0xc757000 mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f16f8947000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 fstat(3, {st_dev=makedev(0xfc, 0), st_ino=133313, st_mode=S_IFREG|0644, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=96, st_size=46785, st_atime=1744117592 /* 2025-04-08T15:06:32.339597967+0200 */, st_atime_nsec=339597967, st_mtime=1744117591 /* 2025-04-08T15:06:31.203000000+0200 */, st_mtime_nsec=203000000, st_ctime=1744117591 /* 2025-04-08T15:06:31.228000000+0200 */, st_ctime_nsec=228000000}) = 0 mmap(NULL, 46785, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f16f893b000 close(3) = 0 openat(AT_FDCWD, "/lib64/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0p7\0\0\0\0\0\0"..., 832) = 832 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 fstat(3, {st_dev=makedev(0xfc, 0), st_ino=171910, st_mode=S_IFREG|0755, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=4792, st_size=2444256, st_atime=1744117589 /* 2025-04-08T15:06:29.536000000+0200 */, st_atime_nsec=536000000, st_mtime=1743638400 /* 2025-04-03T02:00:00+0200 */, st_mtime_nsec=0, st_ctime=1744117589 /* 2025-04-08T15:06:29.496000000+0200 */, st_ctime_nsec=496000000}) = 0 pread64(3, "\6\0\0\0\4\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0@\0\0\0\0\0\0\0"..., 784, 64) = 784 mmap(NULL, 2034704, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f16f874a000 mmap(0x7f16f88b8000, 479232, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16e000) = 0x7f16f88b8000 mmap(0x7f16f892d000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1e2000) = 0x7f16f892d000 mmap(0x7f16f8933000, 31760, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f16f8933000 close(3) = 0 mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f16f8747000 arch_prctl(ARCH_SET_FS, 0x7f16f8747740) = 0 set_tid_address(0x7f16f8747a10) = 40636 set_robust_list(0x7f16f8747a20, 24) = 0 rseq(0x7f16f8747680, 0x20, 0, 0x53053053) = 0 mprotect(0x7f16f892d000, 16384, PROT_READ) = 0 mprotect(0x402000, 4096, PROT_READ) = 0 mprotect(0x7f16f8986000, 8192, PROT_READ) = 0 prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0 munmap(0x7f16f893b000, 46785) = 0 getrandom("\xaf\x44\xe9\x36\x66\x9d\x8b\xa7", 8, GRND_NONBLOCK) = 8 brk(NULL) = 0xc757000 brk(0xc778000) = 0xc778000 openat(AT_FDCWD, "/dev/zero", O_RDONLY) = 3 fstat(3, {st_dev=makedev(0, 0x6), st_ino=6, st_mode=S_IFCHR|0666, st_nlink=1, st_uid=0, st_gid=0, st_blksize=4096, st_blocks=0, st_rdev=makedev(0x1, 0x5), st_atime=1744094012 /* 2025-04-08T08:33:32.143370891+0200 */, st_atime_nsec=143370891, st_mtime=1744094012 /* 2025-04-08T08:33:32.143370891+0200 */, st_mtime_nsec=143370891, st_ctime=1744094012 /* 2025-04-08T08:33:32.143370891+0200 */, st_ctime_nsec=143370891}) = 0 ioctl(3, TCGETS, 0x7fffc0149950) = -1 ENOTTY (Inappropriate ioctl for device) read(3, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096 lseek(3, 0, SEEK_CUR) = 0 close(3) = 0 dup(2) = 3 fcntl(3, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE) fstat(3, {st_dev=makedev(0, 0x18), st_ino=6, st_mode=S_IFCHR|0620, st_nlink=1, st_uid=0, st_gid=5, st_blksize=1024, st_blocks=0, st_rdev=makedev(0x88, 0x3), st_atime=1744117656 /* 2025-04-08T15:07:36+0200 */, st_atime_nsec=0, st_mtime=1744117656 /* 2025-04-08T15:07:36+0200 */, st_mtime_nsec=0, st_ctime=1744110065 /* 2025-04-08T13:01:05.542000000+0200 */, st_ctime_nsec=542000000}) = 0 write(3, "fclose: Invalid argument\n", 25fclose: Invalid argument ) = 25 close(3) = 0 exit_group(1) = ? +++ exited with 1 +++
I'm bisecting this.
Caused by: commit be6818be31e756398e45f70e2819d78be0961223 Author: Joseph Myers <josmyers> Date: Tue Jan 28 20:22:56 2025 +0000 Make fclose seek input file to right offset (bug 12724) I can see what is wrong and will post an upstream patch. Thanks for the report.
Upstream patch posted: [PATCH] libio: Synthesize ESPIPE error if lseek returns 0 after reading bytes <https://inbox.sourceware.org/libc-alpha/87cydmpq0h.fsf@oldenburg.str.redhat.com/>
The fix should have landed in Rawhide through https://bodhi.fedoraproject.org/updates/FEDORA-2025-778b706f66 Specifically: - libio: Synthesize ESPIPE error if lseek returns 0 after reading bytes