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>
