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 } |