From owner-freebsd-arch Tue Oct 9 11:30: 6 2001 Delivered-To: freebsd-arch@freebsd.org Received: from mail5.speakeasy.net (mail5.speakeasy.net [216.254.0.205]) by hub.freebsd.org (Postfix) with ESMTP id 2FCA737B40B for ; Tue, 9 Oct 2001 11:29:57 -0700 (PDT) Received: (qmail 92190 invoked from network); 9 Oct 2001 18:29:56 -0000 Received: from unknown (HELO laptop.baldwin.cx) ([64.81.54.73]) (envelope-sender ) by mail5.speakeasy.net (qmail-ldap-1.03) with SMTP for ; 9 Oct 2001 18:29:56 -0000 Message-ID: X-Mailer: XFMail 1.4.0 on FreeBSD X-Priority: 3 (Normal) Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Date: Tue, 09 Oct 2001 11:29:23 -0700 (PDT) From: John Baldwin To: arch@FreeBSD.org Subject: ucred API Sender: owner-freebsd-arch@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Hey all. I'd like to make the following changes to the ucred API in the interests of making the locking more sane. The changes will occur in 2 stages. Stage 1: - Add a new function crshared(cr) that returns true if ucred cr's refcount is greater than 1. - Change crhold(cr) to return a pointer to the ucred it bumped the reference of. Thus, the following code: cr = foo->f_cred; crhold(cr); becomes: cr = crhold(foo->f_cred); (suggested by Terry L.) - Change the crcopy() function to actually copy the contents of one ucred to another. This is much more lock friendly as having crcopy() block on malloc introduces locking problems. Before code: PROC_LOCK(p); cred = p->p_ucred); PROC_UNLOCK(p); /* XXX: race */ p->p_ucred = crcopy(cred); /* XXX: can block! */ PROC_LOCK(p); p->p_ucred = cred; ... PROC_UNLOCK(p); New code: newcred = crget(); PROC_LOCK(p); oldcred = p->p_ucred; error = suser(oldcred); if (error == 0) { crcopy(newcred, oldcred); .... p->p_ucred = newcred; newcred = oldcred; } PROC_UNLOCK(p); crfree(newcred); Which doesn't block during the critical section and can make all the access checks and changes as one "atomic" change. Stage 2: - Add a per-thread reference to the ucred that is created on syscall entry and released on syscall exit. It is also created and released if needed on trap enter/exit. It is _not_ created for interrupts since interrupts should not care about the ucred of their borrowed context. The per-thread ucred reference will then point to a ucred that won't ever change (setuid, etc. update the per-process ucred) and thus won't need any locking. Almost all references to ucreds for suser(), VOP's etc. will use the thread reference. This will ensure that a thread's ucred will be the same for an entire syscall which will close many races involving multithreaded programs and ucreds. The only place where the per-process ucred will be used for access checks is places that modify the ucred as we want to ensure there is no race of one thread making a credential change it isn't qualified to make due to it performing its access checks on a stale ucred before updating the master ucred. I've talked with Robert Watson about these already and they sound good to him. Any objections? -- John Baldwin -- 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