- Saved searches
- Use saved searches to filter your results more quickly
- License
- dyorgio/run-as-root
- Name already in use
- Sign In Required
- Launching GitHub Desktop
- Launching GitHub Desktop
- Launching Xcode
- Launching Visual Studio Code
- Latest commit
- Git stats
- Files
- README.md
- About
- Cheesy bits and bobs
- Xamarin and Java Processes (root)
- Linux Processes
- Starting a Process On Android
- Reading From The Process
- Running a Process as Root
- Reading Large Files
- Convenience Helper Method
- Есть ли способ для приложения Java получить права root?
Saved searches
Use saved searches to filter your results more quickly
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.
A java library to run pieces of code as root.
License
dyorgio/run-as-root
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Sign In Required
Please sign in to use Codespaces.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching GitHub Desktop
If nothing happens, download GitHub Desktop and try again.
Launching Xcode
If nothing happens, download Xcode and try again.
Launching Visual Studio Code
Your codespace will open once ready.
There was a problem preparing your codespace, please try again.
Latest commit
Git stats
Files
Failed to load latest commit information.
README.md
A java library to run pieces of code as root using native root password input dialog.
A new JVM is created in every execution and destroyed after completion.
This library uses Out Process to create new JVMs.
- Ask user for credentials in Windows, Linux and macOS.
- Do privileged actions.
- Limit scope of root code execution.
- Upgrade permissions during runtime temporarily.
// Specify JVM options (optional) RootExecutor rootExecutor = new RootExecutor("-Xmx64m"); // Execute privileged action without return rootExecutor.run(() -> < // Call your admin code here. >)); // Execute privileged action with return Object value = rootExecutor.call(() -> < // Call your admin code with return here. return null; >)); System.out.println(value);
- Init simple, after include this lib in your project just try to write a file in a protected folder to validate if it is working.
- Avoid big classpaths, it can be a problem in Windows. #8
dependency> groupId>com.github.dyorgio.runtimegroupId> artifactId>run-as-rootartifactId> version>1.2.3version> dependency>
About
A java library to run pieces of code as root.
Cheesy bits and bobs
A blog about cross-platform mobile app development and other programming related things. Written by Mastodon.
Xamarin and Java Processes (root)
I have seen this question pop up from time to time, where someone asks how to run a native process on Android. This is usually because they want to run something with root permissions, which could allow you to do various things, such as reading files you are usually not allowed. This could be reading VPN state from /data/misc/vpn/state . Blocking Advertisements by adding domains to /etc/hosts and much more.
This blog post will show you how to start a Java process and read the exit code, and the output from the process.
Note: If you want to try this yourself, you will need to have a rooted device. I like to run LineageOS on my devices. They support a large amount of popular devices. On LineageOS you can install SU by grabbing it from the Extras web page and flashing using your recovery. This is up to the reader to do.
Linux Processes
Linux is the operating system Android is based on. A standard process on Linux will use
- stdin to read input from the console (i.e. keyboard)
- stdout to write to the console
- stderr to write errors to the console
These are in fact file handles to /proc//fd/ , where is your process id and 0, 1, 2 are stdin, stdout, stderr respectively. You should not worry about this as this is usually handled by the OS.
A process has an exit code. 0 means everything was OK, anything else than 0 means it probably failed.
Starting a Process On Android
On Android you can start a native Process using with Java.Lang.Runtime.GetRuntime().Exec() , which will return a Java.Lang.Process . Alternatively (also preferred way) if you need more control you can use Java.Lang.ProcessBuilder , which allows you to redirect stdin, stdout, stderr. Its Start() method, similarly to Exec() gives you a Java.Lang.Process . This object reflects the Linux process and has streams for stdin, stdout and stderr. These are our way into reading what the process writes out.
Xamarin has some nice helpers for us in the Java.Lang.Process they expose. Instead of blocking when we want to wait for the process to finish, they have added WaitForAsync() , which is very nice. Also the streams for stdin, stdout and stderr are nice C# Streams that you can read and write to very easily. Namely InputStream , OutputStream and ErrorStream .
var builder = new ProcessBuilder("echo", "hello"); var process = builder.Start(); var exitCode = await process.WaitForAsync();
The example above runs the echo command, which just echoes what follows after. In this case “hello”. The WaitForAsync() method returns us a Task with the exit code of the process.
Keep in mind that WaitForAsync() also can throw exceptions such as IOException and SecurityException depending on what you are doing.
Reading From The Process
When we start a Process, it should be considered that we start a process and execute some commands that redirect into this Process. Meaning most of the time, when we want to read the result from the commands we run, we will actually need to read from InputStream , rather than OutputStream which would be the usual stdout. However, since our Process is the one starting other Processes, then their output stream gets redirected into our input stream.
Anyways, reading the stream is super easy.
using (var outputStreamReader = new StreamReader(process.InputStream)) var output = await outputStreamReader.ReadToEndAsync(); >
Bingo! If we ran this on the echo hello process we created further up, output would be hello in this case. Neat!
Running a Process as Root
Running a process as root is super easy. Just add su and -c to the commands you execute as follows.
var builder = new ProcessBuilder("su", "-c", "echo hello");
-c means that the root process su (super user aka. root) should run a specific command. Notice that echo and hello became one argument. This is because we are redirecting into su ’s stdin. Apart from that everything else stays the same.
Most Android OS’s with root, will show a dialog when root is requested.
Reading Large Files
Reading large files by using cat to our Process stdin might be inefficient. You could consider using the ProcessBuilder to redirect the stdin directly to a file at a destination you have better access to.
var myFile = new File("/some/path"); builder.RedirectInput(myFile);
Alternatively you could do the same with the InputStream and read it to a file.
using (var inputStream = process.InputStream) using (var fileStream = File.Create("/some/path")) await inputStream.CopyToAsync(fileStream); >
Convenience Helper Method
Here is a little helper method for running simple commands and getting their result.
async Task<(int exitCode, string result)> RunCommand(params string[] command) string result = null; var exitCode = -1; try var builder = new ProcessBuilder(command); var process = builder.Start(); exitCode = await process.WaitForAsync(); if (exitCode == 0) using (var inputStreamReader = new StreamReader(process.InputStream)) result = await inputStreamReader.ReadToEndAsync(); > > else if (process.ErrorStream != null) using (var errorStreamReader = new StreamReader(process.ErrorStream)) var error = await errorStreamReader.ReadToEndAsync(); result = $"Error error>"; > > > catch (IOException ex) result = $"Exception ex.Message>"; > return (exitCode, result); >
Usage would be something like.
var (exitCode, result) = await RunCommand("su", "-c", "cat /data/misc/vpn/state");
This would return with the exitCode 0 if everything went well, and the string result would contain something like.
ppp0 10.0.0.42/32 0.0.0.0/0 109.226.17.2 144.117.5.51
Nice! Now you should be an expert in native processes and how to launch them from your Android App. It is up to you the reader as an exercise to figure out how OutputStream works. Enjoy!
Есть ли способ для приложения Java получить права root?
При запуске Files.walk(Paths.get(«/var/»)).count() в качестве непривилегированного пользователя выполнение может вызвать исключение, так как есть папки внутри /var/ , для которых требуется разрешение root. Я не ищет способ выполнить команду bash как root (например, sudo find /var ), используя Process и т.д. Я просто хочу убедиться, что Files.walk(Paths.get(«/var/»)).count() не выбрасывает AccessDeniedException :
Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException at sun.reflect.NativeMethodAccessorImpl.invoke0 at sun.reflect.NativeMethodAccessorImpl.invoke at sun.reflect.DelegatingMethodAccessorImpl.invoke at java.lang.reflect.Method.invoke at org.springframework.boot.devtools.restart.RestartLauncher.run Caused by: java.io.UncheckedIOException: java.nio.file.AccessDeniedException: /var/cache/httpd at java.nio.file.FileTreeIterator.fetchNextIfNeeded at java.nio.file.FileTreeIterator.hasNext at java.util.Iterator.forEachRemaining at java.util.Spliterators$IteratorSpliterator.forEachRemaining at java.util.stream.AbstractPipeline.copyInto at java.util.stream.AbstractPipeline.wrapAndCopyInto at java.util.stream.ReduceOps$ReduceOp.evaluateSequential at java.util.stream.AbstractPipeline.evaluate at java.util.stream.LongPipeline.reduce at java.util.stream.LongPipeline.sum at java.util.stream.ReferencePipeline.count at com.example.DemoApplication.main . 5 more Caused by: java.nio.file.AccessDeniedException: /var/cache/httpd at sun.nio.fs.UnixException.translateToIOException at sun.nio.fs.UnixException.rethrowAsIOException at sun.nio.fs.UnixException.rethrowAsIOException at sun.nio.fs.UnixFileSystemProvider.newDirectoryStream at java.nio.file.Files.newDirectoryStream at java.nio.file.FileTreeWalker.visit at java.nio.file.FileTreeWalker.next at java.nio.file.FileTreeIterator.fetchNextIfNeeded
Это просто пример. Используя filter(. ) , можно обойти исключение. Но этот пример можно расширить и в других случаях использования. Итак, возможно ли это вообще, для приложений CLI, JavaFX и т.д., чтобы получить права root после того, как они были выполнены из командной строки с помощью метода, такого как java -jar app.jar ?
Если бы это было возможно, то это было бы серьезной проблемой безопасности . Представьте, что приложение получает root-доступ и выполняет rm -rf / . OOOPS.
Приложение может открыть диалоговое окно и попросить пользователя ввести пароль sudo / root. Многие родные приложения уже имеют эту возможность. Например, Gnome Software, Disk Utility и др. ОООPS. 😉
Я думаю, что общий подход состоит в том, чтобы получить информацию для входа в систему администратора / root, а затем порождать отдельный процесс от имени этого пользователя, и этот отдельный процесс выполняет свою работу. Возможно, вам придется делать это по-разному на каждой платформе. Я не знаю, есть ли кроссплатформенный фреймворк, который справится с этим для вас (и, как вы, наверное, знаете, запрос на один будет OT на SO). Например, смотрите здесь для ответа Windows.
Понимаю. Я только что заметил, что Gnome (Fedora) Disk Usage Analyzer не просматривает эти каталоги, если он не выполняется с использованием sudo . Он может попросить пользователя ввести пароль перед сканированием папки, но эта функция еще не существует. В любом случае, спасибо за объяснение. Это (ГКСУ и т. Д.) Также может помочь.
Будьте честны и просите sudo выполнить ваше приложение. Все пользователи Linux предпочтут этот подход
@Arkadiy нет, я начал щедрость именно для того, чтобы пролить свет на идею получения разрешений во время выполнения (возможно или нет)
@Arkadly Arkadly Я не хочу получить доступ к этим папкам нечестно :)) Я хочу получить доступ к этим папкам независимым от платформы способом. И нет, мне нужно иметь доступ к этим расположениям, а не игнорировать их, потому что я хочу создать древовидную структуру, размер всех файлов и т. Д. (Например, анализатор использования дисков) и показать его пользователю. Сказав, что в DUA мало возможностей и сложности, в отличие от других приложений, он не позволяет получить root-доступ во время выполнения.
Что мне приходит в голову, это рутированный телефон Android (ядро Linux + Java) (который просто имеет su / sudo в вашем каталоге sbin) и приложение, которому требуется root-доступ. Я не разработчик Android, но насколько я знаю, он выполняет привилегированные команды, выполняя su из Java-кода, используя Process так что, похоже, это единственный способ, но вы упомянули, что это не то, что вы ищете.