#98 Auditors without unshadowable names

open
auditors (6)
4
2005-06-01
2005-06-01
No

At
http://www.eros-os.org/pipermail/e-lang/2004-August/010029.html
Kevin Reid writes:

The auditor system can be revised to not require any
unshadowable names
(thus increasing flexibility and removing a 'library'
definition from
the 'language' semantics.

(The following assumes that all Auditors and Guards are
DeepFrozen.)

Add to the AuditWitness something like:

/** Returns the IdentityKey of the Slot bound to the
given name in
the scope of the audited object. */
to fetchSlotIdentity(name :String, absentThunk)
:IdentityKey

(Alternatives include Auditor#audit receiving an object
resembling
Map[String, IdentityKey], the Witness allowing only
querying whether a
given name=>IdentityKey binding is present, etc.)

An IdentityKey is a Selfless object whose identity is
dependent on a
single other object, but does not reveal that object to
its clients.
This prevents the auditor from making use of the
objects in the scope,
or in the inverse alternative above, allows the auditor
to avoid
revealing any authority-carrying objects it is checking
for to an
adversarial 'witness'.

The current auditing system allows caching of the audit
of some
particular ObjectExpr, if the auditor is DeepFrozen,
since the
auditor's answer cannot change. This can still be done:

The cache entry would include all binding queries made
by the auditor.
If the same bindings exist, then the cached result may
be used -
otherwise, the auditor must be reinvoked.

Untested example code, unlikely to be useful in actual
implementation:

def auditCacheFlex := [].asMap().diverge()

def audit(objectExpr :DeepFrozen, scopeMap :Map[String,
IdentityKey],
approversFlex :FlexSet, auditor :(Auditor &
DeepFrozen)) :void {

def conclude(answer) :void {
if (Ref.isBroken(answer)) {
throw(Ref.optProblem(answer))
} else if (answer) {
approversFlex.addElement(auditor)
}
}

def fetchBindingPrim(name) :nullOk[IdentityKey]) {
return scopeMap.fetch(name, thunk{})
}

def approvalVarietiesFlex :=
auditCacheFlex.fetch(def cacheKey := [objectExpr,
auditor], thunk{
auditCacheFlex[cacheKey] := [].asMap().diverge()
})

for requiredScope => answer in approvalVarietiesFlex {
def fail := __continue
for [name, originalResult] in requiredScope {
if (fetchBindingPrim(name) != originalResult) {
fail()
}
}

conclude(answer)
return
}

def queriesFlex := [].diverge()

def witness {
to ask(subAuditor) :void {
audit(objectExpr, scopeMap, approversFlex, subAuditor)
}
to fetchSlotIdentity(name, absentThunk) :boolean {
def res := fetchBindingPrim(name)
queriesFlex.push([name, res])
return if (res == null) { absentThunk() } else { res }
}
}

def newAnswer := auditor.audit(objectExpr, witness)

approvalVarietiesFlex.put(queriesFlex.snapshot(),
newAnswer)

conclude(newAnswer)
}

Discussion


Log in to post a comment.