From owner-freebsd-bugs Sun Jun 18 4:40: 6 2000 Delivered-To: freebsd-bugs@freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.ORG [204.216.27.21]) by hub.freebsd.org (Postfix) with ESMTP id 5AC4E37B9B7 for ; Sun, 18 Jun 2000 04:40:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.9.3/8.9.2) id EAA68052; Sun, 18 Jun 2000 04:40:01 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from segfault.kiev.ua (segfault.kiev.ua [193.193.193.4]) by hub.freebsd.org (Postfix) with ESMTP id DAF6337B9B7 for ; Sun, 18 Jun 2000 04:34:34 -0700 (PDT) (envelope-from netch@nn.kiev.ua) Received: from nn.kiev.ua (nn.kiev.ua [193.193.193.203]) by segfault.kiev.ua (8) with ESMTP id ONG90624 for ; Sun, 18 Jun 2000 14:34:26 +0300 (EEST) (envelope-from netch@nn.kiev.ua) Received: (from netch@localhost) by nn.kiev.ua (8.9.3/8.9.3) id OAA02185; Sun, 18 Jun 2000 14:34:27 +0300 (EEST) (envelope-from netch) Message-Id: <200006181134.OAA02185@nn.kiev.ua> Date: Sun, 18 Jun 2000 14:34:27 +0300 (EEST) From: netch@segfault.kiev.ua (Valentin Nechayev) Reply-To: netch@segfault.kiev.ua To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.2 Subject: kern/19363: Do allow processes know about their file descriptors, reliably & efficiently Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.org >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