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>