garg@mandrill.CWRU.Edu (Dev Datt Garg) (01/18/88)
Hi Friends, I am working on my M.S. Thesis. I am extending the command language of GDB(Gnu Debugger) for Sun3 running BSD unix. One of the features I am trying to add is to be able to save the context of a process at any point in the user program, so that at later stage program can be restarted from that point. I have got some success in doing that. I am having a problem, If the program, which I am debugging has some files open. I am unable to know which files were open, so that the status of those files can be restored. Of course one of the things I am saving is a user structure, which contains most of the info regarding process context. I somehow want to recover the names of the open files from this struct or from anywhere else. I will highly appreciate if some Guru could tell me some way of achieving that. Thanx in advance. usenet: {decvax,cbosgd,sun}!mandrill!garg Dev Datt Garg csnet: garg@mandrill.CWRU.edu arpa: garg@mandrill.CWRU.edu -- usenet: {decvax,cbosgd,sun}!mandrill!garg Dev Datt Garg csnet: garg@mandrill.CWRU.edu arpa: garg@mandrill.CWRU.edu
ram%shukra@Sun.COM (Renu Raman, Sun Microsystems) (01/19/88)
In article <2346@mandrill.CWRU.Edu>, garg@mandrill.CWRU.Edu (Dev Datt Garg) writes: > > Hi Friends, > I am working on my M.S. Thesis. I am extending the command language of > GDB(Gnu Debugger) for Sun3 running BSD unix. One of the features I am trying > to add is to be able to save the context of a process at any point in the > user program, so that at later stage program can be restarted from that point. > I have got some success in doing that. I am having a problem, If the program, > which I am debugging has some files open. I am unable to know which files were > open, so that the status of those files can be restored. > > Of course one of the things I am saving is a user structure, which > contains most of the info regarding process context. I somehow want to > recover the names of the open files from this struct or from anywhere else. > I will highly appreciate if some Guru could tell me some way of achieving > that. > Thanx in advance. > > usenet: {decvax,cbosgd,sun}!mandrill!garg Dev Datt Garg > csnet: garg@mandrill.CWRU.edu > arpa: garg@mandrill.CWRU.edu Read the report "An unix 4.2 BSD implementation of Process suspension and resumption" by A.Y. Chen (Jun 86 , U. of Ill, report no. UiUCDCS-R-86-1286 ). At the end of the report is included the source code which includes some diffs to the kernel - user structure, kern_descrip.c, kern_exec.c, ufs_nami.c. I guess the objective there was to checkpoint a process and save the process state in a stable storage and restore it when needed. An implementation was done on SYS V too. Just send mail to Erna Amerman (erna@a.cs.uiuc.edu) and ask for report DCS-R-86-1286. --------------------- Renukanthan Raman ARPA:ram@sun.com Sun Microsystems UUCP:{ucbvax,seismo,hplabs}!sun!ram M/S 5-40, 2500 Garcia Avenue, Mt. View, CA 94043
narayan@tandem.UUCP (narayan mohanram TCP/IP Conso) (01/21/88)
In article <2346@mandrill.CWRU.Edu>, garg@mandrill.CWRU.Edu (Dev Datt Garg) writes: > One of the features I am trying > to add is to be able to save the context of a process at any point in the > user program, so that at later stage program can be restarted from that point. > I have got some success in doing that. I am having a problem, If the program, > which I am debugging has some files open. I am unable to know which files were > open, so that the status of those files can be restored. The conovoluted way to do that would be to look at the inode (incore) by looking at u.u_ofile[x]->f_inode. This can then give you the major/minor device number of the file that is open (You can also get the seek pointers). You then have to search the mount table, and find where this major/minor device is mounted, and then search the file system for the necessary inode number. You can thus establish a path to the file. Alternately you can write a simple character device driver that will open a file given inode information. You can thus supply this as an ioctl to the program that can then munge the internals of the kernel data structures (XXX). Narayan Mohanram (narayan@ati.tis.llnl.gov)
ok@quintus.UUCP (Richard A. O'Keefe) (01/21/88)
In article <339@tandem.UUCP>, narayan@tandem.UUCP (narayan mohanram TCP/IP Conso) writes: > In article <2346@mandrill.CWRU.Edu>, garg@mandrill.CWRU.Edu (Dev Datt Garg) writes: > > > One of the features I am trying > > to add is to be able to save the context of a process at any point in the > > user program, so that at later stage program can be restarted from that point. > > I have got some success in doing that. I am having a problem, If the program, > > which I am debugging has some files open. I am unable to know which files were > > open, so that the status of those files can be restored. > There is a moderately straightforward method which doesn't involve kernel hacking. Basically, the original poster has {revised GNU debugger} \ {child process} and wants to maintain, in the debugger, a table {child's file descriptor number} --> {symbolic file name}. The answer is simple: The child already contains stubs for all the system calls it uses. The debugger knows which system calls can allocate and deallocate file descriptors. The debugger places special break-points on each appropriate stub (it has the symbol table for the child, so knows where all the stubs are). Note that you have to track chdir() too! The debugger initialises its table when it starts the child. (I don't know the GNU debugger, but presumably you can say e.g. run <input >output 2>error 12<another-file and the debugger knows perfectly well which fd goes with what symbolic file name at this point, because it put them there.) Then, whenever the child executes open() or whatever, the debugger adds the appropriate entry to its table, and whenever the child executes close() or whatever, the debugger deletes the corresponding entry from its table. None of this requires the debugger to know anything that a debugger doesn't have to know anyway, nor does it require special devices or system calls not already provided or not available to ordinary users. In fact, apart from ptrace() as such, it isn't even UNIX-specific. There is a problem, of course: what happens if a file has been deleted, renamed, or otherwise altered since the checkpoint was saved? But this approach is actually better than scanning the disc, because although a file can have any number of names in UNIX, with this approach you know >>the name the child used<<. So if something has gone wrong, at least the user stands a chance of identifying the file name.
rsalz@bbn.com (Rich Salz) (01/21/88)
>In article <2346@mandrill.CWRU.Edu>, garg@mandrill.CWRU.Edu (Dev Datt Garg) writes: > I have got some success in doing that. I am having a problem, If the program, > which I am debugging has some files open. I am unable to know which files were > open, so that the status of those files can be restored. In the general case you can't do it. For example: char *p = "/tmp/mail1234"; freopen(p, "r", stdin); unlink(p); ... (I've got some highly useful programs that do this.) If you can get the major/minor device numbers, you can rummage around to find the inode, then work back from that, but all this was hashed out here about six months ago and the conclusion was: good luck, you won't get them all. /r$ -- For comp.sources.unix stuff, mail to sources@uunet.uu.net.
gallmeis@wasp.cs.unc.edu (Bill Gallmeister) (01/28/88)
In article <7124@ncoast.UUCP> allbery@ncoast.UUCP (Brandon Allbery) writes: >As quoted from <339@tandem.UUCP> by narayan@tandem.UUCP (narayan mohanram TCP/IP Conso): >+--------------- >| In article <2346@mandrill.CWRU.Edu>, garg@mandrill.CWRU.Edu (Dev Datt Garg) writes: >| > to add is to be able to save the context of a process at any point in the >| > user program, so that at later stage program can be restarted from that point. >| >| Alternately you can write a simple character device driver that will >| open a file given inode information. You can thus supply this as >| an ioctl to the program that can then munge the internals of the >| kernel data structures (XXX). >+--------------- > >That last sounds like a security disaster to me...<etc> I promised myself I wouldn't get into this. So here I am. What's wrong with rewriting the library routines so they squirrel away file names + file statistics, then pass them over when the process gets migrated? It really seems that the mapping of filename to inode can be done outside of the kernel. And therefore should be. Run the processes under control of a "puppet master" that knows how to do these things. Much better than modifying the kernel, although it doesn't look quite as good on the resume... this kind of reminds me of someone who asked how to get the size of a malloc'ed block. The answer? "Remember how much you asked for, dimwit!" - bill o --- Bill O. Gallmeister gallmeis@cs.unc.edu "Offer me solutions -- offer me alternatives -- and I decline. It's the end of the world as we know it, and I feel fine."
dmt@ptsfa.UUCP (Dave Turner) (01/28/88)
In article <7124@ncoast.UUCP> allbery@ncoast.UUCP (Brandon Allbery) writes: >As quoted from <339@tandem.UUCP> by narayan@tandem.UUCP (narayan mohanram TCP/IP Conso): >+--------------- >| In article <2346@mandrill.CWRU.Edu>, garg@mandrill.CWRU.Edu (Dev Datt Garg) writes: >| > to add is to be able to save the context of a process at any point in the >| > user program, so that at later stage program can be restarted from that point. >| I almost hate to suggest this but since you are trying to add a new feature, why don't you simply modify open() to save the filename and current directory name. It should be easy to hide the names along with the associated file descriptors and avoid all the trouble and ambiguity of trying to match the inode number to the proper filename. -- Dave Turner 415/542-1299 {ihnp4,lll-crg,qantel,pyramid}!ptsfa!dmt
hansen@mips.COM (Craig Hansen) (01/29/88)
In article <904@thorin.cs.unc.edu>, gallmeis@wasp.cs.unc.edu (Bill Gallmeister) writes: > this kind of reminds me of someone who asked how to get the size of a malloc'ed block. > The answer? "Remember how much you asked for, dimwit!" Actually, if free() is going to be able to deallocate the space, the dimwit malloc() ought to be salting the size away somewhere, since free doesn't depend on the dimwit programmer telling it how big the block is. With that in mind, there's no conceivable reason why there isn't an msize() function for us comp.unix.dimwits. -- Craig Hansen Manager, Architecture Development MIPS Computer Systems, Inc. ...{ames,decwrl,prls}!mips!hansen or hansen@mips.com 408-991-0234
kent@tifsie.UUCP (Russell Kent) (01/29/88)
in article <2120@ttrdc.UUCP>, levy@ttrdc.UUCP (Daniel R. Levy) says: [ deleted lines - RAK ] } #> Alternately you can write a simple character device driver that will } #> open a file given inode information. You can thus supply this as } #> an ioctl to the program that can then munge the internals of the } #> kernel data structures (XXX). } } This if not done carefully would pose a security hole. Either this form } of access should only be allowed to the superuser (perhaps by making the } special device be readable/writeable only by the root, a la /dev/mem } and block devices for disks) or access should only be permitted for files } which could also be opened in the desired manner by pathname. } -- } Dan Levy Wouldn't "access ... permitted for files which could also be opened in the desired manner by pathname" imply that the kernel would have to search the file system directory tree for an accessible path? Do you _really_ want to put this sort of thing into the kernel (can you see the kernel spending millions of machine cycles scanning the disk drive??) -- Russell Kent Phone: +1 214 995 3501 Texas Instruments UUCP address: P.O. Box 655012 MS 3635 ...!convex!smu!tifsie!kent Dallas, TX 75265 ...!ut-sally!im4u!ti-csl!tifsie!kent
brett@wjvax.UUCP (Brett Galloway) (01/30/88)
>In article <1427@mips.mips.COM> hansen@mips.COM (Craig Hansen) writes: >>In article <904@thorin.cs.unc.edu>, gallmeis@wasp.cs.unc.edu (Bill Gallmeister) writes: >>> this kind of reminds me of someone who asked how to get the size of a malloc'ed block. >>> The answer? "Remember how much you asked for, dimwit!" >> >>Actually, if free() is going to be able to deallocate the space, the >>dimwit malloc() ought to be salting the size away somewhere, since >>free doesn't depend on the dimwit programmer telling it how big the >>block is. With that in mind, there's no conceivable reason why there >>isn't an msize() function for us comp.unix.dimwits. I don't agree that only dimwits require this information. All implementations of malloc() will give you *at least* the amount of room you asked for; many will give you more (BSD is reputed to allocate in powers of 2). I have several applications where I could make more efficient use of space if I knew how much space malloc() actually gave me. This occurs whenever I am malloc()'ing a buffer that I may want to realloc() later because it filled up; knowing how much malloc() actually gave me could save both malloc space and run-time. I suggested this on comp.lang.c a while back as a useful, portable enhancement to any malloc() package, but got no response. I have redirected follow-ups back to comp.lang.c because it seems of general interest to users of standard C libraries with a malloc() routine. -- ------------- Brett D. Galloway {ac6,calma,cerebus,isi,isieng,pyramid,tymix}!wjvax!brett
eichin@athena.mit.edu (Mark W. Eichin) (01/30/88)
In article <1427@mips.mips.COM> hansen@mips.COM (Craig Hansen) writes: >In article <904@thorin.cs.unc.edu>, gallmeis@wasp.cs.unc.edu (Bill Gallmeister) writes: >> The answer? "Remember how much you asked for, dimwit!" > >Actually, if free() is going to be able to deallocate the space, the >dimwit malloc() ought to be salting the size away somewhere, since Exactly: a DIMWIT malloc might be allocating the exact amount of space asked for; this then requires a full copy on any realloc and causes other performance problems. A fast malloc might just manage the heap as a set of blocks of power of 2 sizes, which are near (modulo some hysteresis value) the actual size requested via malloc(). Thus free can just relink the block onto a chain, never knowing what the ACTUAL size was, msize() not being inherent in the block structure. This is more efficient than a serial allocator when there is much thrashing of the memory pool (eg. a lisp-like system or an editor) since you can just make the block available for quick re-use. {If anyone knows really precise results of this type, can you point me at them? We have ``proven'' them here in a small way, but real results might make a good thesis project...} The GNU Emacs malloc (derived from several places) did this, with the debugging option of keeping msize in the block header, and storing a magic number at each end of the block, which it could check at free or realloc time (simple bounds checking.) I enhanced this for a project here to fill the ENTIRE `extra' area with magic numbers, and then scanning them for error at the appropriate times... It also trashes freed blocks (with a magic number) and makes sure they aren't written in when they next get reused. These things have helped trap software bugs that make 4.nBSD malloc corrupt the memory pool, making debugging impossible... This project actually needed msize, so we left it always running with the first level of bounds checking (though we haven't gotten it stable enough for non alpha users, so we really run with full checking most of the time.) If it ran well, we would just hook an msize() onto what ever allocator we ended up with, so we could actually port the software. msize() was convenient enough (we were using `intelligent arrays') that we wanted to add it at the allocator level, for performance, rather than including it in the higher level structures. In summary: there IS a reason that there isn't an msize() by default, it is a constraint upon the allocator which can be overly restrictive in certain usage patterns. Mark Eichin <eichin@athena.mit.edu> SIPB Member & Project Athena ``Watchmaker''
brett@wjvax.UUCP (Brett Galloway) (02/01/88)
In article <2672@bloom-beacon.MIT.EDU> eichin@athena.mit.edu (Mark W. Eichin) writes: >>[why isn't there an msize() routine that returns the actual amount of space >>allocated by malloc()?] >In summary: there IS a reason that there isn't an msize() by default, >it is a constraint upon the allocator which can be overly restrictive >in certain usage patterns. I posted the other day another reason for making such a feature (a feature to return the *actual* malloc()'d size available to the user) available. I neglected to mention that I was thinking in terms of a variant malloc() that returned the actual size as well as the character pointer. I agree that an after-the-fact msize() routine might be overly expensive. However, it seems to me that a variant malloc() that reported what it actually allocated could be had for free. I mean a routine like char *mallocsize(size,actual) unsigned size; unsigned *actual; (with types ala BSD -- fill in your own types). If the implementor were lazy, or forgot to implement it at all, he (or you) could just use char *mallocsize(size,actual) unsigned size; unsigned *actual; { *actual = size; return(malloc(size)); } -- ------------- Brett D. Galloway {ac6,calma,cerebus,isi,isieng,pyramid,tymix}!wjvax!brett
kent@tifsie.UUCP (Russell Kent) (02/02/88)
in article <904@thorin.cs.unc.edu>, gallmeis@wasp.cs.unc.edu (Bill Gallmeister) says: > I promised myself I wouldn't get into this. So here I am. What's wrong > with rewriting the library routines so they squirrel away file names + > file statistics, then pass them over when the process gets migrated? It > really seems that the mapping of filename to inode can be done outside > of the kernel. And therefore should be. Run the processes under control > of a "puppet master" that knows how to do these things. Much better than > modifying the kernel, although it doesn't look quite as good on the resume... > Bill O. Gallmeister gallmeis@cs.unc.edu Migrating the pathname to inode number translation from the kernel into the user space would: 1. Eliminate some of the file access security afforded by the present scheme. 2. Destroy the orthogonality of the physical resource naming Explanations: As we all know, the kernel uses the execute bit (x bit) of a directory to allow "search" permission, as opposed to "read" permission which is still handled by the read bit (r bit). Presently, it is possible to construct to path types which I will call "under glass", and "blackhole." An "under glass" pathname is one in which the terminal directory (ie next-to-last pathname component) is readable, but not searchable. This allows programs to see that the file exists, but does not allow it to open the file (the clever reader will note that this is easily accomplished with the permissions on the file itself -- I never said that this was a _useful_ technique 8-). A "blackhole" pathname is on in which at least one of the directories in the pathname is searchable but not readable. This allows programs to access the file _if_ they already know the pathname. Since the directories are not readable, then (with some careful naming) the file is effectively inaccessible unless the name is already known. This can be used where the other security techniques provided by the system are ineffective, awkward, or have potentially unpleasant side-effects. (SA's golden rule: every setuid root program is a potential disaster) These are admittedly esoteric objections; but what about that panacea for nearly all security problems: chroot(). How will you implement this if the user/kernel open is done with inode numbers? (Of course, the _truely_ mischievous user can be dealt with by more extreme measures such as putting his/her home directory on /dev/tape 8-). As for the orthogonality of the name space of physical resources, I can best demonstrate with a question: What is the inode number of /dev/ra0a? Or of /dev/tty03? -- Russell Kent Phone: +1 214 995 3501 Texas Instruments UUCP address: P.O. Box 655012 MS 3635 ...!convex!smu!tifsie!kent Dallas, TX 75265 ...!ut-sally!im4u!ti-csl!tifsie!kent
jc@minya.UUCP (John Chambers) (02/04/88)
In article <1427@mips.mips.COM>, hansen@mips.COM (Craig Hansen) writes: > In article <904@thorin.cs.unc.edu>, gallmeis@wasp.cs.unc.edu (Bill Gallmeister) writes: > > this kind of reminds me of someone who asked how to get the size of a malloc'ed block. > > The answer? "Remember how much you asked for, dimwit!" > > Actually, if free() is going to be able to deallocate the space, the > dimwit malloc() ought to be salting the size away somewhere, since > free doesn't depend on the dimwit programmer telling it how big the > block is. With that in mind, there's no conceivable reason why there > isn't an msize() function for us comp.unix.dimwits. There's another problem you've missed. All too often, I find that I can't remember how much I asked for, because I didn't ask for it. True, if I am writing the whole program, I can keep the size somewhere. But suppose I'm a library routine passed a pointer, and I want to make sure I don't overflow the caller's data block. The turkey didn't pass me its size, so how the @#$*$&%^ am I supposed to discover it? Of course, a good design would always pass a size along with a pointer. Sure, and when you are writing your library sprintf() routine, do you want to go out and modify all the calls in all the software in the world so that there's a size parameter? I mean, sprintf() is specified and cast in a huge chunk of concrete by now. It doesn't include a size field. How is a competent software engineer to guarantee that it doesn't overflow the caller's array? Open files are a similar problem. You can say "Just remember the file name, dimwit." But if you're the poor library routine that has just read garbage from a fd, and you want to give a sensible diagnostic rather than the usual "garbage in input" sort of message, how DO you discover which of the various character strings lying about in memory is the name of that file? Note that it's too late by now to request the file name from the caller; the spec was already approved by management, and the name isn't in your list of parameters. Oh, well, maybe we should just be traditionalists, and not worry about memory faults or useful diagnostics. -- John Chambers <{adelie,ima,maynard,mit-eddie}!minya!{jc,root}> (617/484-6393)
sarge@sting.Berkeley.EDU (Steven Sargent) (02/04/88)
You can (with fair effort) discover the names of many (not all) disk files by fstat'ing the descriptor, then rooting around in directories to find the <name,inumber> translation, then winding up to the root. (getwd(3), or pwd(1) for usg'ers, does something like this, but it depends on being able to start from "." This is somewhat more complicated). You can read the disk -- write a separate program that has readonly permissions for the disk -- being sure that you turn off close-on-exec flags for your fd's before running it. Note: - fails for non-disk files (e.g., pipes); restarting your process in mid-IPC is problematical, anyway; - fails if your process has created, then unlinked, a file (standard trick for creating temp files; on last close, the bits are reclaimed); You may not need read-disk permission (I'm too fuzzy right now to be sure), and just replicate what getwd does; in which case - fails if you don't have read permission on any of the intermediate directories. Salting away the names of files opened by open(2), &c. is ineffective since you can't know the names of files inherited by I/O redirection. I know of at least one implementation in which the full path name associated with u.u_cdir is maintained by the operating system (chdir(), &c. are never "fooled" by symbolic links). I suppose you could do the same thing with filenames ... but that way leads VMS. S.