Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Jun 2000 14:34:27 +0300 (EEST)
From:      netch@segfault.kiev.ua (Valentin Nechayev)
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/19363: Do allow processes know about their file descriptors, reliably & efficiently
Message-ID:  <200006181134.OAA02185@nn.kiev.ua>

next in thread | raw e-mail | index | archive | help

>Number:         19363
>Category:       kern
>Synopsis:       Do allow processes know about their file descriptors, reliably & efficiently
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jun 18 04:40:01 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     netch@netch.kiev.ua (Valentin Nechayev)
>Release:        FreeBSD
>Organization:
Kiev
>Environment:

FreeBSD

>Description:

The goal is described in synopsis field. I suppose it is really useful now.
Reasons (mostly in field of security):

1) On exec(), caller can pass any descriptor to called program. This can
be used for DoS attacks: i.e., sendmail slowly sends a letter and locks
some file system from unmounting. (The situation is semi phantastic,
but only "semi".)

2)

==={
root@nn:~##sysctl -a | grep chroot
kern.chroot_allow_open_directories: 1
root@nn:~##
===}

This is, of course, good idea ;|, but it is correct to provide more
flexibility for programs, isn't it? :)

3) Some programs (sendmail, uucico) try to close all extra files, but
they do it ugly and non-reliably (getdtablesize() does not report possible
descriptors which are more that soft rlimit). This ugly method should be
changed to something similar to
==={
	while ((o = getfd(GETFD_NEXT, 2)) != -1)
		close(o);
===}
and at least added to most setuid/setgid programs, for safety sake.

>How-To-Repeat:

;)

>Fix:

Add syscall with following implementation.

=== cut here ===
--- src/include/unistd.h.orig	Sat Jun 17 22:56:11 2000
+++ src/include/unistd.h	Sat Jun 17 22:57:39 2000
@@ -134,6 +134,7 @@
 #endif
 int	 getdomainname __P((char *, int));
 int	 getdtablesize __P((void));
+int	 getfd __P((int, int));
 int	 getgrouplist __P((const char *, int, int *, int *));
 long	 gethostid __P((void));
 int	 gethostname __P((char *, int));
--- kern_descrip.c.orig	Fri Jun 16 00:05:49 2000
+++ kern_descrip.c	Sat Jun 17 23:18:40 2000
@@ -124,6 +124,49 @@
 }
 
 /*
+ * Query used descriptors
+ */
+#ifndef _SYS_SYSPROTO_H_
+struct getfd_args {
+	int query;
+	int param;
+};
+#endif
+int
+getfd(p, uap)
+	struct proc *p;
+	struct getfd_args *uap;
+{
+	register struct filedesc *fdp = p->p_fd;
+	register int i;
+	if (uap->query == GETFD_NEXT) {
+		i = uap->param + 1;
+		if (i < 0)
+			i = 0;
+		for (; i < fdp->fd_nfiles; i++) {
+			if (fdp->fd_ofiles[i] != NULL) {
+				p->p_retval[0] = i;
+				return (0);
+			}
+		}
+		return (EBADF);
+	}
+	if (uap->query == GETFD_PREV) {
+		i = uap->param - 1;
+		if (i < 0 || i >= fdp->fd_nfiles)
+			i = fdp->fd_nfiles - 1;
+		for (; i >= 0; i--) {
+			if (fdp->fd_ofiles[i] != NULL) {
+				p->p_retval[0] = i;
+				return (0);
+			}
+		}
+		return (EBADF);
+	}
+	return (EINVAL);
+}
+
+/*
  * Duplicate a file descriptor to a particular value.
  */
 #ifndef _SYS_SYSPROTO_H_
--- src/sys/kern/syscalls.master.orig	Sun Jun 18 14:16:27 2000
+++ src/sys/kern/syscalls.master	Sun Jun 18 14:17:07 2000
@@ -520,3 +520,4 @@
 			    int nchanges, struct kevent **changelist, \
 			    int nevents, struct kevent *eventlist, \
 			    struct timespec *timeout); }
+364	STD	BSD	{ int getfd( int query, int param); }
--- src/sys/sys/unistd.h.orig	Wed May 10 08:16:11 2000
+++ src/sys/sys/unistd.h	Sat Jun 17 23:00:49 2000
@@ -219,6 +219,12 @@
 #define RFLINUXTHPN     (1<<16) /* do linux clone exit parent notification */
 #define RFPPWAIT	(1<<31) /* parent sleeps until child exits (vfork) */
 
+/*
+ * getfd() queries
+ */
+#define GETFD_NEXT	0
+#define GETFD_PREV	1
+
 #endif /* !_POSIX_SOURCE */
 
 #endif /* !_SYS_UNISTD_H_ */
=== end cut ===

Selected syscall number, of course, does not matter.;) Iteration in both
upper and lower should be sufficient for first time. Possible progress
for next extension may be adding filter on f_type field value of struct file.

PS. Possibly, MPSAFE can be added to getfd() syscall description.

--
NVA

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200006181134.OAA02185>