src/jdk.jfr/share/classes/jdk/jfr/internal/SecuritySupport.java
changeset 58863 c16ac7a2eba4
parent 58240 046533575954
equal deleted inserted replaced
58861:2c3cc4b01880 58863:c16ac7a2eba4
     1 /*
     1 /*
     2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    36 import java.lang.reflect.Field;
    36 import java.lang.reflect.Field;
    37 import java.lang.reflect.Method;
    37 import java.lang.reflect.Method;
    38 import java.lang.reflect.ReflectPermission;
    38 import java.lang.reflect.ReflectPermission;
    39 import java.nio.channels.FileChannel;
    39 import java.nio.channels.FileChannel;
    40 import java.nio.channels.ReadableByteChannel;
    40 import java.nio.channels.ReadableByteChannel;
       
    41 import java.nio.file.DirectoryStream;
    41 import java.nio.file.FileVisitResult;
    42 import java.nio.file.FileVisitResult;
    42 import java.nio.file.Files;
    43 import java.nio.file.Files;
    43 import java.nio.file.Path;
    44 import java.nio.file.Path;
    44 import java.nio.file.Paths;
    45 import java.nio.file.Paths;
    45 import java.nio.file.SimpleFileVisitor;
    46 import java.nio.file.SimpleFileVisitor;
    63 import jdk.jfr.Event;
    64 import jdk.jfr.Event;
    64 import jdk.jfr.FlightRecorder;
    65 import jdk.jfr.FlightRecorder;
    65 import jdk.jfr.FlightRecorderListener;
    66 import jdk.jfr.FlightRecorderListener;
    66 import jdk.jfr.FlightRecorderPermission;
    67 import jdk.jfr.FlightRecorderPermission;
    67 import jdk.jfr.Recording;
    68 import jdk.jfr.Recording;
       
    69 import jdk.jfr.internal.consumer.FileAccess;
    68 
    70 
    69 /**
    71 /**
    70  * Contains JFR code that does
    72  * Contains JFR code that does
    71  * {@link AccessController#doPrivileged(PrivilegedAction)}
    73  * {@link AccessController#doPrivileged(PrivilegedAction)}
    72  */
    74  */
    73 public final class SecuritySupport {
    75 public final class SecuritySupport {
    74     private final static Unsafe unsafe = Unsafe.getUnsafe();
    76     private final static Unsafe unsafe = Unsafe.getUnsafe();
    75     private final static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
    77     private final static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
    76     private final static Module JFR_MODULE = Event.class.getModule();
    78     private final static Module JFR_MODULE = Event.class.getModule();
    77     public  final static SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr");
    79     public  final static SafePath JFC_DIRECTORY = getPathInProperty("java.home", "lib/jfr");
    78 
    80     public final static FileAccess PRIVILIGED = new Privileged();
    79     static final SafePath USER_HOME = getPathInProperty("user.home", null);
    81     static final SafePath USER_HOME = getPathInProperty("user.home", null);
    80     static final SafePath JAVA_IO_TMPDIR = getPathInProperty("java.io.tmpdir", null);
    82     static final SafePath JAVA_IO_TMPDIR = getPathInProperty("java.io.tmpdir", null);
    81 
    83 
    82     static {
    84     static {
    83         // ensure module java.base can read module jdk.jfr as early as possible
    85         // ensure module java.base can read module jdk.jfr as early as possible
   148     /**
   150     /**
   149      * Path created by the default file provider,and not
   151      * Path created by the default file provider,and not
   150      * a malicious provider.
   152      * a malicious provider.
   151      *
   153      *
   152      */
   154      */
   153     public static final class SafePath {
   155     public static final class SafePath implements Comparable<SafePath> {
   154         private final Path path;
   156         private final Path path;
   155         private final String text;
   157         private final String text;
   156 
   158 
   157         public SafePath(Path p) {
   159         public SafePath(Path p) {
   158             // sanitize
   160             // sanitize
   166 
   168 
   167         public Path toPath() {
   169         public Path toPath() {
   168             return path;
   170             return path;
   169         }
   171         }
   170 
   172 
       
   173         public File toFile() {
       
   174             return path.toFile();
       
   175         }
       
   176 
   171         public String toString() {
   177         public String toString() {
   172             return text;
   178             return text;
       
   179         }
       
   180 
       
   181         @Override
       
   182         public int compareTo(SafePath that) {
       
   183             return that.text.compareTo(this.text);
   173         }
   184         }
   174 
   185 
   175         @Override
   186         @Override
   176         public boolean equals(Object other) {
   187         public boolean equals(Object other) {
   177             if(other != null && other instanceof SafePath){
   188             if(other != null && other instanceof SafePath){
   301 
   312 
   302     public static void registerMirror(Class<? extends Event> eventClass) {
   313     public static void registerMirror(Class<? extends Event> eventClass) {
   303         doPrivileged(() ->  MetadataRepository.getInstance().registerMirror(eventClass), new FlightRecorderPermission(Utils.REGISTER_EVENT));
   314         doPrivileged(() ->  MetadataRepository.getInstance().registerMirror(eventClass), new FlightRecorderPermission(Utils.REGISTER_EVENT));
   304     }
   315     }
   305 
   316 
       
   317     public static void setProperty(String propertyName, String value) {
       
   318         doPrivileged(() -> System.setProperty(propertyName, value), new PropertyPermission(propertyName, "write"));
       
   319     }
       
   320 
   306     static boolean getBooleanProperty(String propertyName) {
   321     static boolean getBooleanProperty(String propertyName) {
   307         return doPrivilegedWithReturn(() -> Boolean.getBoolean(propertyName), new PropertyPermission(propertyName, "read"));
   322         return doPrivilegedWithReturn(() -> Boolean.getBoolean(propertyName), new PropertyPermission(propertyName, "read"));
   308     }
   323     }
   309 
   324 
   310     private static SafePath getPathInProperty(String prop, String subPath) {
   325     private static SafePath getPathInProperty(String prop, String subPath) {
   341 
   356 
   342     static void clearDirectory(SafePath safePath) throws IOException {
   357     static void clearDirectory(SafePath safePath) throws IOException {
   343         doPriviligedIO(() -> Files.walkFileTree(safePath.toPath(), new DirectoryCleaner()));
   358         doPriviligedIO(() -> Files.walkFileTree(safePath.toPath(), new DirectoryCleaner()));
   344     }
   359     }
   345 
   360 
   346     static SafePath toRealPath(SafePath safePath) throws Exception {
   361     static SafePath toRealPath(SafePath safePath) throws IOException {
   347         return new SafePath(doPrivilegedIOWithReturn(() -> safePath.toPath().toRealPath()));
   362         return new SafePath(doPrivilegedIOWithReturn(() -> safePath.toPath().toRealPath()));
   348     }
   363     }
   349 
   364 
   350     static boolean existDirectory(SafePath directory) throws IOException {
   365     static boolean existDirectory(SafePath directory) throws IOException {
   351         return doPrivilegedIOWithReturn(() -> Files.exists(directory.toPath()));
   366         return doPrivilegedIOWithReturn(() -> Files.exists(directory.toPath()));
   367         Path p = doPrivilegedIOWithReturn(() -> Files.createDirectories(safePath.toPath()));
   382         Path p = doPrivilegedIOWithReturn(() -> Files.createDirectories(safePath.toPath()));
   368         return new SafePath(p);
   383         return new SafePath(p);
   369     }
   384     }
   370 
   385 
   371     public static boolean exists(SafePath safePath) throws IOException {
   386     public static boolean exists(SafePath safePath) throws IOException {
   372         return doPrivilegedIOWithReturn(() -> Files.exists(safePath.toPath()));
   387         // Files.exist(path) is allocation intensive
       
   388         return doPrivilegedIOWithReturn(() -> safePath.toPath().toFile().exists());
   373     }
   389     }
   374 
   390 
   375     public static boolean isDirectory(SafePath safePath) throws IOException {
   391     public static boolean isDirectory(SafePath safePath) throws IOException {
   376         return doPrivilegedIOWithReturn(() -> Files.isDirectory(safePath.toPath()));
   392         return doPrivilegedIOWithReturn(() -> Files.isDirectory(safePath.toPath()));
   377     }
   393     }
   419     static void ensureClassIsInitialized(Class<?> clazz) {
   435     static void ensureClassIsInitialized(Class<?> clazz) {
   420         unsafe.ensureClassInitialized(clazz);
   436         unsafe.ensureClassInitialized(clazz);
   421     }
   437     }
   422 
   438 
   423     static Class<?> defineClass(Class<?> lookupClass, byte[] bytes) {
   439     static Class<?> defineClass(Class<?> lookupClass, byte[] bytes) {
   424         return AccessController.doPrivileged(new PrivilegedAction<>() {
   440         return AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
   425             @Override
   441             @Override
   426             public Class<?> run() {
   442             public Class<?> run() {
   427                 try {
   443                 try {
   428                     return MethodHandles.privateLookupIn(lookupClass, LOOKUP).defineClass(bytes);
   444                     return MethodHandles.privateLookupIn(lookupClass, LOOKUP).defineClass(bytes);
   429                 } catch (IllegalAccessException e) {
   445                 } catch (IllegalAccessException e) {
   431                 }
   447                 }
   432             }
   448             }
   433         });
   449         });
   434     }
   450     }
   435 
   451 
   436     static Thread createThreadWitNoPermissions(String threadName, Runnable runnable) {
   452     public static Thread createThreadWitNoPermissions(String threadName, Runnable runnable) {
   437         return doPrivilegedWithReturn(() -> new Thread(runnable, threadName), new Permission[0]);
   453         return doPrivilegedWithReturn(() -> new Thread(runnable, threadName), new Permission[0]);
   438     }
   454     }
   439 
   455 
   440     static void setDaemonThread(Thread t, boolean daeomn) {
   456     static void setDaemonThread(Thread t, boolean daeomn) {
   441       doPrivileged(()-> t.setDaemon(daeomn), new RuntimePermission("modifyThread"));
   457       doPrivileged(()-> t.setDaemon(daeomn), new RuntimePermission("modifyThread"));
   442     }
   458     }
   443 
   459 
   444     public static SafePath getAbsolutePath(SafePath path) throws IOException {
   460     public static SafePath getAbsolutePath(SafePath path) throws IOException {
   445         return new SafePath(doPrivilegedIOWithReturn((()-> path.toPath().toAbsolutePath())));
   461         return new SafePath(doPrivilegedIOWithReturn((()-> path.toPath().toAbsolutePath())));
   446     }
   462     }
       
   463 
       
   464     private final static class Privileged extends FileAccess {
       
   465         @Override
       
   466         public RandomAccessFile openRAF(File f, String mode) throws IOException {
       
   467             return doPrivilegedIOWithReturn( () -> new RandomAccessFile(f, mode));
       
   468         }
       
   469 
       
   470         @Override
       
   471         public  DirectoryStream<Path> newDirectoryStream(Path directory)  throws IOException  {
       
   472             return doPrivilegedIOWithReturn( () -> Files.newDirectoryStream(directory));
       
   473         }
       
   474 
       
   475         @Override
       
   476         public  String getAbsolutePath(File f) throws IOException {
       
   477             return doPrivilegedIOWithReturn( () -> f.getAbsolutePath());
       
   478         }
       
   479         @Override
       
   480         public long length(File f) throws IOException {
       
   481             return doPrivilegedIOWithReturn( () -> f.length());
       
   482         }
       
   483 
       
   484         @Override
       
   485         public  long fileSize(Path p) throws IOException {
       
   486             return doPrivilegedIOWithReturn( () -> Files.size(p));
       
   487         }
       
   488     }
       
   489 
       
   490 
   447 }
   491 }