Skip to main content

Security error accessing filesystem

13 replies [Last post]
anthony_flec
Offline
Joined: 2009-11-30
Points: 0

I'm converting an application to run on ocap-ri-1.1.2. This application has run successfully on ocap-ri-1.1.1. When I launch the application I see a security error when it tries to access the filesystem:

20091124 12:38:20.453 ERROR RI.Stack- Exception occurred during event dispatching:20091124 12:38:20.453 ERROR RI.Stack-
20091124 12:38:20.453 ERROR RI.Stack- java.lang.SecurityException20091124 12:38:20.453 ERROR RI.Stack-
20091124 12:38:20.453 ERROR RI.Stack- at com.vidiom.impl.security.SecurityManagerImpl.checkRead(Ljava/lang/String;)V(SecurityManagerImpl.java:329)20091124 12:38:20.453 ERROR RI.Stack-
20091124 12:38:20.453 ERROR RI.Stack- at java.io.File.checkRead()V(File.java:1726)20091124 12:38:20.453 ERROR RI.Stack-
20091124 12:38:20.453 ERROR RI.Stack- at java.io.File.exists()Z(File.java:764)20091124 12:38:20.453 ERROR RI.Stack-

The perm file exists and contains the correct permissions. I've been able to isolate the problem down to the xlet code shown below. If the xlet is AUTOSTART it works just fine. If the xlet is marked as PRESENT in the xait and started by another application, the security error is thrown. It seems that the security check fails because the context associated with the EDT is the SystemContext, not an ApplicationContext. How can I fix this problem?

import java.awt.EventQueue;
import java.io.File;

import javax.tv.xlet.Xlet;
import javax.tv.xlet.XletContext;
import javax.tv.xlet.XletStateChangeException;

public class FileXlet implements Xlet {
  private File dir;
 
  public void destroyXlet(boolean arg0) throws XletStateChangeException {
  }

