1414import com .sun .tools .attach .AttachNotSupportedException ;
1515import com .sun .tools .attach .VirtualMachine ;
1616
17+ import org .elasticsearch .core .CheckedConsumer ;
18+ import org .elasticsearch .core .CheckedSupplier ;
1719import org .elasticsearch .core .SuppressForbidden ;
1820import org .elasticsearch .entitlement .initialization .EntitlementInitialization ;
1921import org .elasticsearch .entitlement .runtime .api .NotEntitledException ;
2224import org .elasticsearch .logging .Logger ;
2325
2426import java .io .IOException ;
27+ import java .lang .reflect .InvocationTargetException ;
2528import java .nio .file .Files ;
2629import java .nio .file .Path ;
30+ import java .nio .file .attribute .FileAttribute ;
2731import java .util .Map ;
2832import java .util .function .Function ;
2933
@@ -144,30 +148,31 @@ private static String findAgentJar() {
144148 * @throws IllegalStateException if the entitlements system can't prevent an unauthorized action of our choosing
145149 */
146150 private static void selfTest () {
147- ensureCannotStartProcess ();
148- ensureCanCreateTempFile ();
151+ ensureCannotStartProcess (ProcessBuilder ::start );
152+ ensureCanCreateTempFile (EntitlementBootstrap ::createTempFile );
153+
154+ // Try again with reflection
155+ ensureCannotStartProcess (EntitlementBootstrap ::reflectiveStartProcess );
156+ ensureCanCreateTempFile (EntitlementBootstrap ::reflectiveCreateTempFile );
149157 }
150158
151- private static void ensureCannotStartProcess () {
159+ private static void ensureCannotStartProcess (CheckedConsumer < ProcessBuilder , ?> startProcess ) {
152160 try {
153161 // The command doesn't matter; it doesn't even need to exist
154- new ProcessBuilder ("" ). start ( );
162+ startProcess . accept ( new ProcessBuilder ("" ));
155163 } catch (NotEntitledException e ) {
156164 logger .debug ("Success: Entitlement protection correctly prevented process creation" );
157165 return ;
158- } catch (IOException e ) {
166+ } catch (Exception e ) {
159167 throw new IllegalStateException ("Failed entitlement protection self-test" , e );
160168 }
161169 throw new IllegalStateException ("Entitlement protection self-test was incorrectly permitted" );
162170 }
163171
164- /**
165- * Originally {@code Security.selfTest}.
166- */
167172 @ SuppressForbidden (reason = "accesses jvm default tempdir as a self-test" )
168- private static void ensureCanCreateTempFile () {
173+ private static void ensureCanCreateTempFile (CheckedSupplier < Path , ?> createTempFile ) {
169174 try {
170- Path p = Files . createTempFile ( null , null );
175+ Path p = createTempFile . get ( );
171176 p .toFile ().deleteOnExit ();
172177
173178 // Make an effort to clean up the file immediately; also, deleteOnExit leaves the file if the JVM exits abnormally.
@@ -184,5 +189,24 @@ private static void ensureCanCreateTempFile() {
184189 logger .debug ("Success: Entitlement protection correctly permitted temp file creation" );
185190 }
186191
192+ @ SuppressForbidden (reason = "accesses jvm default tempdir as a self-test" )
193+ private static Path createTempFile () throws Exception {
194+ return Files .createTempFile (null , null );
195+ }
196+
197+ private static void reflectiveStartProcess (ProcessBuilder pb ) throws Exception {
198+ try {
199+ var start = ProcessBuilder .class .getMethod ("start" );
200+ start .invoke (pb );
201+ } catch (InvocationTargetException e ) {
202+ throw (Exception ) e .getCause ();
203+ }
204+ }
205+
206+ private static Path reflectiveCreateTempFile () throws Exception {
207+ return (Path ) Files .class .getMethod ("createTempFile" , String .class , String .class , FileAttribute [].class )
208+ .invoke (null , null , null , new FileAttribute <?>[0 ]);
209+ }
210+
187211 private static final Logger logger = LogManager .getLogger (EntitlementBootstrap .class );
188212}
0 commit comments