int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC, getpid() }; if (0 != sysctl(mib, 4, NULL, &buf_size, NULL, 0)) return (errno); buf = malloc(buf, buf_size); newfd = open("/dev/null", O_RDONLY); /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ if (0 != sysctl(mib, 4, buf, &buf_size, NULL, 0)) { if (ENOMEM != errno) { free(buf) return (errno); } } This code should fail, but it fill buf with struct kinfo_file, and there is no newfd. No fail, no error code set, silent data truncation. Probably sys/kern/kern_descrip.c: export_kinfo_to_sb() ... if (efbuf->remainder < kif->kf_structsize) { /* Terminate export. */ efbuf->remainder = 0; return (0); } ... should return here ENOMEM!? I see hack to avoid missing fd for that in lib/libutil/kinfo_getfile.c: kinfo_getfile(): ... len = len * 4 / 3; ... Same for kern.ipc.posix_shm_list. sys/kern/uipc_shm.c: sysctl_posix_shm_list() if (req->oldptr != NULL && kif.kf_structsize + curlen > req->oldlen) break; error = ENOMEM; - before break missed. hack: usr.bin/posixshmcontrol/posixshmcontrol.c: list_shm() sys/kern/kern_proc.c: kern_proc_vmmap_out() ... /* Halt filling and truncate rather than exceeding maxlen */ if (maxlen != -1 && maxlen < kve->kve_structsize) { error = 0; vm_map_lock_read(map); break; ... error = ENOMEM;? And probably other places where exist buf size check and exit from loop before call sbuf_bcat().
At least kern.ipc.posix_shm_list and kern_proc_vmmap_out continue silently truncate data.
For kern_proc_vmmap_out(), we have: /* Halt filling and truncate rather than exceeding maxlen */ if (maxlen != -1 && maxlen < kve->kve_structsize) { error = 0; vm_map_lock_read(map); break; } else if (maxlen != -1) maxlen -= kve->kve_structsize; if (sbuf_bcat(sb, kve, kve->kve_structsize) != 0) error = ENOMEM; Note that when filling out info for the KERN_PROC_VMMAP sysctl, we have maxlen == -1. So we just end up calling sbuf_bcat(), which will indeed return an error if the output buffer is too small. I think there is no bug there. I think you are right about sysctl_posix_shm_list(), we should return an error if req->oldptr is non-NULL and the buffer is truncated. I believe it would be sufficient to just remove the referenced check, sbuf_bcat() will signal an error.
https://reviews.freebsd.org/D33912
(In reply to Mark Johnston from comment #2) > For kern_proc_vmmap_out(), we have I hope current/stable code handle it :) PR was opened mostly because of KERN_PROC_FILEDESC, other things was found by quick search, I do not use/test it. Probably there is more places/syscals that may silently truncate data. > https://reviews.freebsd.org/D33912 Thanks!
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=dc7526170d4cc62f35bafb25dd026399c612ed5b commit dc7526170d4cc62f35bafb25dd026399c612ed5b Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2022-01-17 13:33:05 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2022-01-17 13:35:19 +0000 posixshm: Report output buffer truncation from kern.ipc.posix_shm_list PR: 240573 Reviewed by: kib MFC after: 1 week Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D33912 sys/kern/uipc_shm.c | 3 --- 1 file changed, 3 deletions(-)
(In reply to Ivan Rozhuk from comment #4) I looked through the other KERN_PROC sysctls and did not find any occurrences of the problem. I could have missed something of course. kern_proc_filedesc_out() is a bit special. It is used to provide info for an ELF coredump note as well as for KERN_PROC_FILEDESC. During a coredump, the function is called twice: once to get the note size, and once to actually fill out the note. NT_PROCSTAT_FILES notes contain path names. So, if a referenced file is renamed between the two calls to kern_proc_filedesc_out(), we potentially have to truncate the new path to avoid corrupting the core dump. The coredump code can reserve PATH_MAX bytes for each path to avoid this problem (this is enabled by the kern.coredump_pack_fileinfo sysctl), but that ends up bloating core dump sizes if a large number of files is open. Most other sysctls don't have such a requirement, and so are less likely to have silent truncation bugs.
A commit in branch stable/13 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=9795d85d2e73472e65d48b27a3c684f130722009 commit 9795d85d2e73472e65d48b27a3c684f130722009 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2022-01-17 13:33:05 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2022-01-24 14:16:37 +0000 posixshm: Report output buffer truncation from kern.ipc.posix_shm_list PR: 240573 Reviewed by: kib Sponsored by: The FreeBSD Foundation (cherry picked from commit dc7526170d4cc62f35bafb25dd026399c612ed5b) sys/kern/uipc_shm.c | 3 --- 1 file changed, 3 deletions(-)
I'm not aware of any other instances of sysctls truncating output buffers, please feel free to reopen if you find one.