  public void initXlet(XletContext ctx) throws XletStateChangeException {
    System.out.println("Creating filesystem");
    try {
      dir = new File(getAppRoot(ctx), "test");
      if (!dir.exists())
        dir.mkdirs();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  public void pauseXlet() {
  }

  public void startXlet() throws XletStateChangeException {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        System.out.println("Looking for f1");
        try {
          File f1 = new File(dir, "f1");
          System.out.println(f1.exists());
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }
 
  private static File getAppRoot(XletContext ctx) {
    String root = System.getProperty("dvb.persistent.root");
    String slash = File.separator;

    String org = (String) ctx.getXletProperty("dvb.org.id");
    String app = (String) ctx.getXletProperty("dvb.app.id");

    return new File(root + slash + org + slash + app);
  }
}

Thanks!
Anthony

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
greg80303
Offline
Joined: 2008-07-03
Points: 0

EventQueue.invokeLater() takes whatever action (Runnable) you specify and posts it for execution on the [b]AWT Event thread[/b]. Why are you using this event queue to do file-related, non-GUI activities? The AWT thread is not an application thread and thus, will not allow app-specific file read/write activitites.

However, this does make me think that there is a security hole here. If Xlets can post arbitrary code that will run in the System context, there is a possibility that this would circumvent all OCAP security restrictions for that app. I will create an internal project issue to track this problem and my investigation.

anthony_flec
Offline
Joined: 2009-11-30
Points: 0

During the normal course of operations, the application accesses a disk cache for images. The cache retrieves the images on the caller's thread which in some cases happens to be the AWT Event thread.

I can investigate moving that access to an application thread. For my own edification, is this restriction a feature of the RI or spelled out in the OCAP specifications?

Thanks again for the help.

greg80303
Offline
Joined: 2008-07-03
Points: 0

This is another one of the complications that we have when trying to use a single VM but make it "look" like each app runs in its own separate VM. Technically, its not "against the rules" to perform non-GUI-related activities in the EDT. It is just frowned upon because it can slow down GUI painting and event delivery and affect the presentation to the user.

Bottom line -- There is no spec reference that I can find that would prohibit an application from making calls into the stack (public APIs or filesystem operations).
I think this is something the stack should handle. So, for now, you can consider this a bug in the stack -- and you will have to implement a work-around until we can fix the bug. Would you mind creating an issue on our IssueTracker please?

Thanks,
Greg

anthony_flec
Offline
Joined: 2009-11-30
Points: 0

Greg,

I agree on both counts: in most cases it's not a good idea to invoke expensive operations on the EDT but it doesn't appear to be explicitly prohibited by OCAP. I'll implement a change in my application to prevent filesystem access from the EDT.

I've filed the issue at https://ocap-ri.dev.java.net/issues/show_bug.cgi?id=85.

Thanks for working through this issue!

Anthony

wmunsil
Offline
Joined: 2009-07-05
Points: 0

Just to add my two cents' worth:

From the javadocs for java.awt.EventQueue:

"Some browsers partition applets in different code bases into separate contexts, and establish walls between these contexts. In such a scenario, there will be one EventQueue per context. Other browsers place all applets into the same context, implying that there will be only a single, global EventQueue for all applets. This behavior is implementation-dependent. Consult your browser's documentation for more information."

Ignoring the browser-centric verbiage, I think the intended implementation choice is clear. The RI chose the second implementation, and has done so in a way that opens this security hole. In my opinion, we need to switch to the first implementation, with each event thread executing in the context of its associated application.

Thanks for helping us work through this, Anthony, and for your willingness to code a workaround. And thanks for the insights, Greg.

Wes

wmunsil
Offline
Joined: 2009-07-05
Points: 0

Would you mind describing what the xlet is trying to do? That is, what it is passing to invokeLater, and why?

anthony_flec
Offline
Joined: 2009-11-30
Points: 0

The xlet shown above is a distillation of a larger application that demonstrates the security error. In the application, certain events must be executed by the EDT, hence the use of EventQueue.invokeLater(...). The xlet simply queues a file operation for execution by the EDT.

Does that help?

wmunsil
Offline
Joined: 2009-07-05
Points: 0

Yes, I understand that. What I'd like to understand is the reason for the application to do file operations there.

I'm not trying to find fault, I'm only trying to understand what you're trying to do in case I have to propose some radical alternative strategy.

wmunsil
Offline
Joined: 2009-07-05
Points: 0

Hi Anthony,

The scenario I described applies to reads as well as writes. However, your observation of the null appID sounds right on the money, and your suggested cause sounds probable. I will investigate that suggestion--but probably not until tomorrow!

Wes

wmunsil
Offline
Joined: 2009-07-05
Points: 0

So I suspect what is happening is simply that one app is attempting to access storage owned by the other app (i.e., within the other app's orgID/appID directory). By default, only the owning app can access this storage--1.1.2 checks for this where 1.1.1 did not.

You might try one of two approaches to resolve this: either cause the owning application to grant organization access (read and/or write, as appropriate) to the file using FileAttributes.setFileAttributes, or, possibly better, use storage at the orgID directory level for communication between applications, instead of storage at the orgID/appID directory level.

anthony_flec
Offline
Joined: 2009-11-30
Points: 0

wmunsil, thanks for looking into this problem. The xlet in question never attempts to write to the the originating app's storage (or vice versa) so there shouldn't be security conflict. Also, I've done some retesting and found that the problem occurs even if the xlet is auto-started.

I traced the call into SecurityManagerImpl.hasFileAccess and found that the check fails because the AppID obtained from the CallerContext is null (it's a SystemContext not an ApplicationContext). This only happens if the check is performed on the EDT. That is, if the file operation is performed directly rather than via EventQueue.invokeLater(...) the error does not occur.

Is it possible that the application context is not being associated with the EDT?

wmunsil
Offline
Joined: 2009-07-05
Points: 0

Do the two applications have the same org ID?

anthony_flec
Offline
Joined: 2009-11-30
Points: 0

Yes, the xait looks like this:

version=0
transport.0=local
svc.0.service=0x2BEEF
svc.0.auto_select=true
svc.0.name=Local 1

# SimpleMonApp
app.0.application_control_code=AUTOSTART
app.0.visibility=VISIBLE
app.0.launch_order=0x0
app.0.version=0x0
app.0.application_identifier=0x000000016000
app.0.priority=0xff
app.0.application_name=SimpleMonApp
app.0.initial_class_name=org.cablelabs.oc.wba.apps.simplemonapp.SimpleMonApp
app.0.base_directory=../widget-sampleApps/bin
#Auto starts SimpleNav and WidgetLauncher
app.0.args.0=6001,6002
app.0.service=0x2BEEF

# SimpleNav
app.1.application_control_code=PRESENT
app.1.visibility=VISIBLE
app.1.launch_order=0x0
app.1.version=0x0
app.1.application_identifier=0x000000016001
app.1.priority=0xfe
app.1.application_name=SimpleNav
app.1.base_directory=../widget-sampleApps/bin
app.1.initial_class_name=org.cablelabs.oc.wba.apps.simplenav.SimpleNav
app.1.api.0=org.cablelabs.oc.wba
app.1.args.0=WidgetLauncher,6002,156
app.1.service=0x2BEEF

# WidgetLauncher
app.2.application_identifier=0x000000016002
app.2.application_control_code=PRESENT
app.2.visibility=VISIBLE
app.2.priority=0xfe
app.2.launch_order=0x0
app.2.version=0x0
app.2.application_name=widget-launcher
app.2.base_directory=bin
app.2.initial_class_name=com.comcast.widget.launcher.LauncherXlet
app.2.api.0=org.cablelabs.oc.wba
app.2.service=0x2BEEF