Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 6 Aug 2002 15:51:03 -0400 (EDT)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        julian@FreeBSD.org
Cc:        jhb@FreeBSD.org, arch@FreeBSD.org
Subject:   Problem with credential for initproc
Message-ID:  <Pine.NEB.3.96L.1020806151131.99671F-100000@fledge.watson.org>

next in thread | raw e-mail | index | archive | help

A few months ago, I committed some changes to the main tree so that the
credential used by init would be divorced from the credential used by
proc0 so that operations performed by init in kernel, and once it hit
userland, could operate using a different credential.  This was required
for the MAC code as kernel threads use a special credential for a number
policies.  I accomplished this by divorcing the initproc->p_ucred from
proc0->p_ucred fairly early in create_init() following the call to
fork1().  This meant that by the time start_init() was invoked from the
now-started init proc, all would be well.  Following the seperation, I
also invoked mac_create_proc1() to make the initproc-specific cred changes
from the version prepared for proc0.  At some point with the KSE changes,
this broke.  I suspect what is going on is the following: 

- fork1() created initproc from thread0/proc0, but now allocates a struct
  thread preemptively.  FIRST_THREAD_IN_PROC(initproc)->td_ucred became a
  reference to proc0->p_ucred.

- initproc credentials are then divorced, so initproc->p_ucred is now a
  reference to its own ucred, where the initproc changes are made, but
  FIRST_THREAD_IN_PROC(initproc)->td_ucred is still pointed at
  proc0->p_ucred.

This meant that until initproc hit userland and the credentials were
reset, start_init() runs using a thread that has proc0 creds instead of
proc1 creds.  It looks like a fix would basically be to sync up the
FIRST_THREAD_IN_PROC(initproc) credentails following the divorcing:

static void
create_init(const void *udata __unused)
{
        struct ucred *newcred, *oldcred;
        int error;

        error = fork1(&thread0, RFFDG | RFPROC | RFSTOPPED, &initproc);
        if (error)
                panic("cannot fork init: %d\n", error);
        /* divorce init's credentials from the kernel's */
        newcred = crget();
        PROC_LOCK(initproc);
        initproc->p_flag |= P_SYSTEM;
        oldcred = initproc->p_ucred;
        crcopy(newcred, oldcred);
#ifdef MAC
        mac_create_proc1(newcred);  
#endif
        initproc->p_ucred = newcred;
X
X	Something needs to happen here so that the thread cred is updated
X
        PROC_UNLOCK(initproc);
        crfree(oldcred);
        mtx_lock_spin(&sched_lock);
        initproc->p_sflag |= PS_INMEM;
        mtx_unlock_spin(&sched_lock);
        cpu_set_fork_handler(FIRST_THREAD_IN_PROC(initproc), start_init, NULL);
}

I.e., somewhere around the X's, something needs to happen.

This then breaks some events involving MAC in start_init(), since file
systems get mounted using the wrong credential, resulting in NFS using the
wrong credential, etc. 

Any suggestions, thoughts, patches?  Do we think there might be a related
problem involving spare threads elsewhere in the kernel, or is this the
only situation where one proc (proc0) changes the credential of another
proc (proc1) resulting in them getting out of sync?

Robert N M Watson             FreeBSD Core Team, TrustedBSD Projects
robert@fledge.watson.org      Network Associates Laboratories


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96L.1020806151131.99671F-100000>