xref: /titanic_41/usr/src/uts/common/exec/java/java.c (revision 1d4b38e0077763e7c9b20768eacb841957e787bc)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Launch Java executables via exec(2).
31  *
32  * Java executables are platform-independent executable files
33  * based on the JAR file format.  Executable JAR files contain a
34  * special 'extra field' header in the first file of the archive
35  * that marks the file as a true executable.   The data in that field
36  * is used to pass additional run-time information to the Java VM.
37  *
38  * This handler looks for the appropriate magic number on the
39  * front of the file, checks that the JAR file is executable, then
40  * invokes the Java runtime environment to do the rest of the work.
41  */
42 
43 #include <sys/types.h>
44 #include <sys/proc.h>
45 #include <sys/vnode.h>
46 #include <sys/exec.h>
47 #include <sys/modctl.h>
48 #include <sys/cmn_err.h>
49 #include <sys/pathname.h>
50 
51 /*
52  * These variables can be tweaked via /etc/system to allow prototyping
53  * and debugging.  See PSARC/1997/123.
54  *
55  * Modified by PSARC/1999/012 to be Contract Private between Solaris and
56  * the Java Technology Group.  It is expected that any future change to
57  * these variables be coordinated between the consolidations.
58  */
59 #if defined(__sparc)
60 char *jexec = "/usr/java/jre/lib/sparc/jexec";
61 #elif defined(__i386) || defined(__i386_COMPAT)
62 char *jexec = "/usr/java/jre/lib/i386/jexec";
63 #else
64 #error "Unknown ISA"
65 #endif
66 char *jexec_arg = "-jar";
67 
68 /*
69  * ZIP/JAR file header information
70  */
71 #define	SIGSIZ		4
72 #define	LOCSIG		"PK\003\004"
73 #define	LOCHDRSIZ	30
74 
75 #define	CH(b, n)	(((unsigned char *)(b))[n])
76 #define	SH(b, n)	(CH(b, n) | (CH(b, n+1) << 8))
77 #define	LG(b, n)	(SH(b, n) | (SH(b, n+2) << 16))
78 
79 #define	LOCNAM(b)	(SH(b, 26))	/* filename size */
80 #define	LOCEXT(b)	(SH(b, 28))	/* extra field size */
81 
82 #define	XFHSIZ		4		/* header id, data size */
83 #define	XFHID(b)	(SH(b, 0))	/* extract field header id */
84 #define	XFDATASIZ(b)	(SH(b, 2))	/* extract field data size */
85 #define	XFJAVASIG	0xcafe		/* java executables */
86 
87 /*ARGSUSED3*/
88 static int
89 javaexec(vnode_t *vp, struct execa *uap, struct uarg *args,
90     struct intpdata *idatap, int level, long *execsz, int setid,
91     caddr_t execfile, cred_t *cred)
92 {
93 	struct intpdata idata;
94 	int error;
95 	ssize_t resid;
96 	vnode_t *nvp;
97 	off_t xoff, xoff_end;
98 	char lochdr[LOCHDRSIZ];
99 	struct pathname lookpn;
100 	struct pathname resolvepn;
101 	char *opath;
102 
103 	if (level)
104 		return (ENOEXEC);	/* no recursion */
105 
106 	/*
107 	 * Read in the full local file header, and validate
108 	 * the initial signature.
109 	 */
110 	if ((error = vn_rdwr(UIO_READ, vp, lochdr, sizeof (lochdr),
111 	    0, UIO_SYSSPACE, 0, (rlim64_t)0, cred, &resid)) != 0)
112 		return (error);
113 	if (resid != 0 || strncmp(lochdr, LOCSIG, SIGSIZ) != 0)
114 		return (ENOEXEC);
115 
116 	/*
117 	 * Ok, so this -is- a ZIP file, and might even be a JAR file.
118 	 * Is it a Java executable?
119 	 */
120 	xoff = sizeof (lochdr) + LOCNAM(lochdr);
121 	xoff_end = xoff + LOCEXT(lochdr);
122 
123 	while (xoff < xoff_end) {
124 		char xfhdr[XFHSIZ];
125 
126 		if ((error = vn_rdwr(UIO_READ, vp, xfhdr, sizeof (xfhdr),
127 		    xoff, UIO_SYSSPACE, 0, (rlim64_t)0, cred, &resid)) != 0)
128 			return (error);
129 		if (resid != 0)
130 			return (ENOEXEC);
131 		if (XFHID(xfhdr) == XFJAVASIG)
132 			break;
133 		xoff += sizeof (xfhdr) + XFDATASIZ(xfhdr);
134 	}
135 
136 	if (xoff >= xoff_end)
137 		return (ENOEXEC);
138 
139 	/*
140 	 * Note: If we ever make setid execution work, we need to ensure
141 	 * that we use /dev/fd to avoid the classic setuid shell script
142 	 * security hole.
143 	 */
144 	if (setid)
145 		return (EACCES);
146 
147 	/*
148 	 * Find and invoke the Java runtime environment on the file
149 	 */
150 	idata.intp = NULL;
151 	idata.intp_name = jexec;
152 	idata.intp_arg = jexec_arg;
153 	if (error = pn_get(idata.intp_name, UIO_SYSSPACE, &lookpn))
154 		return (error);
155 	pn_alloc(&resolvepn);
156 	if (error = lookuppn(&lookpn, &resolvepn, FOLLOW, NULLVPP, &nvp)) {
157 		pn_free(&resolvepn);
158 		pn_free(&lookpn);
159 		return (ENOEXEC);
160 	}
161 	opath = args->pathname;
162 	args->pathname = resolvepn.pn_path;
163 	/* don't free resolvepn until we are done with args */
164 	pn_free(&lookpn);
165 	error = gexec(&nvp,
166 		uap, args, &idata, level + 1, execsz, execfile, cred);
167 	VN_RELE(nvp);
168 	args->pathname = opath;
169 	pn_free(&resolvepn);
170 	return (error);
171 }
172 
173 static struct execsw jexecsw = {
174 	javamagicstr,
175 	0,
176 	4,
177 	javaexec,
178 	NULL
179 };
180 
181 static struct modlexec jmodlexec = {
182 	&mod_execops, "exec for Java", &jexecsw
183 };
184 
185 static struct modlinkage jmodlinkage = {
186 	MODREV_1, &jmodlexec, NULL
187 };
188 
189 int
190 _init(void)
191 {
192 	return (mod_install(&jmodlinkage));
193 }
194 
195 int
196 _fini(void)
197 {
198 	return (mod_remove(&jmodlinkage));
199 }
200 
201 int
202 _info(struct modinfo *modinfop)
203 {
204 	return (mod_info(&jmodlinkage, modinfop));
205 }
206