CACAO
access.cpp
Go to the documentation of this file.
1 /* src/vm/access.c - checking access rights
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <assert.h>
29 #include <string.h>
30 
31 #include "vm/types.hpp"
32 
33 #include "native/llni.hpp"
34 
35 #include "vm/access.hpp"
36 #include "vm/jit/builtin.hpp"
37 #include "vm/class.hpp"
38 #include "vm/exceptions.hpp"
39 #include "vm/field.hpp"
40 #include "vm/globals.hpp"
41 #include "vm/method.hpp"
42 
43 #include "vm/jit/stacktrace.hpp"
44 
45 #include "toolbox/buffer.hpp"
46 
47 /* access_is_accessible_class **************************************************
48 
49  Check if a class is accessible from another class
50 
51  IN:
52  referer..........the class containing the reference
53  cls..............the result of resolving the reference
54 
55  RETURN VALUE:
56  true.............access permitted
57  false............access denied
58 
59  NOTE:
60  This function performs the checks listed in section 5.4.4.
61  "Access Control" of "The Java(TM) Virtual Machine Specification,
62  Second Edition".
63 
64 *******************************************************************************/
65 
67 {
68  assert(referer);
69  assert(cls);
70 
71  /* Public classes are always accessible. */
72 
73  if (cls->flags & ACC_PUBLIC)
74  return true;
75 
76  /* A class in the same package is always accessible. */
77 
78  if (SAME_PACKAGE(referer, cls))
79  return true;
80 
81 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
82  /* Code for Sun's OpenJDK (see
83  hotspot/src/share/vm/runtime/reflection.cpp
84  (Reflection::verify_class_access)): Allow all accesses from
85  sun/reflect/MagicAccessorImpl subclasses to succeed
86  trivially. */
87 
88  /* NOTE: This check must be before checks that could return
89  false. */
90 
91  if (class_issubclass(referer, class_sun_reflect_MagicAccessorImpl))
92  return true;
93 #endif
94 
95  /* A non-public class in another package is not accessible. */
96 
97  return false;
98 }
99 
100 
101 /* access_is_accessible_member *************************************************
102 
103  Check if a field or method is accessible from a given class
104 
105  IN:
106  referer..........the class containing the reference
107  declarer.........the class declaring the member
108  memberflags......the access flags of the member
109 
110  RETURN VALUE:
111  true.............access permitted
112  false............access denied
113 
114  NOTE:
115  This function only performs the checks listed in section 5.4.4.
116  "Access Control" of "The Java(TM) Virtual Machine Specification,
117  Second Edition".
118 
119  In particular a special condition for protected access with is
120  part of the verification process according to the spec is not
121  checked in this function.
122 
123 *******************************************************************************/
124 
126  s4 memberflags)
127 {
128  assert(referer);
129  assert(declarer);
130 
131  /* Public members are accessible. */
132 
133  if (memberflags & ACC_PUBLIC)
134  return true;
135 
136 #if defined(WITH_JAVA_RUNTIME_LIBRARY_OPENJDK)
137  /* Code for Sun's OpenJDK (see
138  hotspot/src/share/vm/runtime/reflection.cpp
139  (Reflection::verify_class_access)): Allow all accesses from
140  sun/reflect/MagicAccessorImpl subclasses to succeed
141  trivially. */
142 
143  /* NOTE: This check must be before checks that could return
144  false. */
145 
146  if (class_issubclass(referer, class_sun_reflect_MagicAccessorImpl))
147  return true;
148 #endif
149 
150  /* {declarer is not an interface} */
151 
152  /* private members are only accessible by the class itself */
153 
154  if (memberflags & ACC_PRIVATE)
155  return (referer == declarer);
156 
157  /* {the member is protected or package private} */
158 
159  /* protected and package private members are accessible in the
160  same package */
161 
162  if (SAME_PACKAGE(referer, declarer))
163  return true;
164 
165  /* package private members are not accessible outside the package */
166 
167  if (!(memberflags & ACC_PROTECTED))
168  return false;
169 
170  /* {the member is protected and declarer is in another package} */
171 
172  /* a necessary condition for access is that referer is a subclass
173  of declarer */
174 
175  assert((referer->state & CLASS_LINKED) && (declarer->state & CLASS_LINKED));
176 
177  if (class_isanysubclass(referer, declarer))
178  return true;
179 
180  return false;
181 }
182 
183 
184 /* access_check_field **********************************************************
185 
186  Check if the (indirect) caller has access rights to the specified
187  field.
188 
189  IN:
190  f................the field to check
191  callerdepth......number of callers to ignore
192  For example if the stacktrace looks like this:
193 
194  [0] java.lang.reflect.Method.invokeNative (Native Method)
195  [1] java.lang.reflect.Method.invoke
196  [2] <caller>
197 
198  you must specify 2 so the access rights of <caller>
199  are checked.
200 
201  RETURN VALUE:
202  true.............access permitted
203  false............access denied, an exception has been thrown
204 
205 *******************************************************************************/
206 
207 #if defined(ENABLE_JAVASE)
208 bool access_check_field(fieldinfo *f, int callerdepth)
209 {
210  classinfo *callerclass;
211 
212  /* If everything is public, there is nothing to check. */
213 
214  if ((f->clazz->flags & ACC_PUBLIC) && (f->flags & ACC_PUBLIC))
215  return true;
216 
217  /* Get the caller's class. */
218 
219  callerclass = stacktrace_get_caller_class(callerdepth);
220 
221  if (callerclass == NULL)
222  return false;
223 
224  /* Check access rights. */
225 
226  if (!access_is_accessible_member(callerclass, f->clazz, f->flags)) {
227  Buffer<> buf;
228 
230  .write('.')
232  .write(" not accessible from ", 21)
233  .write_slash_to_dot(callerclass->name)
234  .utf8_str();
235 
237  return false;
238  }
239 
240  /* access granted */
241 
242  return true;
243 }
244 #endif
245 
246 
247 /* access_check_method *********************************************************
248 
249  Check if the (indirect) caller has access rights to the specified
250  method.
251 
252  IN:
253  m................the method to check
254  callerdepth......number of callers to ignore
255  For example if the stacktrace looks like this:
256 
257  [1] java.lang.reflect.Method.invokeNative (Native Method)
258  [1] java.lang.reflect.Method.invoke
259  [2] <caller>
260 
261  you must specify 2 so the access rights of <caller>
262  are checked.
263 
264  RETURN VALUE:
265  true.............access permitted
266  false............access denied, an exception has been thrown
267 
268 *******************************************************************************/
269 
270 #if defined(ENABLE_JAVASE)
271 bool access_check_method(methodinfo *m, int callerdepth)
272 {
273  classinfo *callerclass;
274 
275  /* If everything is public, there is nothing to check. */
276 
277  if ((m->clazz->flags & ACC_PUBLIC) && (m->flags & ACC_PUBLIC))
278  return true;
279 
280  /* Get the caller's class. */
281 
282  callerclass = stacktrace_get_caller_class(callerdepth);
283 
284  if (callerclass == NULL)
285  return false;
286 
287  /* Check access rights. */
288 
289  if (!access_is_accessible_member(callerclass, m->clazz, m->flags)) {
290  Buffer<> buf(64);
291 
292  buf.write_slash_to_dot(m->clazz->name)
293  .write('.')
296  .write(" not accessible from ", 21)
297  .write_slash_to_dot(callerclass->name);
298 
300  return false;
301  }
302 
303  /* access granted */
304 
305  return true;
306 }
307 
308 #endif
309 
310 /*
311  * These are local overrides for various environment variables in Emacs.
312  * Please do not remove this and leave it at the end of the file, where
313  * Emacs will automagically detect them.
314  * ---------------------------------------------------------------------
315  * Local variables:
316  * mode: c++
317  * indent-tabs-mode: t
318  * c-basic-offset: 4
319  * tab-width: 4
320  * End:
321  * vim:noexpandtab:sw=4:ts=4:
322  */
323 
Utf8String name
Definition: method.hpp:71
Utf8String utf8_str()
get utf-8 string contents of buffer as utf8-string
Definition: buffer.hpp:506
Utf8String name
Definition: field.hpp:61
classinfo * stacktrace_get_caller_class(int depth)
Definition: stacktrace.cpp:784
bool access_is_accessible_member(classinfo *referer, classinfo *declarer, s4 memberflags)
Definition: access.cpp:125
bool access_check_method(methodinfo *m, int callerdepth)
Definition: access.cpp:271
s4 state
Definition: class.hpp:115
Buffer & write_slash_to_dot(const char *)
write to buffer, replacing &#39;/&#39; by &#39;.&#39;
Definition: buffer.hpp:297
#define SAME_PACKAGE(a, b)
Definition: access.hpp:40
Utf8String descriptor
Definition: method.hpp:72
classinfo * clazz
Definition: method.hpp:80
Utf8String name
Definition: class.hpp:91
s4 flags
Definition: field.hpp:59
s4 flags
Definition: class.hpp:90
int32_t s4
Definition: types.hpp:45
bool class_isanysubclass(classinfo *sub, classinfo *super)
Definition: class.cpp:1435
classinfo * clazz
Definition: field.hpp:55
bool class_issubclass(classinfo *sub, classinfo *super)
Definition: class.cpp:1404
void exceptions_throw_illegalaccessexception(Utf8String message)
bool access_check_field(fieldinfo *f, int callerdepth)
Definition: access.cpp:208
Buffer & write(char)
Definition: buffer.hpp:280
s4 flags
Definition: method.hpp:70
bool access_is_accessible_class(classinfo *referer, classinfo *cls)
Definition: access.cpp:66