[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Hurd advocacy? (newb docs)



On Wed, 20 Aug 2003, Patrick Strasser wrote:

> I'd like to write a document in this style. I think I'm quite qualified
> for this task, as I do not really know where to start and how things
> work. Someone else to join the party?
> Perhaps someone is willing to ask some guiding question?

    We'll here's one starting point for you.  I've wondered about the
chain of events that occur when a program makes a call to read().  And
here I think that hello.c from the hurd source would be instructive
(so I've included it parts of it below with my own questions/comments
in C++ // style comments).  Here's my best guess as to what happens
(which is probably --make that surely-- way off the mark).  A call to
read() is really a wrapper around another glibc function called
io_read().  This function sends a message to the root translator with
the name of the target file and a request for a handle to a subroutine
which will be invoked to get the actual data. The root translator
checks the name and sees that it belongs to the ext2fs translator. The
root translator then sends a message to the ext2fs translator to try
and get to the bottom of the situation.  The ext2fs translator sees
that the file is really controled by a translator called hello.  And
a message is passed back up the chain until io_read get a pointer to
the function trivfs_S_io_read.  Now we're starting to get some where.
io_read() then grabs some memory (from which process space I'm not
sure) and tells Mach, "make this call to trivfs_S_io_read for me and
if you get an answer back, shove the data in this chunk of memory".
Mach then dutifully calls the approriate function which fills our
little buffer of memory with the correct bytes.  After the rpc
returns, io_read() examines the contents of the message from Mach
and if everything went swell, it copies the data into the original
buffer which was initially passed to it from read().

   I think most of my confusion comes from how Mach passes messages
back and forth and who controls what memory.  (I probably need a
*beginers* guide to Mach IPC, if someone could point me in right
direction).  I've also wonder how much of the Machisms will remain
after the transition to L4.  Of course its also obvious that I don't
understand what translators get involved when a file name is trying
to be resolved, so I'd be happy for any info about that area.  And
feel free to tell me which of TFM I should R (although I think I've
read most of the easy ones).

And here are my related questions about hello.c and trivfs_S_io_read...

error_t
trivfs_S_io_read (struct trivfs_protid *cred,
          mach_port_t reply, mach_msg_type_name_t reply_type,
          char **data, mach_msg_type_number_t *data_len,
          loff_t offs, mach_msg_type_number_t amount)
{
  struct open *op;

  /* Deny access if they have bad credentials. */
  if (! cred)
    return EOPNOTSUPP;
  else if (! (cred->po->openmodes & O_READ))
    return EBADF;
//What exactly are credentials?  Are they Mach port permissions?
//Are they related to not-logged in users?  Surely it has
//nothing to do with file permissions.  Right?  What happens
//if I don't deny a caller with bad credentials.  Is this a
//security risk?  If I'm always supposed to deny access to callers
//with bad credentials, why doesn't libtrivfs do this for me?
//I though it was a convience wrapper.

  /* Get the offset. */
  op = cred->po->hook;
  if (offs == -1)
    offs = op->offs;

  /* Prune the amount they want to read. */
  if (offs > contents_len)
    offs = contents_len;
  if (offs + amount > contents_len)
    amount = contents_len - offs;

  if (amount > 0)
    {
      /* Possibly allocate a new buffer. */
      if (*data_len < amount)
    {
      *data = mmap (0, amount, PROT_READ|PROT_WRITE, MAP_ANON, 0, 0);
      if (*data == MAP_FAILED)
        return ENOMEM;
    }
//I'm assuming that we might have to allocate more memory because
//Mach messages have a default size which is not big enough and we
//don't want to overflow a buffer.  But what happens if I ignore
//this and write beyond my boundaries.  Who suffers?  Does just this
//translator die?  Or do I take others down with me?  I know that
//if the mmap is replaced with a malloc or an automatic array, that I
//get a 16MB core dump when the segv occurs  And I don't think the
//hello translator is 16MB in size.
//And I a bit confused as to who eventually deallocates this memory.
//Is it Mach?  glibc?

      /* Copy the constant data into the buffer. */
      memcpy ((char *) *data, contents + offs, amount);

      /* Update the saved offset. */
      op->offs += amount;
    }

  *data_len = amount;
  return 0;
}


  And I've can pretty much generate an almost endless supply of
newbie questions if you need more :)


Greg Buchholz



Reply to: