Add single static instance of SpecialPermission (#22726)

This commit adds a SpecialPermission constant and uses that constant
opposed to introducing new instances everywhere.

Additionally, this commit introduces a single static method to check that
the current code has permission. This avoids all the duplicated access
blocks that exist currently.
This commit is contained in:
Tim Brooks 2017-01-21 12:03:52 -06:00 committed by GitHub
parent 3ad6d6ebcc
commit a4ac29c005
21 changed files with 64 additions and 167 deletions

View File

@ -57,6 +57,9 @@ import java.security.BasicPermission;
* </code></pre>
*/
public final class SpecialPermission extends BasicPermission {
public static final SpecialPermission INSTANCE = new SpecialPermission();
/**
* Creates a new SpecialPermision object.
*/
@ -76,4 +79,14 @@ public final class SpecialPermission extends BasicPermission {
public SpecialPermission(String name, String actions) {
this();
}
/**
* Check that the current stack has {@link SpecialPermission} access according to the {@link SecurityManager}.
*/
public static void check() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(INSTANCE);
}
}
}

View File

@ -25,14 +25,18 @@ import java.security.AllPermission;
/** Very simple sanity checks for {@link SpecialPermission} */
public class SpecialPermissionTests extends ESTestCase {
public void testEquals() {
assertEquals(new SpecialPermission(), new SpecialPermission());
assertEquals(SpecialPermission.INSTANCE, new SpecialPermission());
assertFalse(new SpecialPermission().equals(new AllPermission()));
assertFalse(SpecialPermission.INSTANCE.equals(new AllPermission()));
}
public void testImplies() {
assertTrue(new SpecialPermission().implies(new SpecialPermission()));
assertTrue(SpecialPermission.INSTANCE.implies(new SpecialPermission()));
assertTrue(SpecialPermission.INSTANCE.implies(SpecialPermission.INSTANCE));
assertFalse(new SpecialPermission().implies(new AllPermission()));
assertFalse(SpecialPermission.INSTANCE.implies(new AllPermission()));
}
}

View File

@ -78,9 +78,7 @@ public class ExpressionScriptEngineService extends AbstractComponent implements
public Object compile(String scriptName, String scriptSource, Map<String, String> params) {
// classloader created here
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
return AccessController.doPrivileged(new PrivilegedAction<Expression>() {
@Override
public Expression run() {

View File

@ -127,9 +127,6 @@ public final class MustacheScriptEngineService extends AbstractComponent impleme
// Nothing to do here
}
// permission checked before doing crazy reflection
static final SpecialPermission SPECIAL_PERMISSION = new SpecialPermission();
/**
* Used at query execution time by script service in order to execute a query template.
* */
@ -158,10 +155,7 @@ public final class MustacheScriptEngineService extends AbstractComponent impleme
final BytesStreamOutput result = new BytesStreamOutput();
try (UTF8StreamWriter writer = utf8StreamWriter().setOutput(result)) {
// crazy reflection here
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SPECIAL_PERMISSION);
}
SpecialPermission.check();
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
((Mustache) template.compiled()).execute(writer, vars);
return null;

View File

@ -149,11 +149,7 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme
}
// Check we ourselves are not being called by unprivileged code.
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
// Create our loader (which loads compiled code with no permissions).
final Loader loader = AccessController.doPrivileged(new PrivilegedAction<Loader>() {

View File

@ -37,10 +37,7 @@ public class PrivilegedNioServerSocketChannel extends NioServerSocketChannel {
@Override
protected int doReadMessages(List<Object> buf) throws Exception {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
try {
return AccessController.doPrivileged((PrivilegedExceptionAction<Integer>) () -> super.doReadMessages(buf));
} catch (PrivilegedActionException e) {

View File

@ -37,10 +37,7 @@ public class PrivilegedNioSocketChannel extends NioSocketChannel {
@Override
protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
try {
return AccessController.doPrivileged((PrivilegedExceptionAction<Boolean>) () -> super.doConnect(remoteAddress, localAddress));
} catch (PrivilegedActionException e) {

View File

@ -20,9 +20,7 @@
package org.elasticsearch.cloud.azure.classic.management;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ServiceLoader;
@ -31,7 +29,6 @@ import com.microsoft.windowsazure.Configuration;
import com.microsoft.windowsazure.core.Builder;
import com.microsoft.windowsazure.core.DefaultBuilder;
import com.microsoft.windowsazure.core.utils.KeyStoreType;
import com.microsoft.windowsazure.exception.ServiceException;
import com.microsoft.windowsazure.management.compute.ComputeManagementClient;
import com.microsoft.windowsazure.management.compute.ComputeManagementService;
import com.microsoft.windowsazure.management.compute.models.HostedServiceGetDetailedResponse;
@ -43,9 +40,6 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.component.AbstractLifecycleComponent;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
public class AzureComputeServiceImpl extends AbstractLifecycleComponent
implements AzureComputeService {
@ -99,10 +93,7 @@ public class AzureComputeServiceImpl extends AbstractLifecycleComponent
@Override
public HostedServiceGetDetailedResponse getServiceDetails() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
try {
return AccessController.doPrivileged((PrivilegedExceptionAction<HostedServiceGetDetailedResponse>)
() -> client.getHostedServicesOperations().getDetailed(serviceName));

View File

@ -35,17 +35,15 @@ import java.security.PrivilegedExceptionAction;
*/
public final class SocketAccess {
private static final SpecialPermission SPECIAL_PERMISSION = new SpecialPermission();
private SocketAccess() {}
public static <T> T doPrivileged(PrivilegedAction<T> operation) {
checkSpecialPermission();
SpecialPermission.check();
return AccessController.doPrivileged(operation);
}
public static <T> T doPrivilegedIOException(PrivilegedExceptionAction<T> operation) throws IOException {
checkSpecialPermission();
SpecialPermission.check();
try {
return AccessController.doPrivileged(operation);
} catch (PrivilegedActionException e) {
@ -53,10 +51,4 @@ public final class SocketAccess {
}
}
private static void checkSpecialPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SPECIAL_PERMISSION);
}
}
}

View File

@ -71,10 +71,7 @@ public class Ec2DiscoveryPlugin extends Plugin implements DiscoveryPlugin, Close
public static final String EC2 = "ec2";
static {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
// Initializing Jackson requires RuntimePermission accessDeclaredMembers
// The ClientConfiguration class requires RuntimePermission getClassLoader
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {

View File

@ -35,17 +35,15 @@ import java.security.PrivilegedExceptionAction;
*/
public final class Access {
private static final SpecialPermission SPECIAL_PERMISSION = new SpecialPermission();
private Access() {}
public static <T> T doPrivileged(PrivilegedAction<T> operation) {
checkSpecialPermission();
SpecialPermission.check();
return AccessController.doPrivileged(operation);
}
public static void doPrivilegedVoid(DiscoveryRunnable action) {
checkSpecialPermission();
SpecialPermission.check();
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
action.execute();
return null;
@ -53,7 +51,7 @@ public final class Access {
}
public static <T> T doPrivilegedIOException(PrivilegedExceptionAction<T> operation) throws IOException {
checkSpecialPermission();
SpecialPermission.check();
try {
return AccessController.doPrivileged(operation);
} catch (PrivilegedActionException e) {
@ -61,13 +59,6 @@ public final class Access {
}
}
private static void checkSpecialPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SPECIAL_PERMISSION);
}
}
@FunctionalInterface
public interface DiscoveryRunnable {
void execute();

View File

@ -82,18 +82,11 @@ final class TikaImpl {
// only package private for testing!
static String parse(final byte content[], final Metadata metadata, final int limit) throws TikaException, IOException {
// check that its not unprivileged code like a script
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<String>() {
@Override
public String run() throws TikaException, IOException {
return TIKA_INSTANCE.parseToString(new ByteArrayInputStream(content), metadata, limit);
}
}, RESTRICTED_CONTEXT);
return AccessController.doPrivileged((PrivilegedExceptionAction<String>)
() -> TIKA_INSTANCE.parseToString(new ByteArrayInputStream(content), metadata, limit), RESTRICTED_CONTEXT);
} catch (PrivilegedActionException e) {
// checked exception from tika: unbox it
Throwable cause = e.getCause();

View File

@ -139,10 +139,7 @@ public final class GeoIpProcessor extends AbstractProcessor {
}
private Map<String, Object> retrieveCityGeoData(InetAddress ipAddress) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
CityResponse response = AccessController.doPrivileged((PrivilegedAction<CityResponse>) () -> {
try {
return dbReader.city(ipAddress);
@ -217,10 +214,7 @@ public final class GeoIpProcessor extends AbstractProcessor {
}
private Map<String, Object> retrieveCountryGeoData(InetAddress ipAddress) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
CountryResponse response = AccessController.doPrivileged((PrivilegedAction<CountryResponse>) () -> {
try {
return dbReader.country(ipAddress);

View File

@ -36,12 +36,10 @@ import java.security.PrivilegedExceptionAction;
*/
public final class SocketAccess {
private static final SpecialPermission SPECIAL_PERMISSION = new SpecialPermission();
private SocketAccess() {}
public static <T> T doPrivilegedException(PrivilegedExceptionAction<T> operation) throws StorageException, URISyntaxException {
checkSpecialPermission();
SpecialPermission.check();
try {
return AccessController.doPrivileged(operation);
} catch (PrivilegedActionException e) {
@ -50,7 +48,7 @@ public final class SocketAccess {
}
public static void doPrivilegedVoidException(StorageRunnable action) throws StorageException, URISyntaxException {
checkSpecialPermission();
SpecialPermission.check();
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
action.executeCouldThrow();
@ -66,13 +64,6 @@ public final class SocketAccess {
}
}
private static void checkSpecialPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SPECIAL_PERMISSION);
}
}
@FunctionalInterface
public interface StorageRunnable {
void executeCouldThrow() throws StorageException, URISyntaxException;

View File

@ -35,12 +35,10 @@ import java.security.PrivilegedExceptionAction;
*/
public final class SocketAccess {
private static final SpecialPermission SPECIAL_PERMISSION = new SpecialPermission();
private SocketAccess() {}
public static <T> T doPrivilegedIOException(PrivilegedExceptionAction<T> operation) throws IOException {
checkSpecialPermission();
SpecialPermission.check();
try {
return AccessController.doPrivileged(operation);
} catch (PrivilegedActionException e) {
@ -49,7 +47,7 @@ public final class SocketAccess {
}
public static void doPrivilegedVoidIOException(StorageRunnable action) throws IOException {
checkSpecialPermission();
SpecialPermission.check();
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> {
action.executeCouldThrow();
@ -60,13 +58,6 @@ public final class SocketAccess {
}
}
private static void checkSpecialPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SPECIAL_PERMISSION);
}
}
@FunctionalInterface
public interface StorageRunnable {
void executeCouldThrow() throws IOException;

View File

@ -21,7 +21,6 @@ package org.elasticsearch.plugin.repository.gcs;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
@ -40,13 +39,10 @@ import com.google.api.services.storage.model.Bucket;
import com.google.api.services.storage.model.Objects;
import com.google.api.services.storage.model.StorageObject;
import org.elasticsearch.SpecialPermission;
import org.elasticsearch.common.inject.Module;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.env.Environment;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.RepositoryPlugin;
import org.elasticsearch.repositories.RepositoriesModule;
import org.elasticsearch.repositories.Repository;
import org.elasticsearch.repositories.gcs.GoogleCloudStorageRepository;
import org.elasticsearch.repositories.gcs.GoogleCloudStorageService;
@ -64,10 +60,7 @@ public class GoogleCloudStoragePlugin extends Plugin implements RepositoryPlugin
* our plugin permissions don't allow core to "reach through" plugins to
* change the permission. Because that'd be silly.
*/
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
// ClassInfo put in cache all the fields of a given class
// that are annoted with @Key; at the same time it changes

View File

@ -109,7 +109,7 @@ final class HdfsBlobStore implements BlobStore {
}
return path;
}
interface Operation<V> {
V run(FileContext fileContext) throws IOException;
}
@ -121,21 +121,13 @@ final class HdfsBlobStore implements BlobStore {
// 1) hadoop dynamic proxy is messy with access rules
// 2) allow hadoop to add credentials to our Subject
<V> V execute(Operation<V> operation) throws IOException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
// unprivileged code such as scripts do not have SpecialPermission
sm.checkPermission(new SpecialPermission());
}
SpecialPermission.check();
if (closed) {
throw new AlreadyClosedException("HdfsBlobStore is closed: " + this);
}
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<V>() {
@Override
public V run() throws IOException {
return operation.run(fileContext);
}
}, null, new ReflectPermission("suppressAccessChecks"),
return AccessController.doPrivileged((PrivilegedExceptionAction<V>)
() -> operation.run(fileContext), null, new ReflectPermission("suppressAccessChecks"),
new AuthPermission("modifyPrivateCredentials"));
} catch (PrivilegedActionException pae) {
throw (IOException) pae.getException();
@ -146,4 +138,4 @@ final class HdfsBlobStore implements BlobStore {
public void close() {
closed = true;
}
}
}

View File

@ -32,23 +32,14 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.env.Environment;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.RepositoryPlugin;
import org.elasticsearch.repositories.RepositoriesModule;
import org.elasticsearch.repositories.Repository;
public final class HdfsPlugin extends Plugin implements RepositoryPlugin {
// initialize some problematic classes with elevated privileges
static {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
return evilHadoopInit();
}
});
SpecialPermission.check();
AccessController.doPrivileged((PrivilegedAction<Void>) HdfsPlugin::evilHadoopInit);
}
@SuppressForbidden(reason = "Needs a security hack for hadoop on windows, until HADOOP-XXXX is fixed")

View File

@ -95,16 +95,9 @@ public final class HdfsRepository extends BlobStoreRepository {
try {
// initialize our filecontext
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
FileContext fileContext = AccessController.doPrivileged(new PrivilegedAction<FileContext>() {
@Override
public FileContext run() {
return createContext(uri, getMetadata().settings());
}
});
SpecialPermission.check();
FileContext fileContext = AccessController.doPrivileged((PrivilegedAction<FileContext>)
() -> createContext(uri, getMetadata().settings()));
blobStore = new HdfsBlobStore(fileContext, pathSetting, bufferSize);
logger.debug("Using file-system [{}] for URI [{}], path [{}]", fileContext.getDefaultFileSystem(), fileContext.getDefaultFileSystem().getUri(), pathSetting);
} catch (IOException e) {

View File

@ -35,8 +35,6 @@ import java.security.PrivilegedExceptionAction;
*/
public final class SocketAccess {
private static final SpecialPermission SPECIAL_PERMISSION = new SpecialPermission();
private SocketAccess() {}
public static <T> T doPrivileged(PrivilegedAction<T> operation) {
@ -62,10 +60,7 @@ public final class SocketAccess {
}
private static void checkSpecialPermission() {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SPECIAL_PERMISSION);
}
SpecialPermission.check();
}
@FunctionalInterface

View File

@ -45,24 +45,18 @@ import org.elasticsearch.repositories.s3.S3Repository;
public class S3RepositoryPlugin extends Plugin implements RepositoryPlugin {
static {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new SpecialPermission());
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
@Override
public Void run() {
try {
// kick jackson to do some static caching of declared members info
Jackson.jsonNodeOf("{}");
// ClientConfiguration clinit has some classloader problems
// TODO: fix that
Class.forName("com.amazonaws.ClientConfiguration");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return null;
SpecialPermission.check();
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
try {
// kick jackson to do some static caching of declared members info
Jackson.jsonNodeOf("{}");
// ClientConfiguration clinit has some classloader problems
// TODO: fix that
Class.forName("com.amazonaws.ClientConfiguration");
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return null;
});
}