Stack Walks


A stack walk is an essential, but expensive, part of the security system. The following description is a logical model of how stack walks and the security system work within the CLR.

A new activation record is put on the stack every time a method is called. This record contains the parameters passed to the method (if any), the address to return to when this function completes, and any local variables . As a program executes, the stack grows and shrinks as functions are called. At certain stages during execution, the thread may seek to access a system resource, such as the file system. Before allowing this access, the security system may demand a stack walk to verify that all functions in the call chain have permission to access the system resource. At this stage, each activation record will be checked to confirm that callers do indeed have the required permission.

At any stage during its execution, a function may wish to check the permissions of all its callers before it accesses a system resource. To do so, it may demand a security check for a specific permission. This demand triggers a stack walk, which has one of two results:

  • The function continues if all callers have the permission granted.

  • An exception is thrown if the callers do not have the required permission.

Figure 4.5 depicts this process.

Figure 4.5. A stack walk for permission

graphics/04fig05.gif

Functions may choose to modify the stack walk using any of several mechanisms. First, one function may vouch for the functions that called it by asserting a specific permission. If a stack walk looks for the asserted permission, and this function's activation record is checked for the permission, then if the function has the asserted permission the check will succeed and the stack walk will terminate. The Assert model does have an interesting semantic, however. You do not need to have a permission to assert it. In such a case, the assertion will succeed when it is called but an exception will be thrown at runtime if a stack walk discovers that the function did not have the permission it asserted.

A second way to modify the stack walk is for a function to deny permissions. This situation may occur when a function knows that it should not be able to assess a resource. PermitOnly provides similar functionality to the denial in that it causes a stack walk to fail. Whereas the Deny operation specifies a set of permissions that would cause the stack walk to fail, however, PermitOnly specifies the set of permissions required to continue the stack walk.

Note that a stack frame can have only one Deny, one PermitOnly, and one Assert in effect at any time. For example, if developers need to assert a number of permissions, they should create a PermissionSet to represent that set and perform a single Assert operation. Some methods remove the current PermissionSet setting for a single stack walk modifier, allowing another permission set to be registered ”for example, RevertPermitOnly and RevertAll.

Listing 4.7 demonstrates many of the aspects of code-based security, such as the asserting, demanding, and denying of specific permissions.

Listing 4.7 Asserting, demanding, and denying permissions
 using System; using System.Security; using System.Security.Permissions; namespace PermissionDemand {    class EntryPoint    {       static void Main(string[] args)       {          String f = @"c:\System Volume Information";          FileIOPermission p =             new FileIOPermission(                FileIOPermissionAccess.Write, f);          p.Demand();          p.Deny();          p.Demand();          CheckDeny(p);          p.Assert();          CheckDeny(p);       }       static void CheckDeny(FileIOPermission p)       {          try          {             p.Demand();          }          catch(SecurityException)          {             Console.WriteLine("Demand failed");          }       }    } } 

Listing 4.7 produces the following output, which appears very counterintuitive at first:

 Demand failed Demand failed 

The first call to Demand succeeds, even though the program attempts to access a restricted system directory. This result occurs because the CLR security system is not tied to the operating system's security system. Therefore, although the operating system will prohibit access to the system directory should the program seek it, the CLR security system will not fail the Demand call because the code has full trust, which includes file access as far as the CLR's security system is concerned .

The next call to Demand , which occurs immediately after the Deny call, also succeeds. The demanding function's activation record is not checked when a Demand call is made ”only its callers. Therefore, although the function has denied access, this fact is not detected by the Demand call. The call to CheckDeny and the subsequent call to Demand do fail, however. The Deny call in the previous method is checked, as it appears in a caller's stack frame.

Next, the program returns to Main and makes a call to Assert . Here the function has asserted a permission that was denied in this stack frame. When the program enters CheckDeny , the call to Demand again raises an exception. But why? A Deny overrides an Assert , because the Deny permission set is always checked before the Assert permission set is examined.



Programming in the .NET Environment
Programming in the .NET Environment
ISBN: 0201770180
EAN: 2147483647
Year: 2002
Pages: 146

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net