8333344: JMX attaching of Subject does not work when security manager not allowed

Reviewed-by: weijun, dfuchs
This commit is contained in:
Kevin Walls 2024-06-19 16:35:20 +00:00
parent 856931d01f
commit bcf4bb4882
17 changed files with 162 additions and 49 deletions

View File

@ -165,6 +165,7 @@ module java.base {
java.desktop,
java.logging,
java.management,
java.management.rmi,
java.naming,
java.rmi,
jdk.charsets,

View File

@ -46,6 +46,7 @@ import javax.management.*;
import javax.management.remote.JMXServerErrorException;
import javax.management.remote.NotificationResult;
import javax.security.auth.Subject;
import jdk.internal.access.SharedSecrets;
import sun.reflect.misc.ReflectUtil;
import static javax.management.remote.rmi.RMIConnector.Util.cast;
@ -108,14 +109,19 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
this.rmiServer = rmiServer;
this.connectionId = connectionId;
this.defaultClassLoader = defaultClassLoader;
this.subject = subject;
if (subject == null) {
this.acc = null;
} else {
// An authenticated Subject was provided.
// Subject Delegation has been removed.
this.acc = JMXSubjectDomainCombiner.getContext(subject);
if (SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
// SM is allowed. Will use ACC created with Subject:
this.acc = JMXSubjectDomainCombiner.getContext(subject);
} else {
this.acc = null;
}
}
this.mbeanServer = rmiServer.getMBeanServer();
@ -1292,10 +1298,21 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
return getServerNotifFwd().fetchNotifs(csn, t, mn);
}
};
if (acc == null)
return action.run();
else
return AccessController.doPrivileged(action, acc);
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
// Modern case
if (subject == null) {
return action.run();
} else {
return Subject.doAs(subject, action);
}
} else {
// SM permitted
if (acc == null) {
return action.run(); // No Subject or ACC
} else {
return AccessController.doPrivileged(action, acc);
}
}
} finally {
serverCommunicatorAdmin.rspOutgoing();
}
@ -1411,16 +1428,36 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
serverCommunicatorAdmin.reqIncoming();
try {
PrivilegedOperation op = new PrivilegedOperation(operation, params);
if (acc == null) {
try {
return op.run();
} catch (Exception e) {
if (e instanceof RuntimeException)
throw (RuntimeException) e;
throw new PrivilegedActionException(e);
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
// Modern case
if (subject == null) {
try {
return op.run();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new PrivilegedActionException(e);
}
}
} else {
return Subject.doAs(subject, op);
}
} else {
return AccessController.doPrivileged(op, acc);
// SM permitted
if (acc == null) {
try {
return op.run();
} catch (Exception e) {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new PrivilegedActionException(e);
}
}
} else {
return AccessController.doPrivileged(op, acc);
}
}
} catch (Error e) {
throw new JMXServerErrorException(e.toString(),e);
@ -1585,15 +1622,25 @@ public class RMIConnectionImpl implements RMIConnection, Unreferenced {
}
try {
final ClassLoader old = AccessController.doPrivileged(new SetCcl(cl));
try{
if (acc != null) {
return AccessController.doPrivileged(
(PrivilegedExceptionAction<T>) () ->
wrappedClass.cast(mo.get()), acc);
}else{
return wrappedClass.cast(mo.get());
try {
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
// Modern case
if (subject != null) {
return Subject.doAs(subject, (PrivilegedExceptionAction<T>) () -> wrappedClass.cast(mo.get()));
} else {
return wrappedClass.cast(mo.get());
}
} else {
// SM permitted
if (acc != null) {
return AccessController.doPrivileged(
(PrivilegedExceptionAction<T>) () ->
wrappedClass.cast(mo.get()), acc);
} else {
return wrappedClass.cast(mo.get());
}
}
}finally{
} finally {
AccessController.doPrivileged(new SetCcl(old));
}
} catch (PrivilegedActionException pe) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -343,10 +343,9 @@ public class ServerNotifForwarder {
//----------------
// PRIVATE METHODS
//----------------
@SuppressWarnings("removal")
private Subject getSubject() {
return Subject.getSubject(AccessController.getContext());
return Subject.current();
}
private void checkState() throws IOException {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -42,6 +42,7 @@ import java.util.regex.Pattern;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.security.auth.Subject;
import jdk.internal.access.SharedSecrets;
/**
* <p>An object of this class implements the MBeanServerAccessController
@ -300,16 +301,19 @@ public class MBeanServerFileAccessController
}
}
@SuppressWarnings("removal")
private synchronized void checkAccess(AccessType requiredAccess, String arg) {
@SuppressWarnings("removal")
final AccessControlContext acc = AccessController.getContext();
@SuppressWarnings("removal")
final Subject s =
AccessController.doPrivileged(new PrivilegedAction<>() {
public Subject run() {
return Subject.getSubject(acc);
}
Subject s = null;
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
s = Subject.current();
} else {
final AccessControlContext acc = AccessController.getContext();
s = AccessController.doPrivileged(new PrivilegedAction<>() {
public Subject run() {
return Subject.getSubject(acc);
}
});
}
if (s == null) return; /* security has not been enabled */
final Set<Principal> principals = s.getPrincipals();
String newPropertyValue = null;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -60,6 +60,8 @@ import javax.management.MBeanServerConnection;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.security.auth.Subject;
import jdk.internal.access.SharedSecrets;
import static javax.management.monitor.MonitorNotification.*;
/**
@ -169,8 +171,9 @@ public abstract class Monitor
new CopyOnWriteArrayList<>();
/**
* AccessControlContext of the Monitor.start() caller.
* Subject and possibly AccessControlContext of the Monitor.start() caller.
*/
private volatile Subject subject;
@SuppressWarnings("removal")
private static final AccessControlContext noPermissionsACC =
new AccessControlContext(
@ -713,10 +716,14 @@ public abstract class Monitor
//
cleanupIsComplexTypeAttribute();
// Cache the AccessControlContext of the Monitor.start() caller.
// Cache the Subject or AccessControlContext of the Monitor.start() caller.
// The monitor tasks will be executed within this context.
//
acc = AccessController.getContext();
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
subject = Subject.current();
} else {
acc = AccessController.getContext();
}
// Start the scheduler.
//
@ -747,8 +754,9 @@ public abstract class Monitor
//
cleanupFutures();
// Reset the AccessControlContext.
// Reset the Subject and AccessControlContext.
//
subject = null;
acc = noPermissionsACC;
// Reset the complex type attribute information
@ -1512,9 +1520,11 @@ public abstract class Monitor
@SuppressWarnings("removal")
public void run() {
final ScheduledFuture<?> sf;
final Subject s;
final AccessControlContext ac;
synchronized (Monitor.this) {
sf = Monitor.this.schedulerFuture;
s = Monitor.this.subject;
ac = Monitor.this.acc;
}
PrivilegedAction<Void> action = new PrivilegedAction<>() {
@ -1531,10 +1541,20 @@ public abstract class Monitor
return null;
}
};
if (ac == null) {
throw new SecurityException("AccessControlContext cannot be null");
if (!SharedSecrets.getJavaLangAccess().allowSecurityManager()) {
// No SecurityManager permitted:
if (s == null) {
action.run();
} else {
Subject.doAs(s, action);
}
} else {
if (ac == null) {
throw new SecurityException("AccessControlContext cannot be null");
}
// ACC means SM is permitted.
AccessController.doPrivileged(action, ac);
}
AccessController.doPrivileged(action, ac);
synchronized (Monitor.this) {
if (Monitor.this.isActive() &&
Monitor.this.schedulerFuture == sf) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,9 +32,17 @@
*
* @run clean StartStopTest
* @run build StartStopTest
*
* @run main/othervm/timeout=300 StartStopTest 1
* @run main/othervm/timeout=300 StartStopTest 2
* @run main/othervm/timeout=300 StartStopTest 3
* @run main/othervm/timeout=300 -Djava.security.manager=allow StartStopTest 1
* @run main/othervm/timeout=300 -Djava.security.manager=allow StartStopTest 2
* @run main/othervm/timeout=300 -Djava.security.manager=allow StartStopTest 3
* @run main/othervm/timeout=300/policy=all.policy StartStopTest 1
* @run main/othervm/timeout=300/policy=all.policy StartStopTest 2
* @run main/othervm/timeout=300/policy=all.policy StartStopTest 3
*
* @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 1
* @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 2
* @run main/othervm/timeout=300 -Djmx.x.monitor.maximum.pool.size=5 StartStopTest 3

View File

@ -30,13 +30,19 @@
*
* @run clean ThreadPoolAccTest
* @run build ThreadPoolAccTest
*
* @run main/othervm ThreadPoolAccTest
* @run main/othervm -Djava.security.manager=allow ThreadPoolAccTest
* @run main/othervm -Djava.security.manager=allow -DThreadPoolAccTest.useGetSubjectACC=true ThreadPoolAccTest
* @run main/othervm/policy=all.policy ThreadPoolAccTest
* @run main/othervm/policy=all.policy -DThreadPoolAccTest.useGetSubjectACC=true ThreadPoolAccTest
*/
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Date;
import java.util.Set;
import java.util.concurrent.Callable;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.ObjectName;
@ -67,7 +73,9 @@ public class ThreadPoolAccTest {
return "";
}
private void setPrincipal() {
Subject subject = Subject.getSubject(AccessController.getContext());
// Use Subject.current() unless test Property is set.
Subject subject = Boolean.getBoolean("ThreadPoolAccTest.useGetSubjectACC") ?
Subject.getSubject(AccessController.getContext()) : Subject.current();
Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
principal = principals.iterator().next().getName();
}
@ -136,7 +144,9 @@ public class ThreadPoolAccTest {
return null;
}
};
Subject.doAs(subject, action);
// Subject.doAs(subject, action);
Callable<Void> c = (Callable<Void>) () -> action.run();
Subject.callAs(subject, c);
}
sleep(500); // wait for getX method to be called, which calls setPrincipal

View File

@ -0,0 +1,3 @@
grant {
permission java.security.AllPermission;
};

View File

@ -30,6 +30,8 @@
* java.management/com.sun.jmx.remote.security
* @run clean NotificationAccessControllerTest
* @run build NotificationAccessControllerTest
*
* @run main/othervm NotificationAccessControllerTest
* @run main/othervm -Djava.security.manager=allow NotificationAccessControllerTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,7 +31,9 @@
*
* @run clean NotificationEmissionTest
* @run build NotificationEmissionTest
*
* @run main NotificationEmissionTest 1
* @run main/othervm -Djava.security.manager=allow NotificationEmissionTest 1
* @run main/othervm -Djava.security.manager=allow NotificationEmissionTest 2
* @run main/othervm -Djava.security.manager=allow NotificationEmissionTest 3
* @run main/othervm -Djava.security.manager=allow NotificationEmissionTest 4

View File

@ -30,6 +30,7 @@
*
* @run clean NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
* @run build NonJMXPrincipalsTest SimpleStandard SimpleStandardMBean
* @run main/othervm NonJMXPrincipalsTest
* @run main/othervm -Djava.security.manager=allow NonJMXPrincipalsTest
*/

View File

@ -30,6 +30,8 @@
*
* @run clean PasswordAccessFileTest SimpleStandard SimpleStandardMBean
* @run build PasswordAccessFileTest SimpleStandard SimpleStandardMBean
*
* @run main/othervm PasswordAccessFileTest
* @run main/othervm -Djava.security.manager=allow PasswordAccessFileTest
*/

View File

@ -30,7 +30,10 @@
* java.management/com.sun.jmx.remote.security
* @run clean RMIAltAuthTest
* @run build RMIAltAuthTest SimpleStandard SimpleStandardMBean
*
* @run main/othervm RMIAltAuthTest
* @run main/othervm -Djava.security.manager=allow RMIAltAuthTest
* @run main/othervm -Djava.security.manager=allow -DSimpleStandard.useGetSubjectACC=true RMIAltAuthTest
*/
import java.io.File;

View File

@ -30,7 +30,10 @@
* java.management/com.sun.jmx.remote.security
* @run clean RMIPasswdAuthTest
* @run build RMIPasswdAuthTest SimpleStandard SimpleStandardMBean
*
* @run main/othervm RMIPasswdAuthTest
* @run main/othervm -Djava.security.manager=allow RMIPasswdAuthTest
* @run main/othervm -Djava.security.manager=allow -DSimpleStandard.useGetSubjectACC=true RMIPasswdAuthTest
*/
import java.io.File;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -152,8 +152,8 @@ public class SimpleStandard
* type JMXPrincipal and refers to the "monitorRole" identity.
*/
private void checkSubject() {
AccessControlContext acc = AccessController.getContext();
Subject subject = Subject.getSubject(acc);
Subject subject = Boolean.getBoolean("SimpleStandard.useGetSubjectACC") ?
Subject.getSubject(AccessController.getContext()) : Subject.current();
Set principals = subject.getPrincipals();
Principal principal = (Principal) principals.iterator().next();
if (!(principal instanceof JMXPrincipal))

View File

@ -29,9 +29,15 @@
* @modules java.management.rmi
* @library /test/lib
* @compile Simple.java
*
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
* @run main/othervm/timeout=300 -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
*
* @run main/othervm/timeout=300 -Djava.security.manager=allow -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials
* @run main/othervm/timeout=300 -Djava.security.manager=allow -DDEBUG_STANDARD -Dusername=username2 -Dpassword=password2 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedSetException -expectedInvokeException
* @run main/othervm/timeout=300 -Djava.security.manager=allow -DDEBUG_STANDARD -Dusername=username6 -Dpassword=password6 AuthorizationTest -server -mapType x.access.file;x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException
*
* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username1 -Dpassword=password1 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials
* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username3 -Dpassword=password3 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedGetException
* @run main/othervm/timeout=300/policy=java.policy.authorization -DDEBUG_STANDARD -Dusername=username5 -Dpassword=password5 AuthorizationTest -server -mapType x.password.file -populate -client -mapType credentials -expectedCreateException -expectedGetException -expectedSetException -expectedInvokeException

View File

@ -61,6 +61,7 @@ import java.util.Set;
*
* @library /test/lib
*
* @run main/othervm/timeout=300 RmiBootstrapTest .*_test.*.in
* @run main/othervm/timeout=300 -Djava.security.manager=allow RmiBootstrapTest .*_test.*.in
* */
@ -72,6 +73,7 @@ import java.util.Set;
*
* @library /test/lib
*
* @run main/othervm/timeout=300 RmiBootstrapTest .*_ssltest.*.in
* @run main/othervm/timeout=300 -Djava.security.manager=allow RmiBootstrapTest .*_ssltest.*.in
* */