Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow TorService to be used in a separate process #61

Closed
wants to merge 2 commits into from

Conversation

grote
Copy link
Contributor

@grote grote commented Dec 9, 2021

Running TorService in a separate process has a couple of advantages:

  • when Tor crashes, the app doesn't crash with it
  • Tor can be restarted frequently without crashing (e.g. tor#23847 tor#23848)
  • might improve security

This PR enables that.

Note that this also upgrades jtorctl.

grote added 2 commits December 9, 2021 10:36
…in a dedicated process

This helps with resetting internal Tor state when restarting it, because we can use a new process.
… process dies

This is implemented via an optional intent extra that can be used to pass the PID of the owning process. Then Tor checks every 15min of that process has died and terminates itself if it has.
if (owningProcessPid != -1) {
lines.add("--__OwningControllerProcess");
lines.add(Integer.toString(owningProcessPid));
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is to ensure that Tor doesn't outlive the app (for more than 15sec) if it crashes. Otherwise, it would continue idling on the system (potentially indefinitely) consuming resources.

Copy link
Member

@eighthave eighthave Dec 16, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Android has native mechanisms for ensuring that a Service does not outlive its app. Binding is one of them. TorService works much more in the Android space than tor daemon ever did. This kind of thing seems like a holdover from running tor as a daemon. (If we eliminate the control port socket, then it will be even more in the direction of native Android.)

Copy link
Member

@eighthave eighthave Dec 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I read up a bit on this option, it doesn't seem like something that should be built into TorService because it is about the daemon-style lifecycle and the control port. If it is something you want to use, you can generate your own torrc and TorService will use that file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use this option in Briar to prevent the Tor process from outliving the controller process, which was a recurrent source of bugs for both Briar and Orbot in the past. When owingProcessPid != -1 the controller and Tor library are running in different processes, so that possibility resurfaces.

As far as I know, Android doesn't guarantee that a service will be destroyed if a bound client in another process crashes. The service may be cached, for example. So I don't think it's wise to rely on Android destroying the service.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another quick thought here: when TorService is running as a foreground service (which we're doing in OnionShare because Android gives various power management advantages to foreground services), we've found than simply unbinding is not enough to stop or destroy the service. I don't know whether the same applies when a bound client dies, rather than unbinding, but I think it would at least be worth checking that the service gets destroyed before we stop using __OwningControllerProcess.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we'll want to use WorkManager for OnionShare, as the tasks started by the app are expected to start immediately, not to be scheduled for later execution when some constraints are met.

Those other tasks should be in a Service instance that is separate from TorService. OnionShare could have multiple uploads running at the same time. Each of those would run in an instance of UploadService that is bound to OnionShare's unique TorService. Or there could be a CoordinatorService which manages the notifications and is set as a foreground service.

That's one possible way of structuring things, yes. But it would be nice if the library didn't impose a specific architecture on the application.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WorkManager now considers foreground processing a first class use case: https://www.droidcon.com/2021/11/17/workmanager-back-to-the-foreground/ see at 6:30. WorkManager is clearly the way forward with Tor on Android.

That's one possible way of structuring things, yes. But it would be nice if the library didn't impose a specific architecture on the application.

This library does not impose that kind of architecture, Android does. A central goal of this library is to make Tor behave natively on Android. Android works quite differently than UNIX, Windows, and macOS. Using desktop lifecycle constructs on Android and iOS works quite poorly, that's why this is a goal.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you refer to Expedited work then that is "for tasks that are important to the user and which complete within a few minutes." This not the case for the OnionShare use-case where you might want to leave the share running for more than a day without the fear of yet another system service killing you early.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See also the docs on quotas: https://developer.android.com/topic/libraries/architecture/workmanager/how-to/define-work#quotas

If you want a library to be used, you really shouldn't impose a specific architecture on the application. If you want an easy way to use this with WorkManager, it is fine to add this as an extra wrapper around the general solution.

IMHO even offering only a Service and broadcasts is already going to far into a certain direction.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the link you sent:

While your app is in the foreground, quotas won’t limit the execution of expedited work.

Here's more on using WorkManager for long running services, "Example use-cases for this new feature include bulk uploads or downloads":
https://developer.android.com/topic/libraries/architecture/workmanager/advanced/long-running

(github messed up the threading so this is a repost)

tor-android-binary/build.gradle Show resolved Hide resolved
@eighthave
Copy link
Member

As discussed elsewhere, I think it is quite risky to rely on UNIX domain sockets for IPC here. Android does not official support them, the Java code never included support for them, and the Android team has been locking down all sorts of things. For example, they are blocking reflection entirely in many cases. They are also blocking ioctl and other things. Even if Chromium uses UNIX domain sockets (and not Linux abstract sockets), they might implement a permission needed to get access to them, and then not allow third party apps with that permission into Google Play. The Android team has been breaking functionality in their drive for locking things down.

The Android ways of IPC are:

  • Sending Intent instances to Service and Activity instances.
  • Binder
  • AIDL

AIDL sucks but I think Binder and Intent are both workable here. I had sketched out some stuff using Binder from an app to the TorServices app, and it seemed like a good approach.

@eighthave
Copy link
Member

eighthave commented Dec 16, 2021

Also, I think using UNIX domain sockets between processes will be brittle, and that's one thing I have been focused on improving with TorService. For example, the client will have to be able to handle the case if TorService crashes or gets killed, and the socket goes away. Or maybe the socket stays up but hangs. Binder and Intent both provide tools to handle that kind of stuff.

eighthave added a commit to eighthave/tor-android that referenced this pull request Dec 17, 2021
This unnests the try/finally block that was added in pull guardianproject#59, and moves it
to the main try block, where it now handles the whole shutdown procedure.

* guardianproject#61 (comment)
* guardianproject#57
* guardianproject#59
@akwizgran
Copy link
Contributor

As discussed elsewhere, I think it is quite risky to rely on UNIX domain sockets for IPC here. Android does not official support them, the Java code never included support for them, and the Android team has been locking down all sorts of things.

TorService already uses a Unix domain socket to talk to the Tor library's control port. Do you think it's likely that Unix sockets will continue to be supported for in-process communication while being blocked for inter-process communication (between processes with the same UID)? That seems unlikely to me, but even if it does happen, perhaps we should cross that bridge when we come to it?

syphyr pushed a commit to syphyr/tor that referenced this pull request Dec 17, 2021
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
@eighthave
Copy link
Member

When I implemented the UNIX domain socket hack, I tried first just making the socket, then decided that the hack was the only safe way. I don't remember the details there, it was a while ago. But I do remember that Android seems to be built around Linux abstract sockets, which still use something called a "path" but have no file on the filesystem and no access controls. I still haven't seen something confirming that it is possible to use UNIX domains sockets in Java on the filesystem with access controls without doing a JNI hack. That kind of JNI hack is the kind of thing they are locking down. For example, they already locked down the Java Reflection that would have worked in place of the JNI hack.

There are lots of official Android docs about IPC, sockets are never mentioned. The only Android app I've ever seen that using UNIX domain sockets is Chromium. It has special status in Android and Google, so they get special permissions as needed. Also, it has an elaborate IPC auth system to enforce access controls. A key goal with TorService was getting fast, stable startup. Eliminating the auth helped a lot there.

@akwizgran
Copy link
Contributor

A key goal with TorService was getting fast, stable startup. Eliminating the auth helped a lot there.

Yes, I think using a Unix socket rather than a TCP socket for the control port is a big improvement in that regard.

If I understand right, you'll keep using the JNI approach internally for now, but you'd prefer not to expose it in the API of the library in case it breaks in future and you need to find a new way of connecting to the control port?

That's fine from our side. We've found a way of using LocalSocket to connect to Tor's control port from our own code without JNI. You might be able to use this approach inside the library too. Create a LocalSocketAddress using the path of the control socket and namespace = LocalSocketNamespace.FILESYSTEM, then get its file descriptor and use that to open a FileInputStream and FileOutputStream as before.

This is all documented stuff that's been available since API 1, so I doubt it will change without warning.

So we can remove the part of the patch that exposes the FileDescriptor via the library's API, if you prefer.

@eighthave
Copy link
Member

Did you confirm with a test that there is a file on the filesystem with proper access controls?

@akwizgran
Copy link
Contributor

Yes, this uses the same file as the JNI method.

@eighthave
Copy link
Member

eighthave commented Dec 21, 2021 via email

@akwizgran
Copy link
Contributor

I cannot see why. Service binding is not complex or hard to use. And it is well documented.

It adds complexity because now we need two services: TorService itself, and a second service whose only purpose is to bind to TorService in order to ensure that TorService gets destroyed if the client dies. With __OwningControllerProcess TorService would be responsible for making sure it gets destroyed if the client dies, which seems like a more convenient library to me.

eighthave added a commit to eighthave/tor-android that referenced this pull request Dec 21, 2021
This unnests the try/finally block that was added in pull guardianproject#59, and moves it
to the main try block, where it now handles the whole shutdown procedure.

* guardianproject#61 (comment)
* guardianproject#57
* guardianproject#59
@grote
Copy link
Contributor Author

grote commented Dec 21, 2021

As starting/stopping Tor within the same process is known to cause problems and crashes, I think this library should make it as easy as possible to be run in a dedicated process, even encourage it. Needing another service and cross-process binding isn't exactly the most easy way to achieve this.

@eighthave
Copy link
Member

eighthave commented Dec 21, 2021 via email

@grote
Copy link
Contributor Author

grote commented Dec 21, 2021

Are you still seeing the crashes with 0.4.6.8?

The double close and thread-safety issues have been resolved with 0.4.6.8.

However, when run in process, the random Tor crashes when restarted frequently persist.

Have you tried 0.4.6.9?

Is that even out, yet? i don't see a tag for it.

It does not require another Service to achieve this.

Then how do you suggest to ensure that Tor gets taken down when the app crashes or gets killed? Ideally, the library doesn't allow you to shoot yourself in the foot that easily and take care of such things out of the box.

@eighthave
Copy link
Member

FYI, you can use __OwningControllerProcess now, just do this right before starting TorService:

File torrc = TorService.getTorrc(this);
FileUtils.writeStringToFile(torrc, "__OwningControllerProcess " + android.os.Process.myPid());
// start TorService 

And you can get TorService.getControlSocket() via reflection.

syphyr pushed a commit to syphyr/tor that referenced this pull request Dec 21, 2021
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
@eighthave
Copy link
Member

Then how do you suggest to ensure that Tor gets taken down when the app crashes or gets killed? Ideally, the library doesn't allow you to shoot yourself in the foot that easily and take care of such things out of the box.

I don't understand why Tor must be shutdown in that scenario. If TorService hasn't been killed by Android, then it seems fine to reconnect to it and use it again. Or is reusing it triggering the crashes that you are seeing? Also, Tor provides Dormant Mode for making sure it doesn't stay active when it is not being used. I think it would make sense here. @n8fr8 told me it is used by Orbot via DormantClientTimeout.

If you are using the UNIX domain socket and __OwningControllerProcess works for you, seems fine to use it. I have no experience with it.

v0.4.6.9 is up on Maven Central.

@eighthave
Copy link
Member

eighthave commented Dec 22, 2021 via email

@eighthave
Copy link
Member

Just went through this with @grote, it seems that 0.4.6.9 covers the issues that this merge request was originally intended to address, so I'm closing this. Please open new issues if anything still needs work.

@eighthave eighthave closed this Dec 22, 2021
syphyr pushed a commit to syphyr/tor that referenced this pull request Jan 21, 2022
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
@eighthave
Copy link
Member

eighthave commented Jan 24, 2022 via email

syphyr pushed a commit to syphyr/tor that referenced this pull request Jan 25, 2022
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Feb 4, 2022
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Oct 13, 2023
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
uniqx pushed a commit to uniqx/tor that referenced this pull request Oct 14, 2023
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Nov 3, 2023
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Nov 9, 2023
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
uniqx pushed a commit to uniqx/tor that referenced this pull request Nov 14, 2023
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Dec 8, 2023
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Jan 21, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Jan 30, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Feb 28, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
bitmold pushed a commit to bitmold/tor that referenced this pull request Apr 7, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
bitmold pushed a commit to bitmold/tor that referenced this pull request Apr 7, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
bitmold pushed a commit to bitmold/tor that referenced this pull request Apr 7, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Apr 9, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Apr 10, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Apr 13, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Apr 16, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Apr 29, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request May 2, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
bitmold pushed a commit to bitmold/tor that referenced this pull request May 3, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
uniqx pushed a commit to uniqx/tor that referenced this pull request May 7, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Jun 1, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Jun 6, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Jun 19, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
uniqx pushed a commit to uniqx/tor that referenced this pull request Jul 15, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Aug 6, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Oct 17, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Oct 24, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Oct 31, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
syphyr pushed a commit to syphyr/tor that referenced this pull request Nov 19, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
uniqx pushed a commit to uniqx/tor that referenced this pull request Dec 3, 2024
This is here as an experiment in case it is useful in Java space.  It is
looking like there are better ways to handle the shutdown, so my guess is
that this will not be useful.

* guardianproject/tor-android#59
* guardianproject/tor-android#61 (comment)
* guardianproject/tor-android#57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants