Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 9 Mar 2005 02:13:24 +0200
From:      Giorgos Keramidas <keramida@ceid.upatras.gr>
To:        Andreas Bachmann <bachi@te-clan.ch>
Cc:        freebsd-net@freebsd.org
Subject:   Re: static pid and uid for a socket?
Message-ID:  <20050309001324.GF5173@gothmog.gr>
In-Reply-To: <1110110710.2060.48.camel@notebook.bachi.net>
References:  <1110107067.2060.26.camel@notebook.bachi.net> <20050306113602.GA72592@gothmog.gr> <1110110710.2060.48.camel@notebook.bachi.net>

next in thread | previous in thread | raw e-mail | index | archive | help
On 2005-03-06 13:05, Andreas Bachmann <bachi@te-clan.ch> wrote:
> > AFAIK, this can only be done if the original process calls execve() on a
> > setuid binary and has not marked the socket descriptor as close-on-exec.
>
> i'm developing a gtk+ based equivalent to 'sockstat'.
> when a user is proposed to run a process, which creates a socket, the
> sockstat printout is for example:
>
> USER   COMMAND LOCAL ADDRESS   FOREIGN ADDRESS
> myuser myprog  10.0.0.10:52265 66.102.11.99:123
>
> but, can the displayed kernel socket structure abrupty (by fork() or
> setuid()) change user or process (because xfile.xf_uid or xfile.xf_pid
> changed)?

No.  At least, not by a fork() that creates a new process.

Each process has a (struct filedesc) in its proc structure.  The filedesc
holds information about all the open file descriptors of the process.  The
filedesc is an interface for the list of open (struct file) objects that a
process holds.

A somewhat simplified ASCII-art view is:

    struct proc
  +--------------------+
  |                    |
  |  struct filedesc   |
  |  +--------------+  |
  |  |       X--------------->  struct file
  |  |              |  |        +------------+
  |  |              |  |        |            |
  |  +--------------+  |        |  f_cred --------> struct ucred
  +--------------------+        |            |      +----------+
                                +------------+      |          |
                                                    +----------+

When a new process is created, its filedesc is copied from the filedesc of the
parent process.  The file descriptors of the parent process are copied [1].

The copying points to the very same (struct file) objects, so initially the
credentials (owner) of the open files in the child are set to the same as
those of the parent process.

The parent and child share through their filedesc structures the same (struct
file) object so far.  This is not a problem, since they obviously have the
same credentials anyway.

When one of the processes that share open file objects in this way calls
execve() (or one of its wrappers), the file decriptors are explicitly
"unshared" to avoid security violations [2].

As far as I can tell, the owner of the (struct file *) object is not
used(?), because the file operations accept a ucred pointer and use that
for access checks to the underlying object (vnode, socket, etc).

<disclaimer type="kernel-newbie">
Since I'm only beginning to learn about the way file descriptors work in
FreeBSD, someone who knows the internals better may put it in better
words :-)
</disclaimer>

[1] See revision 1.249 of kern_fork.c, near lines 416-418.

[2] See revision 1.266 of kern_exec.c near lines 461-465.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20050309001324.GF5173>