Nicolas Williams wrote: > On Mon, Jun 15, 2009 at 09:24:26PM +0200, Darren Reed wrote: >> http://cr.opensolaris.org/~darrenr/6271923-20090615/ >> >> It includes a fix for the bug identified by Nicolas earlier, 6851264. > > Hmmm, I think you could still loop: > > + int which = RCTL_FIRST; > > - while (pr_getrctl(Pr, ctl_name, NULL, blk, RCTL_FIRST) != -1 && > + while (pr_getrctl(Pr, ctl_name, NULL, blk, which) != -1 && > rctlblk_get_privilege(blk) != RCPRIV_SYSTEM) { > - if (pr_setrctl(Pr, ctl_name, NULL, blk, RCTL_DELETE) != 0) > + if (pr_setrctl(Pr, ctl_name, NULL, blk, RCTL_DELETE) != 0) { > failed++; > + which = RCTL_NEXT; > + } else { > + which = RCTL_FIRST; > + } > > Perhaps I'm being thick, but it seems to me that we're always re-trying > on pr_setrctl() failure, without a limit to how many times we re-try -- > at some point you've got to give up, even if it seems wrong for > pr_setrctl() to fail repeatedly.
If we have a list of 3 resources, A, B and C, lets assume that all 3 are not RCPRIV_SYSTEM resources. The first call to pr_getrctl() will return "A". Using the modified code, if the RCTL_DELETE on "A" fails then which becomes RCTL_NEXT and the next call to pr_getrctl() will return "B". We delete this successfully and start over because 'which' is set back to RCTL_FIRST. The basis for me doing this is I'm assuming that the RCTL_DELETE on "B" could cause unexpected things to happen if I do another pr_getrcl() with RCTL_NEXT - the thing I want to go "next" from is now gone. So "B" has been deleted and we see "A" again, which again returns an error, so 'which' gets set to RCTL_NEXT and then we return "C". If deleting "C" returns an error then we try to pr_getrctl() again and oops, we're at the end. If "C" doesn't return an error, then 'which' gets reset back to RCTL_FIRST, the next pr_getrctl() call returns "A", RCTL_DELETE fails so 'which' becomes RCTL_NEXT and we get to the end. It might seem silly to retry RCTL_DELETE on "A" three times but short of creating another "work list", it's just a hazard of the implementation. To examine other situations, if RCTL_DELETE fails for each of "A", "B" and "C", then the list is walked once (RCTL_FIRST, RCTL_NEXT, RCTL_NEXT, RCTL_NEXT) and SETFAILED is returned. If "A" is the only one deleted, the sequence is RCTL_FIRST, RCTL_FIRST, RCTL_NEXT, RCTL_NEXT. If you can splot any flaws or something I've missed in the logic, please work it through and demonstrate the problem. If it helps, I'll expand on the comments for that loop so that it's clear about what's going on. Darren