Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 07 May 2001 13:03:40 -0700 (PDT)
From:      John Baldwin <jhb@FreeBSD.org>
To:        Robert Watson <rwatson@FreeBSD.org>
Cc:        arch@FreeBSD.org
Subject:   RE: Patch to eliminate struct pcred
Message-ID:  <XFMail.010507130340.jhb@FreeBSD.org>
In-Reply-To: <Pine.NEB.3.96L.1010506235944.43785B-100000@fledge.watson.org>

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

On 07-May-01 Robert Watson wrote:

> Index: compat/svr4/svr4_misc.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/compat/svr4/svr4_misc.c,v
> retrieving revision 1.30
> diff -u -r1.30 svr4_misc.c
> --- compat/svr4/svr4_misc.c   2001/05/01 08:11:52     1.30
> +++ compat/svr4/svr4_misc.c   2001/05/06 00:43:54
> @@ -1294,13 +1294,8 @@
>                       /*
>                        * Free up credentials.
>                        */
> -                     PROC_LOCK(q);
> -                     if (--q->p_cred->p_refcnt == 0) {
> -                             crfree(q->p_ucred);
> -                             uifree(q->p_cred->p_uidinfo);
> -                             FREE(q->p_cred, M_SUBPROC);
> -                             q->p_cred = NULL;
> -                     }
> +                     crfree(q->p_ucred);
> +                     q->p_ucred = NULL;

Removing the proc lock here looks suspicious, but I think it might mirror a
change I just made to kern_exit.c in wait1(), in which case it is ok.

> Index: kern/kern_exec.c
> ===================================================================
> RCS file: /home/ncvs/src/sys/kern/kern_exec.c,v
> retrieving revision 1.126
> diff -u -r1.126 kern_exec.c
> --- kern/kern_exec.c  2001/05/01 08:12:56     1.126
> +++ kern/kern_exec.c  2001/05/06 16:25:06
> @@ -104,8 +104,9 @@
>       register struct execve_args *uap;
>  {
>       struct nameidata nd, *ndp;
> +     struct ucred *oldcred = p->p_ucred, *newcred;
>       register_t *stack_base;
> -     int error, len, i;
> +     int error, len, i, intrace;
>       struct image_params image_params, *imgp;
>       struct vattr attr;
>       int (*img_first) __P((struct image_params *));
> @@ -272,23 +273,31 @@
>               p->p_flag &= ~P_PPWAIT;
>               wakeup((caddr_t)p->p_pptr);
>       }
> +     intrace = p->p_flag & P_TRACED;
> +     PROC_UNLOCK(p);

This unlock is busted since we then try to unlock this lock again later on
since you didn't remove the other unlocks.  Also, this whole caching of the
intrace flag is bogus too.  If you read a value and release the lock, then you
have now lost the ability to safely make decisions on the value you just read. 
You have to hold the lock over both reading the value and deciding what to do
based on that value so that the entire thing is an "atomic" operation.  For
now, I would just revert the intrace changes to check the flag directly like
the code does now and not add in this proc unlock.

>       /*
> +      * XXX: Note, the whole execve() is incredibly racey right now
> +      * with regards to debugging and privilege/credential management.
> +      * This MUST be fixed prior to any release.
> +      */
> +
> +     /*
>        * Implement image setuid/setgid.
>        *
>        * Don't honor setuid/setgid if the filesystem prohibits it or if
>        * the process is being traced.
>        */
> -     if ((((attr.va_mode & VSUID) && p->p_ucred->cr_uid != attr.va_uid) ||
> -          ((attr.va_mode & VSGID) && p->p_ucred->cr_gid != attr.va_gid)) &&
> -         (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 &&
> -         (p->p_flag & P_TRACED) == 0) {
> +     newcred = NULL;
> +     if ((((attr.va_mode & VSUID) && oldcred->cr_uid != attr.va_uid) ||
> +          ((attr.va_mode & VSGID) && oldcred->cr_gid != attr.va_gid)) &&
> +         (imgp->vp->v_mount->mnt_flag & MNT_NOSUID) == 0 && intrace == 0) {
>               PROC_UNLOCK(p);
>               /*
>                * Turn off syscall tracing for set-id programs, except for
>                * root.
>                */
> -             if (p->p_tracep && suser(p)) {
> +             if (p->p_tracep && suser_xxx(oldcred, NULL, PRISON_ROOT)) {
>                       p->p_traceflag = 0;
>                       vrele(p->p_tracep);
>                       p->p_tracep = NULL;
> @@ -296,25 +305,42 @@
>               /*
>                * Set the new credentials.
>                */
> -             p->p_ucred = crcopy(p->p_ucred);
> +             newcred = crdup(p->p_ucred);
>               if (attr.va_mode & VSUID)
> -                     change_euid(p, attr.va_uid);
> +                     change_euid(newcred, attr.va_uid);
>               if (attr.va_mode & VSGID)
> -                     p->p_ucred->cr_gid = attr.va_gid;
> +                     change_egid(newcred, attr.va_gid);
>               setsugid(p);
>               setugidsafety(p);
>       } else {
> -             if (p->p_ucred->cr_uid == p->p_cred->p_ruid &&
> -                 p->p_ucred->cr_gid == p->p_cred->p_rgid)
> -                     p->p_flag &= ~P_SUGID;
> +             if (oldcred->cr_uid == oldcred->cr_ruid &&
> +                 oldcred->cr_gid == oldcred->cr_rgid)
> +                     p->p_flag &= ~P_SUGID;  /* XXX locking */
>               PROC_UNLOCK(p);
>       }
>  
>       /*
>        * Implement correct POSIX saved-id behavior.
> +      *
> +      * XXX: determine whether tests and sets should occur on old or
> +      * new credentials.
>        */
> -     p->p_cred->p_svuid = p->p_ucred->cr_uid;
> -     p->p_cred->p_svgid = p->p_ucred->cr_gid;
> +     if (p->p_ucred->cr_svuid != p->p_ucred->cr_uid ||
> +         p->p_ucred->cr_svgid != p->p_ucred->cr_gid) {
> +             if (newcred != NULL)
> +                     newcred = crdup(p->p_ucred);
> +
> +             change_svuid(newcred, p->p_ucred->cr_uid);
> +             change_svgid(newcred, p->p_ucred->cr_gid);
> +     }
> +
> +     if (newcred != NULL) {
> +             struct ucred *oldcred;
> +
> +             oldcred = p->p_ucred;
> +             p->p_ucred = newcred;
> +             crfree(oldcred);
> +     }
>  
>       /*
>        * Store the vp for use in procfs

-- 

John Baldwin <jhb@FreeBSD.org> -- http://www.FreeBSD.org/~jhb/
PGP Key: http://www.baldwin.cx/~john/pgpkey.asc
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/

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?XFMail.010507130340.jhb>