这是indexloc提供的服务,不要输入任何密码
Skip to content

Commit fe6e3d4

Browse files
Added: Add support for unix filesystem sockets for API communication
Previously in `termux-api.c` in `termux-api-package` version `<= 0.58.0` created abstract namespace sockets. Filesystem sockets are more secure and can allow root processes to communicate with the Termux:API as socket parent directory ownership/permissions is used to grant access instead of socket creator process. >In the Linux implementation, pathname sockets honor the permissions of the directory they are in. Creation of a new socket fails if the process does not have write and search (execute) permission on the directory in which the socket is created. >On Linux, connecting to a stream socket object requires write permission on that socket; sending a datagram to a datagram socket likewise requires write permission on that socket. - https://man7.org/linux/man-pages/man7/unix.7.html
1 parent bab9ef3 commit fe6e3d4

File tree

2 files changed

+58
-13
lines changed

2 files changed

+58
-13
lines changed

app/src/main/java/com/termux/api/apis/SensorAPI.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -388,7 +388,8 @@ public void run() {
388388

389389
try {
390390
try (LocalSocket outputSocket = new LocalSocket()) {
391-
outputSocket.connect(new LocalSocketAddress(this.outputSocketAddress));
391+
outputSocket.connect(ResultReturner.getApiLocalSocketAddress(
392+
ResultReturner.context, "output", this.outputSocketAddress));
392393

393394
try (PrintWriter writer = new PrintWriter(outputSocket.getOutputStream())) {
394395

app/src/main/java/com/termux/api/util/ResultReturner.java

Lines changed: 56 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,17 @@
77
import android.content.BroadcastReceiver.PendingResult;
88
import android.content.Context;
99
import android.content.Intent;
10+
import android.content.pm.ApplicationInfo;
1011
import android.net.LocalSocket;
1112
import android.net.LocalSocketAddress;
13+
import android.net.LocalSocketAddress.Namespace;
1214
import android.os.ParcelFileDescriptor;
1315
import android.util.JsonWriter;
1416

17+
import androidx.annotation.NonNull;
18+
19+
import com.termux.shared.android.PackageUtils;
20+
import com.termux.shared.file.FileUtils;
1521
import com.termux.shared.logger.Logger;
1622
import com.termux.shared.termux.TermuxConstants;
1723
import com.termux.shared.termux.plugins.TermuxPluginUtils;
@@ -23,22 +29,25 @@
2329
import java.io.OutputStream;
2430
import java.io.PrintWriter;
2531
import java.nio.charset.StandardCharsets;
32+
import java.util.ArrayList;
33+
import java.util.Arrays;
34+
import java.util.List;
2635

2736
public abstract class ResultReturner {
2837

2938
@SuppressLint("StaticFieldLeak")
30-
private static Context context;
39+
public static Context context;
3140

3241
private static final String LOG_TAG = "ResultReturner";
3342

3443
/**
35-
* An extra intent parameter which specifies a linux abstract namespace socket address where output from the API
44+
* An extra intent parameter which specifies a unix socket address where output from the API
3645
* call should be written.
3746
*/
3847
private static final String SOCKET_OUTPUT_EXTRA = "socket_output";
3948

4049
/**
41-
* An extra intent parameter which specifies a linux abstract namespace socket address where input to the API call
50+
* An extra intent parameter which specifies a unix socket address where input to the API call
4251
* can be read from.
4352
*/
4453
private static final String SOCKET_INPUT_EXTRA = "socket_input";
@@ -48,7 +57,7 @@ public interface ResultWriter {
4857
}
4958

5059
/**
51-
* Possible subclass of {@link ResultWriter} when input is to be read from stdin.
60+
* Possible subclass of {@link ResultWriter} when input is to be read from {@link #SOCKET_INPUT_EXTRA}.
5261
*/
5362
public static abstract class WithInput implements ResultWriter {
5463
protected InputStream in;
@@ -80,7 +89,7 @@ public final void writeResult(PrintWriter unused) throws Exception {
8089
}
8190

8291
/**
83-
* Possible marker interface for a {@link ResultWriter} when input is to be read from stdin.
92+
* Possible marker interface for a {@link ResultWriter} when input is to be read from {@link #SOCKET_INPUT_EXTRA}.
8493
*/
8594
public static abstract class WithStringInput extends WithInput {
8695
protected String inputString;
@@ -179,6 +188,41 @@ public static void copyIntentExtras(Intent origIntent, Intent newIntent) {
179188

180189
}
181190

191+
/**
192+
* Get {@link LocalSocketAddress} for a socket address.
193+
*
194+
* If socket address starts with a path separator `/`, then a {@link Namespace#FILESYSTEM}
195+
* {@link LocalSocketAddress} is returned, otherwise an {@link Namespace#ABSTRACT}.
196+
*
197+
* The `termux-api-package` versions `<= 0.58.0` create a abstract namespace socket and higher
198+
* version create filesystem path socket.
199+
*
200+
* - https://man7.org/linux/man-pages/man7/unix.7.html
201+
*/
202+
@SuppressLint("SdCardPath")
203+
public static LocalSocketAddress getApiLocalSocketAddress(@NonNull Context context,
204+
@NonNull String socketLabel, @NonNull String socketAddress) {
205+
if (socketAddress.startsWith("/")) {
206+
ApplicationInfo termuxApplicationInfo = PackageUtils.getApplicationInfoForPackage(context,
207+
TermuxConstants.TERMUX_PACKAGE_NAME);
208+
if (termuxApplicationInfo == null) {
209+
throw new RuntimeException("Failed to get ApplicationInfo for the Termux app package: " +
210+
TermuxConstants.TERMUX_PACKAGE_NAME);
211+
}
212+
213+
List<String> termuxAppDataDirectories = Arrays.asList(termuxApplicationInfo.dataDir,
214+
"/data/data/" + TermuxConstants.TERMUX_PACKAGE_NAME);
215+
if (!FileUtils.isPathInDirPaths(socketAddress, termuxAppDataDirectories, true)) {
216+
throw new RuntimeException("The " + socketLabel + " socket address \"" + socketAddress + "\"" +
217+
" is not under Termux app data directories: " + termuxAppDataDirectories);
218+
}
219+
220+
return new LocalSocketAddress(socketAddress, Namespace.FILESYSTEM);
221+
} else {
222+
return new LocalSocketAddress(socketAddress, Namespace.ABSTRACT);
223+
}
224+
}
225+
182226
/**
183227
* Run in a separate thread, unless the context is an IntentService.
184228
*/
@@ -192,11 +236,11 @@ public static void returnData(Object context, final Intent intent, final ResultW
192236
LocalSocket outputSocket = null;
193237
try {
194238
outputSocket = new LocalSocket();
195-
String outputSocketAdress = intent.getStringExtra(SOCKET_OUTPUT_EXTRA);
196-
if (outputSocketAdress == null || outputSocketAdress.isEmpty())
239+
String outputSocketAddress = intent.getStringExtra(SOCKET_OUTPUT_EXTRA);
240+
if (outputSocketAddress == null || outputSocketAddress.isEmpty())
197241
throw new IOException("Missing '" + SOCKET_OUTPUT_EXTRA + "' extra");
198-
Logger.logDebug(LOG_TAG, "Connecting to output socket \"" + outputSocketAdress + "\"");
199-
outputSocket.connect(new LocalSocketAddress(outputSocketAdress));
242+
Logger.logDebug(LOG_TAG, "Connecting to output socket \"" + outputSocketAddress + "\"");
243+
outputSocket.connect(getApiLocalSocketAddress(ResultReturner.context, "output", outputSocketAddress));
200244
writer = new PrintWriter(outputSocket.getOutputStream());
201245

202246
if (resultWriter != null) {
@@ -209,10 +253,10 @@ public static void returnData(Object context, final Intent intent, final ResultW
209253
}
210254
if (resultWriter instanceof WithInput) {
211255
try (LocalSocket inputSocket = new LocalSocket()) {
212-
String inputSocketAdress = intent.getStringExtra(SOCKET_INPUT_EXTRA);
213-
if (inputSocketAdress == null || inputSocketAdress.isEmpty())
256+
String inputSocketAddress = intent.getStringExtra(SOCKET_INPUT_EXTRA);
257+
if (inputSocketAddress == null || inputSocketAddress.isEmpty())
214258
throw new IOException("Missing '" + SOCKET_INPUT_EXTRA + "' extra");
215-
inputSocket.connect(new LocalSocketAddress(inputSocketAdress));
259+
inputSocket.connect(getApiLocalSocketAddress(ResultReturner.context, "input", inputSocketAddress));
216260
((WithInput) resultWriter).setInput(inputSocket.getInputStream());
217261
resultWriter.writeResult(writer);
218262
}

0 commit comments

Comments
 (0)