Merged revisions 8299-8320 via svnmerge from
[cacao.git] / src / vm / access.c
1 /* src/vm/access.c - checking access rights
2
3    Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
4    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
5    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
6    J. Wenninger, Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301, USA.
24
25    $Id: access.c 8318 2007-08-16 10:05:34Z michi $
26
27 */
28
29
30 #include "config.h"
31
32 #include <assert.h>
33 #include <string.h>
34
35 #include "vm/types.h"
36
37 #include "mm/memory.h"
38
39 #include "native/llni.h"
40
41 #include "vm/access.h"
42 #include "vm/builtin.h"
43 #include "vm/exceptions.h"
44
45 #include "vm/jit/stacktrace.h"
46
47 #include "vmcore/class.h"
48 #include "vmcore/field.h"
49 #include "vmcore/method.h"
50
51
52 /****************************************************************************/
53 /* ACCESS CHECKS                                                            */
54 /****************************************************************************/
55
56 /* access_is_accessible_class **************************************************
57  
58    Check if a class is accessible from another class
59   
60    IN:
61        referer..........the class containing the reference
62        cls..............the result of resolving the reference
63   
64    RETURN VALUE:
65        true.............access permitted
66        false............access denied
67    
68    NOTE:
69        This function performs the checks listed in section 5.4.4.
70            "Access Control" of "The Java(TM) Virtual Machine Specification,
71            Second Edition".
72
73 *******************************************************************************/
74
75 bool access_is_accessible_class(classinfo *referer, classinfo *cls)
76 {
77         assert(referer);
78         assert(cls);
79
80         /* Public classes are always accessible. */
81
82         if (cls->flags & ACC_PUBLIC)
83                 return true;
84
85         /* A class in the same package is always accessible. */
86
87         if (SAME_PACKAGE(referer, cls))
88                 return true;
89
90 #if defined(WITH_CLASSPATH_SUN)
91         /* Code for Sun's OpenJDK (see
92            hotspot/src/share/vm/runtime/reflection.cpp
93            (Reflection::verify_class_access)): Allow all accesses from
94            sun/reflect/MagicAccessorImpl subclasses to succeed
95            trivially. */
96
97         /* NOTE: This check must be before checks that could return
98            false. */
99
100         if (class_issubclass(cls, class_sun_reflect_MagicAccessorImpl))
101                 return true;
102 #endif
103
104         /* A non-public class in another package is not accessible. */
105
106         return false;
107 }
108
109
110 /* access_is_accessible_member *************************************************
111  
112    Check if a field or method is accessible from a given class
113   
114    IN:
115        referer..........the class containing the reference
116        declarer.........the class declaring the member
117        memberflags......the access flags of the member
118   
119    RETURN VALUE:
120        true.............access permitted
121        false............access denied
122
123    NOTE:
124        This function only performs the checks listed in section 5.4.4.
125            "Access Control" of "The Java(TM) Virtual Machine Specification,
126            Second Edition".
127
128            In particular a special condition for protected access with is
129            part of the verification process according to the spec is not
130            checked in this function.
131    
132 *******************************************************************************/
133
134 bool access_is_accessible_member(classinfo *referer, classinfo *declarer,
135                                                                  s4 memberflags)
136 {
137         assert(referer);
138         assert(declarer);
139
140         /* Public members are accessible. */
141
142         if (memberflags & ACC_PUBLIC)
143                 return true;
144
145 #if defined(WITH_CLASSPATH_SUN)
146         /* Code for Sun's OpenJDK (see
147            hotspot/src/share/vm/runtime/reflection.cpp
148            (Reflection::verify_class_access)): Allow all accesses from
149            sun/reflect/MagicAccessorImpl subclasses to succeed
150            trivially. */
151
152         /* NOTE: This check must be before checks that could return
153            false. */
154
155         if (class_issubclass(declarer, class_sun_reflect_MagicAccessorImpl))
156                 return true;
157 #endif
158
159         /* {declarer is not an interface} */
160
161         /* private members are only accessible by the class itself */
162
163         if (memberflags & ACC_PRIVATE)
164                 return (referer == declarer);
165
166         /* {the member is protected or package private} */
167
168         /* protected and package private members are accessible in the
169            same package */
170
171         if (SAME_PACKAGE(referer, declarer))
172                 return true;
173
174         /* package private members are not accessible outside the package */
175
176         if (!(memberflags & ACC_PROTECTED))
177                 return false;
178
179         /* {the member is protected and declarer is in another package} */
180
181         /* a necessary condition for access is that referer is a subclass
182            of declarer */
183
184         assert((referer->state & CLASS_LINKED) && (declarer->state & CLASS_LINKED));
185
186         if (class_isanysubclass(referer, declarer))
187                 return true;
188
189         return false;
190 }
191
192
193 /* access_check_field **********************************************************
194  
195    Check if the (indirect) caller has access rights to the specified
196    field.
197   
198    IN:
199        f................the field to check
200            calldepth........number of callers to ignore
201                             For example if the stacktrace looks like this:
202
203                                            java.lang.reflect.Method.invokeNative (Native Method)
204                                    [0] java.lang.reflect.Method.invoke (Method.java:329)
205                                    [1] <caller>
206
207                                         you must specify 1 so the access rights of <caller> 
208                                                 are checked.
209   
210    RETURN VALUE:
211        true.............access permitted
212        false............access denied, an exception has been thrown
213    
214 *******************************************************************************/
215
216 bool access_check_field(fieldinfo *f, s4 calldepth)
217 {
218         java_handle_objectarray_t *oa;
219         classinfo                 *callerclass;
220         char                      *msg;
221         s4                         msglen;
222         utf                       *u;
223
224         /* if everything is public, there is nothing to check */
225
226         if ((f->class->flags & ACC_PUBLIC) && (f->flags & ACC_PUBLIC))
227                 return true;
228
229         /* get the caller's class */
230
231         oa = stacktrace_getClassContext();
232
233         if (oa == NULL)
234                 return false;
235
236         assert(calldepth >= 0 && calldepth < LLNI_array_size(oa));
237
238         callerclass = (classinfo *) oa->data[calldepth];
239
240         /* check access rights */
241
242         if (!access_is_accessible_member(callerclass, f->class, f->flags)) {
243                 msglen =
244                         utf_bytes(f->class->name) +
245                         strlen(".") +
246                         utf_bytes(f->name) +
247                         strlen(" not accessible from ") +
248                         utf_bytes(callerclass->name) +
249                         strlen("0");
250
251                 msg = MNEW(char, msglen);
252
253                 utf_copy_classname(msg, f->class->name);
254                 strcat(msg, ".");
255                 utf_cat_classname(msg, f->name);
256                 strcat(msg, " not accessible from ");
257                 utf_cat_classname(msg, callerclass->name);
258
259                 u = utf_new_char(msg);
260
261                 MFREE(msg, char, msglen);
262                 
263                 exceptions_throw_illegalaccessexception(u);
264
265                 return false;
266         }
267
268         /* access granted */
269
270         return true;
271 }
272
273
274 /* access_check_method *********************************************************
275  
276    Check if the (indirect) caller has access rights to the specified
277    method.
278   
279    IN:
280        m................the method to check
281            calldepth........number of callers to ignore
282                             For example if the stacktrace looks like this:
283
284                                            java.lang.reflect.Method.invokeNative (Native Method)
285                                    [0] java.lang.reflect.Method.invoke (Method.java:329)
286                                    [1] <caller>
287
288                                         you must specify 1 so the access rights of <caller> 
289                                                 are checked.
290   
291    RETURN VALUE:
292        true.............access permitted
293        false............access denied, an exception has been thrown
294    
295 *******************************************************************************/
296
297 bool access_check_method(methodinfo *m, s4 calldepth)
298 {
299         java_handle_objectarray_t *oa;
300         classinfo                 *callerclass;
301         char                      *msg;
302         s4                         msglen;
303         utf                       *u;
304
305         /* if everything is public, there is nothing to check */
306
307         if ((m->class->flags & ACC_PUBLIC) && (m->flags & ACC_PUBLIC))
308                 return true;
309
310         /* get the caller's class */
311
312         oa = stacktrace_getClassContext();
313
314         if (oa == NULL)
315                 return false;
316
317         assert(calldepth >= 0 && calldepth < LLNI_array_size(oa));
318
319         callerclass = (classinfo *) oa->data[calldepth];
320
321         /* check access rights */
322
323         if (!access_is_accessible_member(callerclass, m->class, m->flags)) {
324                 msglen =
325                         utf_bytes(m->class->name) +
326                         strlen(".") +
327                         utf_bytes(m->name) +
328                         utf_bytes(m->descriptor) +
329                         strlen(" not accessible from ") +
330                         utf_bytes(callerclass->name) +
331                         strlen("0");
332
333                 msg = MNEW(char, msglen);
334
335                 utf_copy_classname(msg, m->class->name);
336                 strcat(msg, ".");
337                 utf_cat_classname(msg, m->name);
338                 utf_cat_classname(msg, m->descriptor);
339                 strcat(msg, " not accessible from ");
340                 utf_cat_classname(msg, callerclass->name);
341
342                 u = utf_new_char(msg);
343
344                 MFREE(msg, char, msglen);
345                 
346                 exceptions_throw_illegalaccessexception(u);
347
348                 return false;
349         }
350
351         /* access granted */
352
353         return true;
354 }
355
356
357 /*
358  * These are local overrides for various environment variables in Emacs.
359  * Please do not remove this and leave it at the end of the file, where
360  * Emacs will automagically detect them.
361  * ---------------------------------------------------------------------
362  * Local variables:
363  * mode: c
364  * indent-tabs-mode: t
365  * c-basic-offset: 4
366  * tab-width: 4
367  * End:
368  * vim:noexpandtab:sw=4:ts=4:
369  */
370