Skip to content

Commit 156ba85

Browse files
authored
J9 Allow attachment as root (#1631)
* Allow attachment as root * Add javadoc for getUserId
1 parent 01ed75b commit 156ba85

File tree

1 file changed

+66
-36
lines changed

1 file changed

+66
-36
lines changed

byte-buddy-agent/src/main/java/net/bytebuddy/agent/VirtualMachine.java

+66-36
Original file line numberDiff line numberDiff line change
@@ -1660,49 +1660,23 @@ protected ForOpenJ9(Socket socket) {
16601660
* @throws IOException If an IO exception occurs during establishing the connection.
16611661
*/
16621662
public static VirtualMachine attach(String processId) throws IOException {
1663-
return attach(processId, false);
1664-
}
1665-
1666-
/**
1667-
* Attaches to the supplied process id using the default JNA implementation.
1668-
*
1669-
* @param processId The process id.
1670-
* @param ignoreUser {@code true} if VM processes that are owned by different users should be considered.
1671-
* @return A suitable virtual machine implementation.
1672-
* @throws IOException If an IO exception occurs during establishing the connection.
1673-
*/
1674-
public static VirtualMachine attach(String processId, boolean ignoreUser) throws IOException {
16751663
return attach(processId, 5000, Platform.isWindows()
16761664
? new Dispatcher.ForJnaWindowsEnvironment()
16771665
: new Dispatcher.ForJnaPosixEnvironment(15, 100, TimeUnit.MILLISECONDS));
16781666
}
16791667

1680-
/**
1681-
* Attaches to the supplied process id. This method will not consider attaching to VMs owned by
1682-
* different users than the current user.
1683-
*
1684-
* @param processId The process id.
1685-
* @param timeout The timeout for establishing the socket connection.
1686-
* @param dispatcher The connector to use to communicate with the target VM.
1687-
* @return A suitable virtual machine implementation.
1688-
* @throws IOException If an IO exception occurs during establishing the connection.
1689-
*/
1690-
public static VirtualMachine attach(String processId, int timeout, Dispatcher dispatcher) throws IOException {
1691-
return attach(processId, timeout, dispatcher, false);
1692-
}
1693-
16941668
/**
16951669
* Attaches to the supplied process id.
16961670
*
16971671
* @param processId The process id.
16981672
* @param timeout The timeout for establishing the socket connection.
16991673
* @param dispatcher The connector to use to communicate with the target VM.
1700-
* @param ignoreUser {@code true} if VM processes that are owned by different users should be considered.
17011674
* @return A suitable virtual machine implementation.
17021675
* @throws IOException If an IO exception occurs during establishing the connection.
17031676
*/
1704-
public static VirtualMachine attach(String processId, int timeout, Dispatcher dispatcher, boolean ignoreUser) throws IOException {
1677+
public static VirtualMachine attach(String processId, int timeout, Dispatcher dispatcher) throws IOException {
17051678
File directory = new File(System.getProperty(IBM_TEMPORARY_FOLDER, dispatcher.getTemporaryFolder(processId)), ".com_ibm_tools_attach");
1679+
long userId = dispatcher.userId();
17061680
RandomAccessFile attachLock = new RandomAccessFile(new File(directory, "_attachlock"), "rw");
17071681
try {
17081682
FileLock attachLockLock = attachLock.getChannel().lock();
@@ -1716,10 +1690,9 @@ public static VirtualMachine attach(String processId, int timeout, Dispatcher di
17161690
if (vmFolder == null) {
17171691
throw new IllegalStateException("No descriptor files found in " + directory);
17181692
}
1719-
long userId = dispatcher.userId();
17201693
virtualMachines = new ArrayList<Properties>();
17211694
for (File aVmFolder : vmFolder) {
1722-
if (aVmFolder.isDirectory() && (ignoreUser || dispatcher.getOwnerIdOf(aVmFolder) == userId)) {
1695+
if (aVmFolder.isDirectory() && isFileOwnedByUid(dispatcher, aVmFolder, userId)) {
17231696
File attachInfo = new File(aVmFolder, "attachInfo");
17241697
if (attachInfo.isFile()) {
17251698
Properties virtualMachine = new Properties();
@@ -1730,12 +1703,7 @@ public static VirtualMachine attach(String processId, int timeout, Dispatcher di
17301703
inputStream.close();
17311704
}
17321705
int targetProcessId = Integer.parseInt(virtualMachine.getProperty("processId"));
1733-
long targetUserId;
1734-
try {
1735-
targetUserId = Long.parseLong(virtualMachine.getProperty("userUid"));
1736-
} catch (NumberFormatException ignored) {
1737-
targetUserId = 0L;
1738-
}
1706+
long targetUserId = getUserId(virtualMachine);
17391707
if (userId != 0L && targetUserId == 0L) {
17401708
targetUserId = dispatcher.getOwnerIdOf(attachInfo);
17411709
}
@@ -1782,10 +1750,14 @@ public static VirtualMachine attach(String processId, int timeout, Dispatcher di
17821750
key = Long.toHexString(SECURE_RANDOM.nextLong());
17831751
}
17841752
File reply = new File(receiver, "replyInfo");
1753+
long targetUserId = getUserId(target);
17851754
try {
17861755
if (reply.createNewFile()) {
17871756
dispatcher.setPermissions(reply, 0600);
17881757
}
1758+
if (0 == userId && 0 != targetUserId) {
1759+
dispatcher.chownFileToTargetUid(reply, targetUserId);
1760+
}
17891761
FileOutputStream outputStream = new FileOutputStream(reply);
17901762
try {
17911763
outputStream.write(key.getBytes("UTF-8"));
@@ -1867,6 +1839,31 @@ public static VirtualMachine attach(String processId, int timeout, Dispatcher di
18671839
}
18681840
}
18691841

1842+
/**
1843+
* Returns the userUid present in the virtualMachine properties file
1844+
* @param virtualMachine Properties of the J9 attachInfo file
1845+
* @return the userUid if it can be parsed, <code>0L</code> otherwise.
1846+
*/
1847+
private static long getUserId(Properties virtualMachine) {
1848+
long targetUserId;
1849+
try {
1850+
targetUserId = Long.parseLong(virtualMachine.getProperty("userUid"));
1851+
} catch (NumberFormatException ignored) {
1852+
targetUserId = 0L;
1853+
}
1854+
return targetUserId;
1855+
}
1856+
1857+
/**
1858+
* Check if the file is owned by the UID. Note that UID 0 "owns" all files.
1859+
* @param aVmFolder File or directory
1860+
* @param userId user UID.
1861+
* @return true if the uid owns the file or uid == 0.
1862+
*/
1863+
private static boolean isFileOwnedByUid(Dispatcher dispatcher, File aVmFolder, long userId) {
1864+
return 0 == userId || dispatcher.getOwnerIdOf(aVmFolder) == userId;
1865+
}
1866+
18701867
/**
18711868
* {@inheritDoc}
18721869
*/
@@ -2077,6 +2074,13 @@ public interface Dispatcher {
20772074
*/
20782075
void decrementSemaphore(File directory, String name, boolean global, int count);
20792076

2077+
/**
2078+
* change the ownership of a file. Can be called only if this process is owned by root.
2079+
* @param path path to the file
2080+
* @param targetUserId effective userid
2081+
*/
2082+
void chownFileToTargetUid(File path, long targetUserId);
2083+
20802084
/**
20812085
* A connector implementation for a POSIX environment using JNA.
20822086
*/
@@ -2214,6 +2218,14 @@ public void decrementSemaphore(File directory, String name, boolean global, int
22142218
notifySemaphore(directory, name, count, (short) -1, (short) (PosixLibrary.SEM_UNDO | PosixLibrary.IPC_NOWAIT), true);
22152219
}
22162220

2221+
/**
2222+
* {@inheritDoc}
2223+
*/
2224+
@Override
2225+
public void chownFileToTargetUid(File file, long targetUserId) {
2226+
library.chown(file.getAbsolutePath(), targetUserId);
2227+
}
2228+
22172229
/**
22182230
* Notifies a POSIX semaphore.
22192231
*
@@ -2319,6 +2331,16 @@ protected interface PosixLibrary extends Library {
23192331
*/
23202332
int chmod(String path, int mode) throws LastErrorException;
23212333

2334+
/**
2335+
* Runs the {@code chown} command.
2336+
*
2337+
* @param path The file path.
2338+
* @param uid The userid to set.
2339+
* @return The return code.
2340+
* @throws LastErrorException If an error occurred.
2341+
*/
2342+
int chown(String path, long uid) throws LastErrorException;
2343+
23222344
/**
23232345
* Runs the {@code ftok} command.
23242346
*
@@ -2502,6 +2524,14 @@ public void decrementSemaphore(File directory, String name, boolean global, int
25022524
}
25032525
}
25042526

2527+
/**
2528+
* {@inheritDoc}
2529+
*/
2530+
@Override
2531+
public void chownFileToTargetUid(File path, long targetUserId) {
2532+
/* do nothing */
2533+
}
2534+
25052535
/**
25062536
* Opens a semaphore for signaling another process that an attachment is performed.
25072537
*

0 commit comments

Comments
 (0)