Bug 240573 - sysctl() does not return ENOMEM but silently truncate returned data
Summary: sysctl() does not return ENOMEM but silently truncate returned data
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: freebsd-bugs mailing list
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-09-14 00:28 UTC by rozhuk.im
Modified: 2019-11-03 17:18 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description rozhuk.im 2019-09-14 00:28:30 UTC
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().