NB-14: Cloning/fetching/pushing remote repositories with Git over SSH disregards cnd.tmpbase
See original GitHub issueApache NetBeans version
Apache NetBeans 14
What happened
In Apache NetBeans
14, Git
-related support for cloning,
fetching from, or pushing to remote repositories is broken,
as outlined below, whenever the temporary-file directory
(/tmp
) is mounted with the noexec
option set.
In prior releases, having cnd.tmpbase
system property
defined, allowed to select a temporary-file directory where
necessary execution would have taken place. It may, as well,
work still, but its coverage seems to slip (junixsocket).
How to reproduce
[P R E L I M I N A R Y S T E P]
Set up the ssh
transport protocol for a target repository
(locally generate public-private key pair, upload the public
key).
Create a new directory that can be read, written, searched
by an Apache NetBeans
process and which can be used by it
for the management of its own temporary files.
Enable keyring-related logging in netbeans/etc/netbeans.conf
:
netbeans_default_options="... -J-Dorg.netbeans.modules.keyring.level=0"
Proceed with the following steps (FAILURE and SUCCESS) in
any order.
[F A I L U R E]
Manually forbid execution of binaries and other executable
files from the /tmp
directory:
sudo mount --options remount,noexec /tmp
mount | grep /tmp
Launch Apache NetBeans
14 with -J-Dcnd.tmpbase=/path/to/new/dir
.
(Substitute the actual path to the newly-created directory
for /path/to/new/dir
.)
Try either cloning or fetching from or pushing to some Git
repository for which the ssh
transport protocol was set.
When CLONING…
Go Team -> Git -> Clone
[Repository URL: git@…]
Check “Private/Public Key”, type in the passphrase, and press the “Next” button. Expect a message written just above the “Next” button:
Cannot connect to repository at git@… .
Press “Cancel” and exit Apache NetBeans
.
In /tmp
(and not in /path/to/new/dir
), verify the presence
of libtmp*libjunixsocket*.so
files (apparently, extracted
from netbeans/ide/modules/ext/junixsocket-native-common-2.4.0.jar
).
View ~/.netbeans/14/var/log/messages.log
.
Look for the keyring provider being used:
FINE [org.netbeans.modules.keyring]: Using provider: org.netbeans.modules.keyring.gnome.libsecret.GnomeLibSecretProvider@xxxxxxxx
Look for the “remote hung up unexpectedly” entries:
INFO [org.netbeans.modules.git]: git@xxxxxxxxxxxxxxxx.git: remote hung up unexpectedly
And right below it:
java.lang.NoClassDefFoundError: Could not initialize class org.newsclub.net.unix.AFUNIXSocketAddress at com.jcraft.jsch.JUnixSocketFactory.connect(JUnixSocketFactory.java:58) at com.jcraft.jsch.SSHAgentConnector.open(SSHAgentConnector.java:78) at com.jcraft.jsch.SSHAgentConnector.isAvailable(SSHAgentConnector.java:69) at com.jcraft.jsch.AgentIdentityRepository.getStatus(AgentIdentityRepository.java:68) at org.netbeans.libs.git.jgit.JGitSshSessionFactory.setupJSchIdentityRepository(JGitSshSessionFactory.java:182) at org.netbeans.libs.git.jgit.JGitSshSessionFactory.setupJSch(JGitSshSessionFactory.java:206) at org.netbeans.libs.git.jgit.JGitSshSessionFactory.getSession(JGitSshSessionFactory.java:103) at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:107) at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:247) Caused: org.eclipse.jgit.errors.TransportException: git@xxxxxxxxxxxxxxxx.git: remote hung up unexpectedly at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:263) at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:137) at org.netbeans.libs.git.jgit.commands.ListRemoteObjectsCommand.runTransportCommand(ListRemoteObjectsCommand.java:51) Caused: org.netbeans.libs.git.GitException: git@xxxxxxxxxxxxxxxx.git: remote hung up unexpectedly at org.netbeans.libs.git.jgit.commands.TransportCommand.handleException(TransportCommand.java:238) at org.netbeans.libs.git.jgit.commands.ListRemoteObjectsCommand.runTransportCommand(ListRemoteObjectsCommand.java:64) at org.netbeans.libs.git.jgit.commands.TransportCommand.run(TransportCommand.java:168) at org.netbeans.libs.git.jgit.commands.GitCommand$1.run(GitCommand.java:57) at org.netbeans.libs.git.jgit.commands.GitCommand$1.run(GitCommand.java:54) at java.base/java.security.AccessController.doPrivileged(AccessController.java:569) at org.netbeans.libs.git.jgit.commands.GitCommand.execute(GitCommand.java:54) at org.netbeans.libs.git.GitClient.listRemoteBranches(GitClient.java:893) at org.netbeans.modules.git.client.GitClient$36.call(GitClient.java:582) at org.netbeans.modules.git.client.GitClient$36.call(GitClient.java:578) at org.openide.util.NetworkSettings.suppressAuthenticationDialog(NetworkSettings.java:138) at org.netbeans.modules.git.client.GitClient$CommandInvoker$1$1.call(GitClient.java:931) at org.netbeans.modules.git.client.GitClient$CommandInvoker$1.call(GitClient.java:956) at org.netbeans.modules.git.client.GitClient$CommandInvoker.runMethodIntern(GitClient.java:968) at org.netbeans.modules.git.client.GitClient$CommandInvoker.runMethod(GitClient.java:897) at org.netbeans.modules.git.client.GitClient$CommandInvoker.runMethod(GitClient.java:875) at org.netbeans.modules.git.client.GitClient$CommandInvoker.access$400(GitClient.java:869) at org.netbeans.modules.git.client.GitClient.listRemoteBranches(GitClient.java:578) [catch] at org.netbeans.modules.git.ui.clone.RepositoryStep$RepositoryStepProgressSupport.perform(RepositoryStep.java:302) at org.netbeans.modules.git.client.GitProgressSupport.performIntern(GitProgressSupport.java:92) at org.netbeans.modules.git.client.GitProgressSupport.run(GitProgressSupport.java:85) at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1418) at org.netbeans.modules.openide.util.GlobalLookup.execute(GlobalLookup.java:45) at org.openide.util.lookup.Lookups.executeWith(Lookups.java:278) at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2033)
Affirm the availability of that not-found class:
cd /path/to/netbeans/14/
jar tf netbeans/ide/modules/ext/junixsocket-common-2.4.0.jar | grep AFUNIXSocketAddress
(Clone the repository with git-clone(1):
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/PRIVATE_KEY
git clone --verbose git@...
Open the (supported) project.)
When FETCHING (or PUSHING)…
(When the project is newly opened, expect a pop-up window,
entitled “Specify Git repository location”, to appear.
Check “Private/Public Key”, type in the passphrase, and
press the “OK” button. And now…)
Expect a pop-up window, entitled “Git Command Failed”, to
appear with an error message (also saved in messages.log
):
git@xxxxxxxxxxxxxxxx.git: remote hung up unexpectedly
Again, as with CLONING, libtmp*libjunixsocket*.so
files
should be abandoned in /tmp
(and not in /path/to/new/dir
).
And a similar (fetching) stack trace shall be written to
~/.netbeans/14/var/log/messages.log
:
java.lang.NoClassDefFoundError: Could not initialize class org.newsclub.net.unix.AFUNIXSocketAddress at com.jcraft.jsch.JUnixSocketFactory.connect(JUnixSocketFactory.java:58) at com.jcraft.jsch.SSHAgentConnector.open(SSHAgentConnector.java:78) at com.jcraft.jsch.SSHAgentConnector.isAvailable(SSHAgentConnector.java:69) at com.jcraft.jsch.AgentIdentityRepository.getStatus(AgentIdentityRepository.java:68) at org.netbeans.libs.git.jgit.JGitSshSessionFactory.setupJSchIdentityRepository(JGitSshSessionFactory.java:182) at org.netbeans.libs.git.jgit.JGitSshSessionFactory.setupJSch(JGitSshSessionFactory.java:206) at org.netbeans.libs.git.jgit.JGitSshSessionFactory.getSession(JGitSshSessionFactory.java:103) at org.eclipse.jgit.transport.SshTransport.getSession(SshTransport.java:107) at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:247) Caused: org.eclipse.jgit.errors.TransportException: git@xxxxxxxxxxxxxxxx.git: remote hung up unexpectedly at org.eclipse.jgit.transport.TransportGitSsh$SshFetchConnection.<init>(TransportGitSsh.java:263) at org.eclipse.jgit.transport.TransportGitSsh.openFetch(TransportGitSsh.java:137) at org.eclipse.jgit.transport.FetchProcess.executeImp(FetchProcess.java:105) at org.eclipse.jgit.transport.FetchProcess.execute(FetchProcess.java:91) at org.eclipse.jgit.transport.Transport.fetch(Transport.java:1260) at org.netbeans.libs.git.jgit.commands.FetchCommand.runTransportCommand(FetchCommand.java:80) Caused: org.netbeans.libs.git.GitException: git@xxxxxxxxxxxxxxxx.git: remote hung up unexpectedly at org.netbeans.libs.git.jgit.commands.TransportCommand.handleException(TransportCommand.java:238) at org.netbeans.libs.git.jgit.commands.FetchCommand.runTransportCommand(FetchCommand.java:98) at org.netbeans.libs.git.jgit.commands.TransportCommand.run(TransportCommand.java:168) at org.netbeans.libs.git.jgit.commands.GitCommand$1.run(GitCommand.java:57) at org.netbeans.libs.git.jgit.commands.GitCommand$1.run(GitCommand.java:54) at java.base/java.security.AccessController.doPrivileged(AccessController.java:569) at org.netbeans.libs.git.jgit.commands.GitCommand.execute(GitCommand.java:54) at org.netbeans.libs.git.GitClient.fetch(GitClient.java:640) at org.netbeans.modules.git.client.GitClient$19.call(GitClient.java:403) at org.netbeans.modules.git.client.GitClient$19.call(GitClient.java:399) at org.openide.util.NetworkSettings.suppressAuthenticationDialog(NetworkSettings.java:138) at org.netbeans.modules.git.client.GitClient$CommandInvoker$1$1.call(GitClient.java:931) at org.netbeans.modules.git.client.GitClient$CommandInvoker$1$1.call(GitClient.java:937) at org.netbeans.modules.git.client.GitClient$CommandInvoker$1.call(GitClient.java:956) at org.netbeans.modules.git.client.GitClient$CommandInvoker.runMethodIntern(GitClient.java:968) at org.netbeans.modules.git.client.GitClient$CommandInvoker.runMethod(GitClient.java:893) at org.netbeans.modules.git.client.GitClient$CommandInvoker.runMethod(GitClient.java:875) at org.netbeans.modules.git.client.GitClient$CommandInvoker.access$400(GitClient.java:869) at org.netbeans.modules.git.client.GitClient.fetch(GitClient.java:399) at org.netbeans.modules.git.ui.fetch.FetchAction.fetchRepeatedly(FetchAction.java:170) [catch] at org.netbeans.modules.git.ui.fetch.FetchAction$3.perform(FetchAction.java:146) at org.netbeans.modules.git.client.GitProgressSupport.performIntern(GitProgressSupport.java:92) at org.netbeans.modules.git.client.GitProgressSupport.run(GitProgressSupport.java:85) at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:1418) at org.netbeans.modules.openide.util.GlobalLookup.execute(GlobalLookup.java:45) at org.openide.util.lookup.Lookups.executeWith(Lookups.java:278) at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:2033)
[S U C C E S S # 1]
Manually permit execution of binaries and other executable
files from the /tmp
directory:
sudo mount --options remount,exec /tmp
mount | grep /tmp
(If present, manually remove stale libtmp*libjunixsocket*.so
files from /tmp
.)
Launch Apache NetBeans
14.
Try fetching from (or pushing to) some Git
repository for
which the ssh
transport protocol was set.
Expect a pop-up window, entitled “Specify Git repository
location”, to appear.
Check “Private/Public Key”, type in the passphrase, and
press the “OK” button.
(There should be neither a new NoClassDefFoundError
logged
entry nor new libtmp*libjunixsocket*.so
files left over in
/tmp
.)
[S U C C E S S # 2]
Manually forbid execution of binaries and other executable
files from the /tmp
directory:
sudo mount --options remount,noexec /tmp
mount | grep /tmp
Launch Apache NetBeans
14 with JUnixSocket
’s property set
-J-Dorg.newsclub.net.unix.library.tmpdir=/path/to/new/dir
,
as the temporary-file directory path. (Substitute the actual
path to the newly-created directory for /path/to/new/dir
.)
Try fetching from (or pushing to) some Git
repository for
which the ssh
transport protocol was set.
Expect a pop-up window, entitled “Specify Git repository
location”, to appear.
Check “Private/Public Key”, type in the passphrase, and
press the “OK” button.
(There should be neither a new NoClassDefFoundError
logged
entry nor new libtmp*libjunixsocket*.so
files left over in
/tmp
.)
Did this work correctly in an earlier version?
Apache NetBeans 13
Operating System
GNU/Linux Debian (testing/bookworm)
JDK
OpenJDK (17.0.3+7-Debian-1)
Apache NetBeans packaging
Apache NetBeans binary zip
Anything else
It may be speculated that all that is needed to resolve this
issue lies in extending cnd.tmpbase
’s coverage by re-using
its value, if any, as the value of the property parsed by
the JUnixSocket
dependency of Apache NetBeans
:
org.newsclub.net.unix.library.tmpdir
.
For example,
class UnifiedBespokeTmpDirTests
{
private static final String PROP_J_UNIX_SOCKET_TMP_DIR =
"org.newsclub.net.unix.library.tmpdir";
private static final String PROP_NET_BEANS_TMP_DIR = "cnd.tmpbase";
// Call it some time before org.newsclub.net.unix.NativeLibraryLoader
// from "junixsocket-common" can be loaded.
static void unifyBespokeTmpDir(boolean dependsOnJUnixSocket)
{
if (!dependsOnJUnixSocket)
return;
final String netBeansTmpDir = System.getProperty(
PROP_NET_BEANS_TMP_DIR);
if (netBeansTmpDir != null)
System.setProperty(PROP_J_UNIX_SOCKET_TMP_DIR,
netBeansTmpDir);
}
public static void main(String[] args)
{
System.setProperty(PROP_NET_BEANS_TMP_DIR, "/foo");
unifyBespokeTmpDir(true);
assert System.getProperty(PROP_J_UNIX_SOCKET_TMP_DIR, "")
.equals(System.getProperty(PROP_NET_BEANS_TMP_DIR));
}
}
Are you willing to submit a pull request?
Yes
Code of Conduct
Yes
Issue Analytics
- State:
- Created a year ago
- Comments:11 (7 by maintainers)
@neilcsmith-net - I looked at 13 and the difference is, that the old git integration used a unix domain socket implementation based on JNA and this is already covered by the same mechanism that is now used to load the junixsocket library after the referenced PR. As we never advertised, that you could run with a noexec temp, this is IMHO not a regression.
So I have a PR ready, that should fix this. PR is referenced, a binary build is available here:
https://doppel-helix.eu/NetBeans-dev-dev-a27179c197747f3f5a3e5031135d856374385bf5-release.zip
I tested with a readonly tmpfs on linux and was able to reproduce the problem (retargetting
java.io.tmpdir
there) and also could verify, that pull works after this change.HOWEVER this needs to be tested on mac OS and of course if there are more linux users willing to test, it would also be appreciated. On windows I assume the putty agent is more common, so it is less interesting there.
The test scenario is this: With this build you should still be able to do a git pull using an SSH based connection, that is authenticated using an SSH agent. This is basicly the whole use-case the unixdomain socket library has in NetBeans (communication with the SSH agent).ssh based git pull, that is authenticated using an ssh agent (that is the whole use case of the existence of the library)
@geertjanw if I remember correctly you are a mac OS user, so it would be great if you could give it a spin.