John L. Moreland, David R. Nadeau
San Diego Supercomputer Center
(SDSC)
Permission to copy without fee all or part of this material is granted
provided that the copies are not made or distributed for direct commercial
advantage, the ACM copyright notice and the title of the publication and its
date appear, and notice is given that copying is by permission of the
Association of Compouting Machinery. To copy otherwise, or to republish,
requires a fee and/or specific permission.
(c) 1995 ACM This paper presents a prototype implementation of a behavior system
for VRML [3]. It demonstrates the requirements and the "real world" problems
involved in creating a behavior system. It also uncovers some of the more
esoteric problems one finds in the finer implementation details of a VRML
behavior language. Implementation details having to do with system and network
security are specifically discussed.
The choice of Perl as a behavior language was made not necessarily because
Perl should become the standard VRML behavior language. It was chosen for
convenience of implementation and demonstration purposes. The choice of Perl
also enables us to demonstrate several techniques to enable the repurposing of
an existing scripting language as a VRML behavior language.
The Virtual Reality Modeling Language (VRML) is a developing standard
for describing interactive three-dimensional scenes delivered across the
internet. The first version (v1.0) of the VRML specification, however, did not
include semantics for describing interactive behaviors in a scene. Instead, this
task was left to be defined in future revisions of the standard.
The implementation of a prototype behavior system for VRML has helped to
demonstrate many unique requirements and "real world" problems involved in
creating a future behavior system standard for VRML. Having implemented such a
prototype, we have found that there is an inherent competition between providing
required functionality and dealing with the pitfalls of network security, system
security, performance issues, and portability.
To describe the advantages and disadvantages of a specific language
implementation, it is useful to define the basic functional requirements
necessary in general for a VRML behavior language. We may then set out to define
the specific language features and identify problems involved in providing those
features in a non-prototype language implementation.
There are, perhaps, many more language feature requirements that should be
addressed in a standards specification. The items listed here are sufficient,
however, to demonstrate specific language features we will present, and they
help identify most of the problems uncovered in our prototype implementation.
The Perl Behavior System (PBS) is a prototype implementation of a behavior
language. PBS uses the Virtual Reality Behavior System (VRBS [5] - pronounced
"Verbs" ) to communicate with a VRML browser (in our case, SDSC WebView). PBS
itself consists of a "wrapper" script (written in Perl) that provides a
preprocessor for end-user scripts and a small number of simple routines used to
interact with VRML worlds. The calls that users make to PBS then call Perl-VRBS
functions to communicate with a VRML world. (See figure)
* This paper to appear in the proceedings of VRML 95, the First Annual
Symposium on the Virtual Reality Modeling Language, December 13-15, San Diego,
CA USA. The proceedings are published by ACM.
Abstract
1. Introduction
2. Functional Requirements
2.1 Architecture Independent
The language should not be tied to any specific hardware
architecture. This includes issues such as assuming word size, byte ordering,
memory layout, etc.
2.2 Operating System Independent
The language should not be tied to any specific operating system. This
includes issues such as assuming a process management model, directory path
notation, or file name formats.
2.3 Portable
The interpreter should be available on or easily ported to a wide variety
of computer systems. The intent is to provide a language that can be shared
over a network between many different heterogeneous systems.
2.4 Powerful
A developer should be provided with sufficiently powerful tools (language
features / libraries) to be able to author arbitrarily
sophisticated environments.
2.5 Usable
The language should be easy to author and learn, and should provide a
quick development cycle. Convoluted syntax and overly intricate semantics will
discourage the majority of users.
2.6 Network Secure
The language should provide some well-defined networking capabilities, but
limit the scope to prevent intentional or unintentional network security
problems.
2.7 System Secure
The language should provide certain well-defined system access
capabilities (such as file I/O, process creation, etc.), but limit the scope
to prevent intentional or unintentional system security problems.
Analysis
Several scripting languages fulfill requirements 2.1-2.5. Perl, in
particular, is powerful, portable, available for most systems, and it is very
C-like so is suits our needs for purposes of discussion. It is requirement 2.6
and 2.7 that tend to be troublesome for most languages, however.
3. The Perl Behavior System (PBS)
In the SDSC WebView/PBS environment, behavior scripts are downloaded by the SDSC WebView browser. Each time a new world is encountered by the browser, a new Perl interpreter is started. The interpreter is killed when the browser flushes a world from it's memory cache. So, there may be more than one interpreter running at any given time. However, any number of behavior scripts that are part of the same world may be running simultaneously under one interpreter. This enables several scripts from one world to interact with the same scene.
When a new interpreter is started for a world, the following events take place:
PBS contains a Perl implementation of the VRBS protocol routines. These are low-level routines that are not intended to be called by end user scripts but by a language-specific user-level binding layer.
The PBS wrapper provides the following end user callable routines (as of this publication):
AddEvent DeleteNode GetBrowserExtension GetBrowserHosts GetBrowserName GetBrowserNodeFields GetBrowserNodeTypes GetBrowserPort GetBrowserVersion GetBrowserViewerTypes GetNodeBBox GetNodeField GetNodeField1 GetNodeNames GetNodeType GetWorldId GetWorldUrl InsertNode ReplaceNode SetNodeField SetNodeField1* See the VRBS Protocol Specification [4] document for details about these subroutines.
In addition to the calls that a user makes to PBS, the PBS wrapper also makes calls to user routines through event callbacks. Event callbacks are user-defined routines that are added to an internal PBS list by calling the AddEvent routine. The user routines are later called as a result of some specific event sent from the browser.
An event callback mechanism is used for several reasons:
A straightforward way to begin describing how a behavior interacts with the PBS wrapper is to provide an example. The following Perl behavior script demonstrates the rotation of a scene element by changing the rotation field value of a Rotation node:
#!/usr/local/bin/perl sub rotate { local( $eventID, # My Event ID $nodeName, # User Data ! $eventType, # "EvTimer" $worldId, # My World ID $time, # uSeconds ) = @_; $angle += 0.01; &SetNodeField( # Change a field $worldId, # Which world $nodeName, # "Fred" "rotation", # Field to change "0.0 1.0 0.0 $angle" # Value ); } $angle = 0.0; # Our initial angle $foo = &AddEvent( # Add a callback "rotate", # Call "rotate" sub. "Fred", # User Data "EvTimer", # Timer event "1.0" # One second interval );Notice that the user script does not have any kind of "main loop". Its sole purpose is to initialize its environment, and to nominate callback routines by making one or more calls to the AddEvent routine. The function of each callback routine is to describe the interaction between the user and the VRML environment. The user script hen returns control to the PBS wrapper code by simply completing.
Each time the user's script calls the AddEvent routine, the PBS wrapper adds an entry to an event table:
id world event func data params 0 2001 EvTimer rotate Fred 1000 1 42 NodeChan doIt toIt MilkThis event table enables the pbs wrapper to call the correct user-nominated callback routine when the browser sends an event. At this stage, however, the browser does not know that pbs is interested in seeing events of the given type. The AddEvent routine must also determine if it has ever asked the browser to start sending the event type or not (that is, if the given event type is ever generated by some user action or other behavior interaction). Here is a list of the currently supported event types that can be added:
[0] EvNodeButtonPress [1] EvNodeButtonRelease [2] EvNodeKeyPress [3] EvNodeKeyRelease [4] EvNodePointerWithin2 [5] EvNodePointerEnter2 [6] EvNodePointerLeave2 [7] EvNodePointerWithin3 [8] EvNodePointerEnter3 [9] EvNodePointerLeave3 [10] EvNodeChange [11] EvNodeFieldChange [12] EvTimer [13] EvWorldEnter [14] EvWorldLeaveAfter the pbs wrapper has cached the event in its event table, it then determines if it needs to register a new event type with the browser. It does this by looking in its own list of event types who's entries denote the number (count) of user callback routines that have previously been registered for the event type:
@eventList = ( 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 );By using the event numbers themselves (see list above) as an index into the eventList cache, we can quickly determine if we need to tell the browser whether to respond to specific event types. In this case, the table indicates that there has been one EvTimer event registered and one NodeChange event registered.
Notice that the finite number, type, and capabilities of the events that VRBS provides leaves the implementors in control of what kind of calls are made between the browser and behaviors. This in turn limits the scope of what an "ill-mannered" script could do to an unsuspecting user's environment. However, the calls that can be made by the behavior to the scripting language interpreter itself presents more difficult access control issues.
One of the most unique aspects of developing a behavior model for VRML is the notion that scripts can be downloaded from a remote machine on a network. Once downloaded, the script is then executed on the local machine. The potential for intentional or unintentional inclusion of a software pathogen (computer virus) is quite real.
Even if a language were to fulfill the behavior language requirements described in sections 2.1-2.5, a language which does not meet requirements 2.6 and 2.7 could potentially be too dangerous to trust when used as a behavior system. The issue is access. That is, the ability to make use of system or network resources can potentially lead to exploitation of the capabilities of those resources.
To illustrate some of the potential problems in allowing a behavior language to make "unrestrained" calls, we will classify some of Perl's built-in subroutines and examine the positive and negative aspects of their use in a behavior script.
There are two main types of potentially dangerous language features: internal language parsing constructs, and external communications constructs. The external communications classification can be further broken down into three subcategories: file operations, system interaction, and network access.
Another Perl function that is quite useful for initialization but potentially hazardous is the undef routine. This enables a script to undefine any variable or subroutine such that it no longer has any definition whatsoever. The concern here is similar to that of the sub keyword. An ill-mannered behavior could completely remove the ability for other scripts to function.
Since a string to be executed in Perl can be computed at runtime, we have a further problem in determining what, in a user behavior "looks dangerous".
Any language that wishes to execute fragments of its own language may have a similar code evaluation capability. Therefore, there should be similar concern on behalf of other behavior languages.
A scripting language processor can grant as few or as many capabilities to a script as the language specification allows. A pre-processor can even detect and remove existing constructs before they ever get to the interpreter. We can even modify the interpreter itself to remove any built in language constructs that can cause the kind of grief we have discussed. But, modifying the interpreter means changing the language which, in this case, defeats the purpose of using a "standard" scripting language. However, access to resources outside of the language interpreter itself is a far more difficult issue than internal interpreter issues.
Perl provides the following functionality for accessing or manipulating local files: <> (glob), chdir, chmod, chown, dbmopen, link, lstat, mkdir, open, opendir, readlink, rename, rmdir, stat, symlink, truncate, unlink, and utime.
The justification for allowing or disallowing use of each of these routines in turn can be easily proposed. However, it is more important to ask "to what extent should the functions be allowed". Hopefully we can justify the validity of one solution to this problem in section 9.
Perl provides the following routines for interaction with operating system level functionality: chroot, die, exec, exit, fork, getgrp, getlogin, getpid, getpriority, glob, kill, setgrp, setpriority, sleep, syscall, system, umask, wait, waitpid, and `` (accent graves).
In our virtual directory-structure room above, we could imagine providing a more limited form of an ls-like command. But providing this sort of functionality directly in the language could become unwieldy, not to mention non-portable (as is the case for the ls command).
Perl provides the following functions to enable TCP/IP socket connections which could easily be abused: accept, bind, connect, and listen.
Allowing a network connection to an unfamiliar host through an untrusted port using an arbitrary protocol has obvious problems. But, as in our first example above, it also has some notable benefits.
The key to all of these problems is, again, resource access. If a language, and interpreter, or even a network or operating system grant the ability to access specific resources, the game is over. The solution therefore is to not allow access to critical resources to begin with, or at least limit the extent of access capabilities.
As we have demonstrated, the danger in a behavior language lies in the unrestrained access a language has to both internal and external resources.
One method that has proven useful in avoiding resource access problems is by preprocessing the incoming behavior script before it is ever passed to the interpreter. In essence, we run a "sanitizing" pass on the behavior script to disable or replace any built-in access-granting routines or any user-level code fragments that have the potential of being anti-social.
A feature of Perl that allows us to implement a sanitizing pass is that a Perl script can not compute and then call a built-in function name. This has to do with the function-call syntax of Perl itself. Calls to built-in Perl function names are not preceded by an ampersand (&) character. This is not the case for user-defined routines. The difference in implementation is that built-in function names are bound to interpreter code at compile time, whereas user-defined routines are bound to interpreter code at run time.
What all this means to the pbs sanitizing pass is that the Perl language itself forces scripts to explicitly state the static names of built-in functions. The following code fragment will help illustrate this point:
# Perl will call a USER routine # called "system", NOT the # built-in system call that the # user-script tried to hide: $foo = "sys" . "tem"; &$foo( "rm -rf /" );Note that the user is forced to use the "&" syntax to call any user-defined OR any user-computed functions. The only way to call the built-in system function is to explicitly name the built-in function BEFORE compile time:
system( "rm -rf /" );In this case, our sanitizing filter can easily find and replace the system call or warn about it before the code fragment ever reaches the parsing or execution stages.
There are several key points that come to mind that can help solve some problems. We can choose routines to remove from a behavior script. For example, the system call could be removed because we can not predict which commands the script will try to run. We could warn the user about questionable code. We may just tell the browser user that a behavior that was about to start was potentially too dangerous to run. We would just not run the script in this case. We could select a subset of routines to modify. The open call we might change to restrict opened files to one fixed directory. The script itself does not have to know this.
The last option means that we simply wrap the routines we have deemed dangerous with our own code (that has parameter-compatible arguments with the real routines) that provide reduced access to resources.
It is clear that there are resource access problems involved in downloading a behavior script from a remote system and running a script on a local machine. The solutions are less clear. The restrictions we place on a language can clearly hamper the usefulness of the language. By the same token it is also clear that unlimited resource access by a behavior is potentially dangerous. Determining what is "enough access" or "too much access" is an interesting and worthy area of future research.
The Perl Behavior System (PBS) is the result of work by John L. Moreland and David R. Nadeau at the San Diego Supercomputer Center. Many thanks go to the SDSC Webview team: David R. Nadeau, Cherylin Michaels, John L. Moreland, and Dema Zlotin. Special thanks to Andrew Gross for his expert input on network and system security issues.
This work has been supported through major funding from the National Science Foundation and the State of California. The opinions, conclusions, and recommendations expressed herein are those of the authors and do not necessarily reflect the views of SDSC, General Atomics, or their sponsors.
[1] Wall, Larry and Randal Schwartz. Programming Perl. O-Reilly & Associates, March 1992.
[2] Wernecke, Josie. The Inventor Mentor. Addison-Wesley Publishing Company, 1994.
[3] Bell, Gavin and Anthony Parisi. The Virtual Realitfy Modeling Language v1.0 specification.
[4] Nadeau, David and John Moreland. VRBS Protocol Specification. San Diego Supercomputer Center., July 1995.
[5] Nadeau, David and John Moreland. The Virtual Reality Behavior System (VRBS). San Diego Supercomputer Center, July 1995.