Opened 8 years ago
Closed 8 years ago
#12597 closed enhancement (fixed)
Prevent recursion in PermissionSystem.check_permission
Reported by: | Ryan J Ollos | Owned by: | Ryan J Ollos |
---|---|---|---|
Priority: | normal | Milestone: | 1.2.1 |
Component: | general | Version: | |
Severity: | normal | Keywords: | permissions |
Cc: | Branch: | ||
Release Notes: |
Fixed recursion in permission policy checks. |
||
API Changes: | |||
Internal Changes: |
Description
Discussed in gdiscussion:trac-users:MNvfBPbiAS0 and other threads, there is a high likelihood of recursion when a permission policy calls Permission.has_permission
(usually via ACTION in perm
) within its policy.check_permission
method. One possible way to avoid this, which I'd like to explore, would be to skip calling policy.check_permission on the policy that invoked PermissionCache.has_permission
.
Using CookBook/Configuration/SignedTickets as an example, the policy would be changed:
- any(a in perm for a in self.admin_actions): + any(a in perm(resource, policy=self) + for a in self.admin_actions):
Attachments (0)
Change History (6)
comment:1 by , 8 years ago
follow-up: 4 comment:2 by , 8 years ago
I find it quite difficult to think about the implications here. Does this ever unintentionally skip an important permission check?
Might a conservative alternative be to "pre-cache" a negative decision? (untested)
-
trac/perm.py
diff -r 23adc5e36b28 trac/perm.py
a b 588 588 cache_decision, cache_resource = cached 589 589 if resource == cache_resource: 590 590 return cache_decision 591 # In case of recursive check, disallow permission 592 self._cache[key] = (False, resource) 591 593 perm = self 592 594 if resource is not self._resource: 593 595 perm = PermissionCache(self.env, self.username, resource,
comment:3 by , 8 years ago
Milestone: | 1.0.14 → 1.2.1 |
---|
I'll investigate for 1.2.1. next-stable-1.0.x should be (or soon be) for major defects only.
comment:4 by , 8 years ago
Replying to Peter Suter:
Might a conservative alternative be to "pre-cache" a negative decision? (untested)
That appears to be a simple way to solve the issue: rjollos.git:t12597_perm_policy_recursion.1.
With the change, ReadonlySignedTickets policy works with the following change:
-
ReadonlySignedTickets.py
old new 15 15 if resource is None or resource.realm != 'ticket' or \ 16 16 resource.id is None or \ 17 17 action in self.allowed_actions or \ 18 action in ('TICKET_ADMIN', 'TRAC_ADMIN') or \19 18 'TICKET_ADMIN' in perm: 20 19 return None
comment:5 by , 8 years ago
Additional change in [4831f0f3/rjollos.git].
if resource ... in has_permission
didn't seem to be behaving as intended.
if resource
would always evaluate toTrue
. I suppose we could implement__nonzero__
/__bool__
onResource
so thatResource(None)
would evaluate toFalse
, but unsure whether that's generally useful.>>> from trac.resource import Resource >>> r = Resource(None) >>> bool(r) True
ACTION in perm
should behave the same asACTION in perm(None)
, however before the change the cached key would be different:After the change:>>> from trac.perm import PermissionCache >>> from trac.test import EnvironmentStub >>> env = EnvironmentStub() >>> perm1 = PermissionCache(env) >>> perm2 = PermissionCache(env) >>> 'PERM' in perm1 False >>> perm1._cache {('anonymous', -9223372036584357655, 'PERM'): (False, None)} >>> 'PERM' in perm2(None) False >>> perm2._cache {('anonymous', 7976857064515516242, 'PERM'): (False, <Resource ''>)}
Added test case in [2128800/rjollos.git].>>> from trac.perm import PermissionCache >>> from trac.test import EnvironmentStub >>> env = EnvironmentStub() >>> perm1 = PermissionCache(env) >>> perm2 = PermissionCache(env) >>> 'PERM' in perm1 False >>> perm1._cache {('anonymous', -9223372036583836439, 'PERM'): (False, None)} >>> 'PERM' in perm2(None) False >>> perm2._cache {('anonymous', -9223372036583836439, 'PERM'): (False, None)}
- Still considering, but implementing
__nonzero__
behavior proposed in (1),ACTION in perm(Resource(None))
could be made to behave the same as the two cases discussed in (2): [83ada83e/rjollos.git].
comment:6 by , 8 years ago
Release Notes: | modified (diff) |
---|---|
Resolution: | → fixed |
Status: | assigned → closed |
Most changes committed in r15340, merged in r15341. I didn't commit [83ada83e/rjollos.git].
The following changes may need additional work, but with a small amount of testing I can say they appear to fix the issue raised on the mailing list: log:rjollos.git:t12597_perm_policy_recursion.