You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

SecurityActions.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * Javassist, a Java-bytecode translator toolkit.
  3. * Copyright (C) 1999- Shigeru Chiba. All Rights Reserved.
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. Alternatively, the contents of this file may be used under
  8. * the terms of the GNU Lesser General Public License Version 2.1 or later,
  9. * or the Apache License Version 2.0.
  10. *
  11. * Software distributed under the License is distributed on an "AS IS" basis,
  12. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  13. * for the specific language governing rights and limitations under the
  14. * License.
  15. */
  16. package javassist.util.proxy;
  17. import java.lang.invoke.MethodHandle;
  18. import java.lang.invoke.MethodHandles;
  19. import java.lang.reflect.AccessibleObject;
  20. import java.lang.reflect.Constructor;
  21. import java.lang.reflect.Field;
  22. import java.lang.reflect.Method;
  23. import java.security.AccessController;
  24. import java.security.PrivilegedAction;
  25. import java.security.PrivilegedActionException;
  26. import java.security.PrivilegedExceptionAction;
  27. import java.util.ArrayList;
  28. import java.util.Collections;
  29. import java.util.HashMap;
  30. import java.util.List;
  31. import java.util.Map;
  32. import javassist.bytecode.ClassFile;
  33. class SecurityActions extends SecurityManager
  34. {
  35. public static final SecurityActions stack = new SecurityActions();
  36. /**
  37. * Since Java 9 abruptly removed <code>Reflection.getCallerClass()</code>
  38. * in favour of <code>StackWalker</code> we are left having to find a
  39. * solution for the older versions without upsetting the new compiler.
  40. *
  41. * The member scoped function <code>getClassContext()</code>
  42. * available as a <code>SecurityManager</code> sibling remains
  43. * functional across all versions, for now.
  44. *
  45. * @return represents the declaring class of the method that invoked
  46. * the method that called this or index 2 on the stack trace.
  47. * @since 3.23
  48. */
  49. public Class<?> getCallerClass() {
  50. return getClassContext()[2];
  51. }
  52. static Method[] getDeclaredMethods(final Class<?> clazz)
  53. {
  54. if (System.getSecurityManager() == null)
  55. return clazz.getDeclaredMethods();
  56. else {
  57. return AccessController.doPrivileged(
  58. new PrivilegedAction<Method[]>() {
  59. public Method[] run() {
  60. return clazz.getDeclaredMethods();
  61. }
  62. });
  63. }
  64. }
  65. static Constructor<?>[] getDeclaredConstructors(final Class<?> clazz)
  66. {
  67. if (System.getSecurityManager() == null)
  68. return clazz.getDeclaredConstructors();
  69. else {
  70. return AccessController.doPrivileged(
  71. new PrivilegedAction<Constructor<?>[]>() {
  72. public Constructor<?>[] run() {
  73. return clazz.getDeclaredConstructors();
  74. }
  75. });
  76. }
  77. }
  78. static MethodHandle getMethodHandle(final Class<?> clazz, final
  79. String name, final Class<?>[] params) throws NoSuchMethodException
  80. {
  81. try {
  82. return AccessController.doPrivileged(
  83. new PrivilegedExceptionAction<MethodHandle>() {
  84. public MethodHandle run() throws IllegalAccessException,
  85. NoSuchMethodException, SecurityException {
  86. Method rmet = clazz.getDeclaredMethod(name, params);
  87. rmet.setAccessible(true);
  88. MethodHandle meth = MethodHandles.lookup().unreflect(rmet);
  89. rmet.setAccessible(false);
  90. return meth;
  91. }
  92. });
  93. }
  94. catch (PrivilegedActionException e) {
  95. if (e.getCause() instanceof NoSuchMethodException)
  96. throw (NoSuchMethodException) e.getCause();
  97. throw new RuntimeException(e.getCause());
  98. }
  99. }
  100. static Method getDeclaredMethod(final Class<?> clazz, final String name,
  101. final Class<?>[] types) throws NoSuchMethodException
  102. {
  103. if (System.getSecurityManager() == null)
  104. return clazz.getDeclaredMethod(name, types);
  105. else {
  106. try {
  107. return AccessController.doPrivileged(
  108. new PrivilegedExceptionAction<Method>() {
  109. public Method run() throws Exception {
  110. return clazz.getDeclaredMethod(name, types);
  111. }
  112. });
  113. }
  114. catch (PrivilegedActionException e) {
  115. if (e.getCause() instanceof NoSuchMethodException)
  116. throw (NoSuchMethodException) e.getCause();
  117. throw new RuntimeException(e.getCause());
  118. }
  119. }
  120. }
  121. static Constructor<?> getDeclaredConstructor(final Class<?> clazz,
  122. final Class<?>[] types)
  123. throws NoSuchMethodException
  124. {
  125. if (System.getSecurityManager() == null)
  126. return clazz.getDeclaredConstructor(types);
  127. else {
  128. try {
  129. return AccessController.doPrivileged(
  130. new PrivilegedExceptionAction<Constructor<?>>() {
  131. public Constructor<?> run() throws Exception {
  132. return clazz.getDeclaredConstructor(types);
  133. }
  134. });
  135. }
  136. catch (PrivilegedActionException e) {
  137. if (e.getCause() instanceof NoSuchMethodException)
  138. throw (NoSuchMethodException) e.getCause();
  139. throw new RuntimeException(e.getCause());
  140. }
  141. }
  142. }
  143. static void setAccessible(final AccessibleObject ao,
  144. final boolean accessible)
  145. {
  146. if (System.getSecurityManager() == null)
  147. ao.setAccessible(accessible);
  148. else {
  149. AccessController.doPrivileged(new PrivilegedAction<Void>() {
  150. public Void run() {
  151. ao.setAccessible(accessible);
  152. return null;
  153. }
  154. });
  155. }
  156. }
  157. static void set(final Field fld, final Object target, final Object value)
  158. throws IllegalAccessException
  159. {
  160. if (System.getSecurityManager() == null)
  161. fld.set(target, value);
  162. else {
  163. try {
  164. AccessController.doPrivileged(
  165. new PrivilegedExceptionAction<Void>() {
  166. public Void run() throws Exception {
  167. fld.set(target, value);
  168. return null;
  169. }
  170. });
  171. }
  172. catch (PrivilegedActionException e) {
  173. if (e.getCause() instanceof NoSuchMethodException)
  174. throw (IllegalAccessException) e.getCause();
  175. throw new RuntimeException(e.getCause());
  176. }
  177. }
  178. }
  179. static TheUnsafe getSunMiscUnsafeAnonymously() throws ClassNotFoundException
  180. {
  181. try {
  182. return AccessController.doPrivileged(
  183. new PrivilegedExceptionAction<TheUnsafe>() { public TheUnsafe run() throws
  184. ClassNotFoundException, NoSuchFieldException, SecurityException,
  185. IllegalArgumentException, IllegalAccessException {
  186. Class<?> unsafe = Class.forName("sun.misc.Unsafe");
  187. Field theUnsafe = unsafe.getDeclaredField("theUnsafe");
  188. theUnsafe.setAccessible(true);
  189. TheUnsafe usf = stack.new TheUnsafe(unsafe, theUnsafe.get(null));
  190. theUnsafe.setAccessible(false);
  191. disableWarning(usf);
  192. return usf;
  193. }
  194. });
  195. }
  196. catch (PrivilegedActionException e) {
  197. if (e.getCause() instanceof ClassNotFoundException)
  198. throw (ClassNotFoundException) e.getCause();
  199. if (e.getCause() instanceof NoSuchFieldException)
  200. throw new ClassNotFoundException("No such instance.", e.getCause());
  201. if (e.getCause() instanceof IllegalAccessException
  202. || e.getCause() instanceof IllegalAccessException
  203. || e.getCause() instanceof SecurityException)
  204. throw new ClassNotFoundException("Security denied access.", e.getCause());
  205. throw new RuntimeException(e.getCause());
  206. }
  207. }
  208. /**
  209. * _The_ Notorious sun.misc.Unsafe in all its glory, but anonymous
  210. * so as not to attract unwanted attention. Kept in two separate
  211. * parts it manages to avoid detection from linker/compiler/general
  212. * complainers and those. This functionality will vanish from the
  213. * JDK soon but in the meantime it shouldn't be an obstacle.
  214. *
  215. * All exposed methods are cached in a dictionary with overloaded
  216. * methods collected under their corresponding keys. Currently the
  217. * implementation assumes there is only one, if you need find a
  218. * need there will have to be a compare.
  219. * @since 3.23 */
  220. class TheUnsafe
  221. {
  222. final Class<?> unsafe;
  223. final Object theUnsafe;
  224. final Map<String, List<Method>> methods =
  225. new HashMap<String, List<Method>>();
  226. TheUnsafe(Class<?> c, Object o)
  227. {
  228. this.unsafe = c;
  229. this.theUnsafe = o;
  230. for (Method m: unsafe.getDeclaredMethods()) {
  231. if (!methods.containsKey(m.getName())) {
  232. methods.put(m.getName(), Collections.singletonList(m));
  233. continue;
  234. }
  235. if (methods.get(m.getName()).size() == 1)
  236. methods.put(m.getName(),
  237. new ArrayList<Method>(methods.get(m.getName())));
  238. methods.get(m.getName()).add(m);
  239. }
  240. }
  241. private Method getM(String name, Object[] o)
  242. {
  243. return methods.get(name).get(0);
  244. }
  245. public Object call(String name, Object... args)
  246. {
  247. try {
  248. return getM(name, args).invoke(theUnsafe, args);
  249. } catch (Throwable t) {t.printStackTrace();}
  250. return null;
  251. }
  252. }
  253. /**
  254. * Java 9 now complains about every privileged action regardless.
  255. * Displaying warnings of "illegal usage" and then instructing users
  256. * to go hassle the maintainers in order to have it fixed.
  257. * Making it hush for now, see all fixed.
  258. * @param tu theUnsafe that'll fix it */
  259. static void disableWarning(TheUnsafe tu) {
  260. try {
  261. if (ClassFile.MAJOR_VERSION < ClassFile.JAVA_9)
  262. return;
  263. Class<?> cls = Class.forName("jdk.internal.module.IllegalAccessLogger");
  264. Field logger = cls.getDeclaredField("logger");
  265. tu.call("putObjectVolatile", cls, tu.call("staticFieldOffset", logger), null);
  266. } catch (Exception e) { /*swallow*/ }
  267. }
  268. }