运行 Jetty9 的 setUID 功能时出现 UnsatisfiedLinkError

UnsatisfiedLinkError when running Jetty9's setUID feature

我刚刚尝试 运行 Jetty 9 作为非 root 用户,使用 setuid 功能绑定低端口号但没有成功。 我在 start.ini 中启用了模块 setuid 并添加了 -Djava.library.path=/opt/jetty/lib/setuid 但是启动 Jetty 时我有以下堆栈跟踪:

2015-06-09 16:27:27.211:WARN:oejx.XmlConfiguration:main: Config error at | | java.lang.reflect.InvocationTargetException in file:/opt/jetty/etc/jetty-setuid.xml java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.eclipse.jetty.start.Main.invokeMain(Main.java:321) at org.eclipse.jetty.start.Main.start(Main.java:817) at org.eclipse.jetty.start.Main.main(Main.java:112) Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.set(XmlConfiguration.java:479) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.configure(XmlConfiguration.java:411) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.newObj(XmlConfiguration.java:815) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.itemValue(XmlConfiguration.java:1125) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.value(XmlConfiguration.java:1030) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.call(XmlConfiguration.java:721) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.configure(XmlConfiguration.java:417) at org.eclipse.jetty.xml.XmlConfiguration$JettyXmlConfiguration.configure(XmlConfiguration.java:354) at org.eclipse.jetty.xml.XmlConfiguration.configure(XmlConfiguration.java:262) at org.eclipse.jetty.xml.XmlConfiguration.run(XmlConfiguration.java:1243) at java.security.AccessController.doPrivileged(Native Method) at org.eclipse.jetty.xml.XmlConfiguration.main(XmlConfiguration.java:1174) ... 7 more Caused by: java.lang.UnsatisfiedLinkError: org.eclipse.jetty.setuid.SetUID.getpwnam(Ljava/lang/String;)Lorg/eclipse/jetty/setuid/Passwd; at org.eclipse.jetty.setuid.SetUID.getpwnam(Native Method) at org.eclipse.jetty.setuid.SetUIDListener.setUsername(SetUIDListener.java:53) ... 23 more

这些是此错误的唯一参考:

但他们要么停止了,要么不显示解决方案。 我为 setuid 包找到的源代码是: https://github.com/jetty-project/codehaus-jetty-project/blob/master/jetty-setuid/modules/java/src/main/java/org/mortbay/setuid/SetUID.java

尽管我不能确定这是我正在使用的版本,但鉴于此版本来自 org.mortbay 包,而 Jetty 9 使用的是 Eclipse 版本。

我尝试在 java args(第一个 try-catch 块)中设置 -Djetty.libsetuid.path,将路径添加到 $PATH 变量或设置 -Djava.library.path(第二次尝试-catch 块)或将 so 复制到 /lib,最后,保持原样(第三个 try-catch 块)。在所有情况下,我都得到了相同的异常堆栈。 我无法确定 Jetty 是找不到 so 文件还是无法加载它,因为如果我删除了对路径的所有引用(我在后面描述的情况),我仍然会收到相同的错误消息。 我使用 Java7 到 运行 Jetty。

编辑 作为测试,我将以下代码片段添加到我的一个 Web 应用程序中,因为如果 Web 应用程序成功,我就会知道问题不在于找到共享对象:

SetUID.setgid(1002);
SetUID.setuid(1002);
Passwd pw = SetUID.getpwuid(1002);
System.setProperty("user.name", pw.getPwName());
System.setProperty("user.home", pw.getPwDir());

结果我有同样的 UnsatisfiedLinkError。

编辑2 相反,我尝试了以下操作:

System.load(SetUID.__FILENAME);
SetUID.setgid(1002);

这让我收到以下错误消息:

javax.servlet.ServletException: java.lang.UnsatisfiedLinkError: Native Library /lib/libsetuid.so already loaded in another classloader

因此,我可以得出结论,至少库已加载。

探索 libsetuid 文件 (nm -D /path/to/the/so),我意识到我使用的 so 已经过时并且与 Jetty 9 不兼容,函数被命名为 mortbay:

root@root:~/# nm -D libsetuid.so --size-sort | less 0000000000000010 T Java_org_mortbay_setuid_SetUID_setgid 0000000000000010 T Java_org_mortbay_setuid_SetUID_setuid 0000000000000015 T Java_org_mortbay_setuid_SetUID_setumask 0000000000000018 T throwNewJavaSecurityException 0000000000000058 T throwNewJavaException 000000000000008e T Java_org_mortbay_setuid_SetUID_setrlimitnofiles 00000000000000a7 T getJavaMethodId 00000000000000f5 T Java_org_mortbay_setuid_SetUID_getrlimitnofiles 0000000000000102 T getJavaFieldInt 0000000000000111 T setJavaFieldInt 0000000000000111 T setJavaFieldLong 0000000000000121 T setJavaFieldString 00000000000001ba T Java_org_mortbay_setuid_SetUID_getpwuid 00000000000001e5 T Java_org_mortbay_setuid_SetUID_getpwnam 000000000000027e T Java_org_mortbay_setuid_SetUID_getgrgid 000000000000029e T Java_org_mortbay_setuid_SetUID_getgrnam

现在,我使用的是码头下载中已有的共享对象,而不是 wiki 中链接的对象。 除此之外,查看 setuid 模块的代码,我决定在我的 java 参数中使用 属性 -Djetty.libsetuid.path 来指示库的绝对路径,例如 -Djetty.libsetuid.path=/opt/jetty/lib/setuid.so